mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-11-19 02:47:18 +01:00
VoxelBlock is no longer a Reference
This commit is contained in:
parent
cefa371d83
commit
d3ab015c67
@ -1,23 +1,9 @@
|
||||
#include "voxel_map.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
VoxelMap::VoxelMap() : _last_accessed_block(NULL) {
|
||||
for (unsigned int i = 0; i < VoxelBuffer::MAX_CHANNELS; ++i) {
|
||||
_default_voxel[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VoxelMap::~VoxelMap() {
|
||||
|
||||
}
|
||||
|
||||
int VoxelMap::get_voxel(Vector3i pos, unsigned int c) {
|
||||
Vector3i bpos = voxel_to_block(pos);
|
||||
VoxelBlock * block = get_block(bpos);
|
||||
if (block == NULL) {
|
||||
return _default_voxel[c];
|
||||
}
|
||||
return block->voxels->get_voxel(pos - block_to_voxel(bpos), c);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
// VoxelBlock
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
MeshInstance * VoxelBlock::get_mesh_instance(const Node & root) {
|
||||
if (mesh_instance_path.is_empty())
|
||||
@ -28,10 +14,6 @@ MeshInstance * VoxelBlock::get_mesh_instance(const Node & root) {
|
||||
return n->cast_to<MeshInstance>();
|
||||
}
|
||||
|
||||
VoxelBlock::~VoxelBlock() {
|
||||
|
||||
}
|
||||
|
||||
// Helper
|
||||
VoxelBlock * VoxelBlock::create(Vector3i bpos, VoxelBuffer * buffer) {
|
||||
VoxelBlock * block = memnew(VoxelBlock);
|
||||
@ -49,6 +31,32 @@ VoxelBlock * VoxelBlock::create(Vector3i bpos, VoxelBuffer * buffer) {
|
||||
return block;
|
||||
}
|
||||
|
||||
VoxelBlock::VoxelBlock(): voxels(NULL) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// VoxelMap
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VoxelMap::VoxelMap() : _last_accessed_block(NULL) {
|
||||
for (unsigned int i = 0; i < VoxelBuffer::MAX_CHANNELS; ++i) {
|
||||
_default_voxel[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VoxelMap::~VoxelMap() {
|
||||
clear();
|
||||
}
|
||||
|
||||
int VoxelMap::get_voxel(Vector3i pos, unsigned int c) {
|
||||
Vector3i bpos = voxel_to_block(pos);
|
||||
VoxelBlock * block = get_block(bpos);
|
||||
if (block == NULL) {
|
||||
return _default_voxel[c];
|
||||
}
|
||||
return block->voxels->get_voxel(pos - block_to_voxel(bpos), c);
|
||||
}
|
||||
|
||||
void VoxelMap::set_voxel(int value, Vector3i pos, unsigned int c) {
|
||||
Vector3i bpos = voxel_to_block(pos);
|
||||
VoxelBlock * block = get_block(bpos);
|
||||
@ -73,9 +81,9 @@ VoxelBlock * VoxelMap::get_block(Vector3i bpos) {
|
||||
if (_last_accessed_block && _last_accessed_block->pos == bpos) {
|
||||
return _last_accessed_block;
|
||||
}
|
||||
Ref<VoxelBlock> * p = _blocks.getptr(bpos);
|
||||
VoxelBlock ** p = _blocks.getptr(bpos);
|
||||
if (p) {
|
||||
_last_accessed_block = p->ptr();
|
||||
_last_accessed_block = *p;
|
||||
return _last_accessed_block;
|
||||
}
|
||||
return NULL;
|
||||
@ -187,22 +195,21 @@ void VoxelMap::remove_blocks_not_in_area(Vector3i min, Vector3i max) {
|
||||
Vector3i::sort_min_max(min, max);
|
||||
|
||||
Vector<Vector3i> to_remove;
|
||||
Vector3i * key = NULL;
|
||||
const Vector3i * key = NULL;
|
||||
|
||||
while (_blocks.next(key)) {
|
||||
while (key = _blocks.next(key)) {
|
||||
|
||||
Ref<VoxelBlock> & block_ref = _blocks.get(*key);
|
||||
ERR_FAIL_COND(block_ref.is_null()); // Should never trigger
|
||||
VoxelBlock & block = **block_ref;
|
||||
VoxelBlock * block_ref = _blocks.get(*key);
|
||||
ERR_FAIL_COND(block_ref == NULL); // Should never trigger
|
||||
|
||||
if (!block.pos.is_contained_in(min, max)) {
|
||||
if (block_ref->pos.is_contained_in(min, max)) {
|
||||
|
||||
//if (_observer)
|
||||
// _observer->block_removed(block);
|
||||
|
||||
to_remove.push_back(*key);
|
||||
|
||||
if (&block == _last_accessed_block)
|
||||
if (block_ref == _last_accessed_block)
|
||||
_last_accessed_block = NULL;
|
||||
}
|
||||
}
|
||||
@ -212,6 +219,20 @@ void VoxelMap::remove_blocks_not_in_area(Vector3i min, Vector3i max) {
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelMap::clear() {
|
||||
const Vector3i * key = NULL;
|
||||
while (key = _blocks.next(key)) {
|
||||
VoxelBlock * block_ref = _blocks.get(*key);
|
||||
if(block_ref == NULL) {
|
||||
OS::get_singleton()->printerr("Unexpected NULL in VoxelMap::clear()");
|
||||
}
|
||||
memdelete(block_ref);
|
||||
}
|
||||
_blocks.clear();
|
||||
_last_accessed_block = NULL;
|
||||
}
|
||||
|
||||
|
||||
void VoxelMap::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_voxel", "x", "y", "z", "c"), &VoxelMap::_get_voxel_binding, DEFVAL(0));
|
||||
|
82
voxel_map.h
82
voxel_map.h
@ -6,11 +6,9 @@
|
||||
#include <scene/3d/mesh_instance.h>
|
||||
#include "voxel_buffer.h"
|
||||
|
||||
class VoxelMap;
|
||||
|
||||
// Fixed-size voxel container used in VoxelMap. Used internally.
|
||||
class VoxelBlock : public Reference {
|
||||
OBJ_TYPE(VoxelBlock, Reference)
|
||||
class VoxelBlock {
|
||||
public:
|
||||
static const int SIZE_POW2 = 4; // 3=>8, 4=>16, 5=>32...
|
||||
static const int SIZE = 1 << SIZE_POW2;
|
||||
@ -18,43 +16,24 @@ public:
|
||||
Ref<VoxelBuffer> voxels; // SIZE*SIZE*SIZE voxels
|
||||
Vector3i pos;
|
||||
NodePath mesh_instance_path;
|
||||
//VoxelMap * map;
|
||||
|
||||
MeshInstance * get_mesh_instance(const Node & root);
|
||||
|
||||
static VoxelBlock * create(Vector3i bpos, VoxelBuffer * buffer = 0);
|
||||
|
||||
~VoxelBlock();
|
||||
MeshInstance * get_mesh_instance(const Node & root);
|
||||
|
||||
private:
|
||||
VoxelBlock() : Reference(), voxels(NULL) {}
|
||||
VoxelBlock();
|
||||
|
||||
};
|
||||
|
||||
//class IVoxelMapObserver {
|
||||
//public:
|
||||
// virtual void block_removed(VoxelBlock & block) = 0;
|
||||
//};
|
||||
|
||||
// Infinite voxel storage by means of octants like Gridmap
|
||||
class VoxelMap : public Reference {
|
||||
OBJ_TYPE(VoxelMap, Reference)
|
||||
public:
|
||||
VoxelMap();
|
||||
~VoxelMap();
|
||||
|
||||
int get_voxel(Vector3i pos, unsigned int c = 0);
|
||||
void set_voxel(int value, Vector3i pos, unsigned int c = 0);
|
||||
|
||||
void set_default_voxel(int value, unsigned int channel=0);
|
||||
int get_default_voxel(unsigned int channel=0);
|
||||
|
||||
// Converts voxel coodinates into block coordinates
|
||||
static _FORCE_INLINE_ Vector3i voxel_to_block(Vector3i pos) {
|
||||
return Vector3i(
|
||||
//pos.x < 0 ? (pos.x + 1) / VoxelBlock::SIZE - 1 : pos.x / VoxelBlock::SIZE,
|
||||
//pos.y < 0 ? (pos.y + 1) / VoxelBlock::SIZE - 1 : pos.y / VoxelBlock::SIZE,
|
||||
//pos.z < 0 ? (pos.z + 1) / VoxelBlock::SIZE - 1 : pos.z / VoxelBlock::SIZE
|
||||
pos.x >> VoxelBlock::SIZE_POW2,
|
||||
pos.y >> VoxelBlock::SIZE_POW2,
|
||||
pos.z >> VoxelBlock::SIZE_POW2
|
||||
@ -66,6 +45,15 @@ public:
|
||||
return bpos * VoxelBlock::SIZE;
|
||||
}
|
||||
|
||||
VoxelMap();
|
||||
~VoxelMap();
|
||||
|
||||
int get_voxel(Vector3i pos, unsigned int c = 0);
|
||||
void set_voxel(int value, Vector3i pos, unsigned int c = 0);
|
||||
|
||||
void set_default_voxel(int value, unsigned int channel=0);
|
||||
int get_default_voxel(unsigned int channel=0);
|
||||
|
||||
// Gets a copy of all voxels in the area starting at min_pos having the same size as dst_buffer.
|
||||
void get_buffer_copy(Vector3i min_pos, VoxelBuffer & dst_buffer, unsigned int channel = 0);
|
||||
|
||||
@ -74,15 +62,14 @@ public:
|
||||
|
||||
void remove_blocks_not_in_area(Vector3i min, Vector3i max);
|
||||
|
||||
_FORCE_INLINE_ Ref<VoxelBlock> get_block_ref(Vector3i bpos) { return get_block(bpos); }
|
||||
VoxelBlock * get_block(Vector3i bpos);
|
||||
|
||||
bool has_block(Vector3i pos) const;
|
||||
bool is_block_surrounded(Vector3i pos) const;
|
||||
|
||||
//void set_observer(IVoxelMapObserver * observer) { _observer = observer; }
|
||||
void clear();
|
||||
|
||||
private:
|
||||
VoxelBlock * get_block(Vector3i bpos);
|
||||
void set_block(Vector3i bpos, VoxelBlock * block);
|
||||
|
||||
_FORCE_INLINE_ int get_block_size() const { return VoxelBlock::SIZE; }
|
||||
@ -103,52 +90,13 @@ private:
|
||||
uint8_t _default_voxel[VoxelBuffer::MAX_CHANNELS];
|
||||
|
||||
// Blocks stored with a spatial hash in all 3D directions
|
||||
HashMap<Vector3i, Ref<VoxelBlock>, Vector3iHasher> _blocks;
|
||||
HashMap<Vector3i, VoxelBlock*, Vector3iHasher> _blocks;
|
||||
|
||||
// Voxel access will most frequently be in contiguous areas, so the same blocks are accessed.
|
||||
// To prevent too much hashing, this reference is checked before.
|
||||
VoxelBlock * _last_accessed_block;
|
||||
|
||||
//IVoxelMapObserver * _observer;
|
||||
};
|
||||
|
||||
//class VoxelSector {
|
||||
//public:
|
||||
// static const int SIZE = 16;
|
||||
//
|
||||
//private:
|
||||
// Ref<VoxelBlock> blocks[SIZE * SIZE * SIZE];
|
||||
//};
|
||||
|
||||
//template <unsigned int P>
|
||||
//struct VoxelTree {
|
||||
//
|
||||
// const int SIZE = 1 << P;
|
||||
// const int VOLUME = P*P*P;
|
||||
//
|
||||
// uint8_t get_voxel(int x, int y, int z) {
|
||||
// unsigned int i = index(x / SIZE, y / SIZE, z / SIZE);
|
||||
// ERR_FAIL_COND_V(i >= VOLUME, 0);
|
||||
// if (subtrees) {
|
||||
// VoxelTree<N> * subtree = subtrees[i];
|
||||
// if (subtree) {
|
||||
// return subtree->get_voxel(x, y, z);
|
||||
// }
|
||||
// }
|
||||
// else if (blocks[i].is_valid()) {
|
||||
// return blocks[i]->voxels.get_voxel(x, y, z);
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// unsigned int index(int x, int y, int z) {
|
||||
// return (pos.z * SIZE + pos.x) * SIZE + pos.y;
|
||||
// }
|
||||
//
|
||||
// Ref<VoxelBlock> * blocks;
|
||||
// VoxelTree<N> * subtrees;
|
||||
// int level;
|
||||
//};
|
||||
|
||||
#endif // VOXEL_MAP_H
|
||||
|
||||
|
@ -126,11 +126,11 @@ void VoxelTerrain::update_blocks() {
|
||||
}
|
||||
|
||||
void VoxelTerrain::update_block_mesh(Vector3i block_pos) {
|
||||
Ref<VoxelBlock> block_ref = _map->get_block_ref(block_pos);
|
||||
if (block_ref.is_null()) {
|
||||
VoxelBlock * block = _map->get_block(block_pos);
|
||||
if (block == NULL) {
|
||||
return;
|
||||
}
|
||||
if (block_ref->voxels->is_uniform(0) && block_ref->voxels->get_voxel(0, 0, 0, 0) == 0) {
|
||||
if (block->voxels->is_uniform(0) && block->voxels->get_voxel(0, 0, 0, 0) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -161,14 +161,14 @@ void VoxelTerrain::update_block_mesh(Vector3i block_pos) {
|
||||
// Build mesh (that part is the most CPU-intensive)
|
||||
Ref<Mesh> mesh = _mesher->build(nbuffer);
|
||||
|
||||
MeshInstance * mesh_instance = block_ref->get_mesh_instance(*this);
|
||||
MeshInstance * mesh_instance = block->get_mesh_instance(*this);
|
||||
if (mesh_instance == NULL) {
|
||||
// Create and spawn mesh
|
||||
mesh_instance = memnew(MeshInstance);
|
||||
mesh_instance->set_mesh(mesh);
|
||||
mesh_instance->set_translation(VoxelMap::block_to_voxel(block_pos).to_vec3());
|
||||
add_child(mesh_instance);
|
||||
block_ref->mesh_instance_path = mesh_instance->get_path();
|
||||
block->mesh_instance_path = mesh_instance->get_path();
|
||||
}
|
||||
else {
|
||||
// Update mesh
|
||||
|
Loading…
Reference in New Issue
Block a user