mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-11-11 20:35:08 +01:00
Fixed set_voxel() and block force_update_blocks()
This commit is contained in:
parent
d3ab015c67
commit
06a399f932
@ -23,7 +23,7 @@ void VoxelBuffer::create(int sx, int sy, int sz) {
|
||||
Channel & channel = _channels[i];
|
||||
if (channel.data) {
|
||||
// TODO Optimize with realloc
|
||||
delete_channel(i, _size);
|
||||
delete_channel(i);
|
||||
create_channel(i, new_size);
|
||||
}
|
||||
}
|
||||
@ -35,17 +35,24 @@ void VoxelBuffer::clear() {
|
||||
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
||||
Channel & channel = _channels[i];
|
||||
if (channel.data) {
|
||||
delete_channel(i, _size);
|
||||
delete_channel(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) {
|
||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
||||
delete_channel(channel_index, _size);
|
||||
if(_channels[channel_index].data)
|
||||
delete_channel(channel_index);
|
||||
_channels[channel_index].defval = clear_value;
|
||||
}
|
||||
|
||||
void VoxelBuffer::set_default_values(uint8_t values[VoxelBuffer::MAX_CHANNELS]) {
|
||||
for(unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
||||
_channels[i].defval = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelBuffer::get_voxel(int x, int y, int z, unsigned int channel_index) const {
|
||||
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
|
||||
|
||||
@ -156,7 +163,7 @@ void VoxelBuffer::copy_from(const VoxelBuffer & other, unsigned int channel_inde
|
||||
memcpy(channel.data, other_channel.data, get_volume() * sizeof(uint8_t));
|
||||
}
|
||||
else if(channel.data) {
|
||||
delete_channel(channel_index, _size);
|
||||
delete_channel(channel_index);
|
||||
}
|
||||
|
||||
channel.defval = other_channel.defval;
|
||||
@ -223,8 +230,9 @@ void VoxelBuffer::create_channel_noinit(int i, Vector3i size) {
|
||||
channel.data = (uint8_t*)memalloc(volume * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
void VoxelBuffer::delete_channel(int i, Vector3i size) {
|
||||
void VoxelBuffer::delete_channel(int i) {
|
||||
Channel & channel = _channels[i];
|
||||
ERR_FAIL_COND(channel.data == NULL);
|
||||
memfree(channel.data);
|
||||
channel.data = NULL;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ public:
|
||||
|
||||
_FORCE_INLINE_ Vector3i get_size() const { return _size; }
|
||||
|
||||
void set_default_values(uint8_t values[MAX_CHANNELS]);
|
||||
|
||||
int get_voxel(int x, int y, int z, unsigned int channel_index=0) const;
|
||||
void set_voxel(int value, int x, int y, int z, unsigned int channel_index=0);
|
||||
void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0);
|
||||
@ -62,7 +64,7 @@ public:
|
||||
private:
|
||||
void create_channel_noinit(int i, Vector3i size);
|
||||
void create_channel(int i, Vector3i size, uint8_t defval=0);
|
||||
void delete_channel(int i, Vector3i size);
|
||||
void delete_channel(int i);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -15,18 +15,15 @@ MeshInstance * VoxelBlock::get_mesh_instance(const Node & root) {
|
||||
}
|
||||
|
||||
// Helper
|
||||
VoxelBlock * VoxelBlock::create(Vector3i bpos, VoxelBuffer * buffer) {
|
||||
VoxelBlock * VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer) {
|
||||
const int bs = VoxelBlock::SIZE;
|
||||
ERR_FAIL_COND_V(buffer.is_null(), NULL);
|
||||
ERR_FAIL_COND_V(buffer->get_size() != Vector3i(bs, bs, bs), NULL);
|
||||
|
||||
VoxelBlock * block = memnew(VoxelBlock);
|
||||
block->pos = bpos;
|
||||
if (buffer) {
|
||||
const int bs = VoxelBlock::SIZE;
|
||||
ERR_FAIL_COND_V(buffer->get_size() != Vector3i(bs, bs, bs), NULL);
|
||||
}
|
||||
else {
|
||||
buffer = memnew(VoxelBuffer);
|
||||
}
|
||||
ERR_FAIL_COND_V(buffer == NULL, NULL);
|
||||
block->voxels = Ref<VoxelBuffer>(buffer);
|
||||
|
||||
block->voxels = buffer;
|
||||
//block->map = ↦
|
||||
return block;
|
||||
}
|
||||
@ -58,12 +55,21 @@ int VoxelMap::get_voxel(Vector3i pos, unsigned int c) {
|
||||
}
|
||||
|
||||
void VoxelMap::set_voxel(int value, Vector3i pos, unsigned int c) {
|
||||
|
||||
Vector3i bpos = voxel_to_block(pos);
|
||||
VoxelBlock * block = get_block(bpos);
|
||||
|
||||
if (block == NULL) {
|
||||
block = VoxelBlock::create(bpos);
|
||||
|
||||
Ref<VoxelBuffer> buffer(memnew(VoxelBuffer));
|
||||
buffer->create(VoxelBlock::SIZE, VoxelBlock::SIZE, VoxelBlock::SIZE);
|
||||
buffer->set_default_values(_default_voxel);
|
||||
|
||||
block = VoxelBlock::create(bpos, buffer);
|
||||
|
||||
set_block(bpos, block);
|
||||
}
|
||||
|
||||
block->voxels->set_voxel(value, pos - block_to_voxel(bpos), c);
|
||||
}
|
||||
|
||||
@ -90,6 +96,7 @@ VoxelBlock * VoxelMap::get_block(Vector3i bpos) {
|
||||
}
|
||||
|
||||
void VoxelMap::set_block(Vector3i bpos, VoxelBlock * block) {
|
||||
ERR_FAIL_COND(block == NULL);
|
||||
if (_last_accessed_block == NULL || _last_accessed_block->pos == bpos) {
|
||||
_last_accessed_block = block;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
Vector3i pos;
|
||||
NodePath mesh_instance_path;
|
||||
|
||||
static VoxelBlock * create(Vector3i bpos, VoxelBuffer * buffer = 0);
|
||||
static VoxelBlock * create(Vector3i bpos, Ref<VoxelBuffer> buffer);
|
||||
|
||||
MeshInstance * get_mesh_instance(const Node & root);
|
||||
|
||||
|
@ -79,6 +79,7 @@ void VoxelTerrain::update_blocks() {
|
||||
uint32_t max_time = 1000 / 60;
|
||||
|
||||
while (!_block_update_queue.empty() && (os.get_ticks_msec() - time_before) < max_time) {
|
||||
//printf("Remaining: %i\n", _block_update_queue.size());
|
||||
|
||||
// TODO Move this to a thread
|
||||
// TODO Have VoxelTerrainGenerator in C++
|
||||
@ -88,22 +89,22 @@ void VoxelTerrain::update_blocks() {
|
||||
Vector3i block_pos = _block_update_queue[_block_update_queue.size() - 1];
|
||||
|
||||
if (!_map->has_block(block_pos)) {
|
||||
|
||||
// Create buffer
|
||||
if(!_provider.is_null()) {
|
||||
Ref<VoxelBuffer> buffer_ref = Ref<VoxelBuffer>(memnew(VoxelBuffer));
|
||||
const Vector3i block_size(VoxelBlock::SIZE, VoxelBlock::SIZE, VoxelBlock::SIZE);
|
||||
buffer_ref->create(block_size.x, block_size.y, block_size.z);
|
||||
|
||||
// Query voxel provider
|
||||
if(!_provider.is_null()) {
|
||||
_provider->emerge_block(buffer_ref, block_pos);
|
||||
}
|
||||
|
||||
// Check script return
|
||||
ERR_FAIL_COND(buffer_ref->get_size() != block_size);
|
||||
|
||||
// Store buffer
|
||||
_map->set_block_buffer(block_pos, buffer_ref);
|
||||
}
|
||||
}
|
||||
|
||||
// Update meshes
|
||||
Vector3i ndir;
|
||||
@ -111,6 +112,7 @@ void VoxelTerrain::update_blocks() {
|
||||
for (ndir.x = -1; ndir.x < 2; ++ndir.x) {
|
||||
for (ndir.y = -1; ndir.y < 2; ++ndir.y) {
|
||||
Vector3i npos = block_pos + ndir;
|
||||
// TODO What if the map is really composed of empty blocks?
|
||||
if (_map->is_block_surrounded(npos)) {
|
||||
update_block_mesh(npos);
|
||||
}
|
||||
@ -118,7 +120,6 @@ void VoxelTerrain::update_blocks() {
|
||||
}
|
||||
}
|
||||
//update_block_mesh(block_pos);
|
||||
}
|
||||
|
||||
// Pop request
|
||||
_block_update_queue.resize(_block_update_queue.size() - 1);
|
||||
@ -191,6 +192,8 @@ void VoxelTerrain::_bind_methods() {
|
||||
ObjectTypeDB::bind_method(_MD("get_block_update_count"), &VoxelTerrain::get_block_update_count);
|
||||
ObjectTypeDB::bind_method(_MD("get_mesher:VoxelMesher"), &VoxelTerrain::get_mesher);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_map:VoxelMap"), &VoxelTerrain::get_map);
|
||||
|
||||
// TODO Make those two static in VoxelMap?
|
||||
ObjectTypeDB::bind_method(_MD("voxel_to_block", "voxel_pos"), &VoxelTerrain::_voxel_to_block_binding);
|
||||
ObjectTypeDB::bind_method(_MD("block_to_voxel", "block_pos"), &VoxelTerrain::_block_to_voxel_binding);
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
int get_block_update_count();
|
||||
|
||||
Ref<VoxelMesher> get_mesher() { return _mesher; }
|
||||
Ref<VoxelMap> get_map() { return _map; }
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
Loading…
Reference in New Issue
Block a user