godot_voxel/voxel_map.h

116 lines
3.9 KiB
C
Raw Normal View History

#ifndef VOXEL_MAP_H
#define VOXEL_MAP_H
#include <scene/main/node.h>
#include <core/hash_map.h>
#include <scene/3d/mesh_instance.h>
2017-03-26 18:09:37 +02:00
#include <scene/3d/physics_body.h>
#include "voxel_buffer.h"
// Fixed-size voxel container used in VoxelMap. Used internally.
2017-01-03 02:50:19 +01:00
class VoxelBlock {
public:
2017-01-01 04:40:16 +01:00
static const int SIZE_POW2 = 4; // 3=>8, 4=>16, 5=>32...
static const int SIZE = 1 << SIZE_POW2;
static const int SIZE_MASK = 0xf;
2017-01-01 04:40:16 +01:00
Ref<VoxelBuffer> voxels; // SIZE*SIZE*SIZE voxels
Vector3i pos;
NodePath mesh_instance_path;
static VoxelBlock * create(Vector3i bpos, Ref<VoxelBuffer> buffer);
2017-01-03 02:50:19 +01:00
MeshInstance * get_mesh_instance(const Node & root);
private:
2017-01-03 02:50:19 +01:00
VoxelBlock();
};
// Infinite voxel storage by means of octants like Gridmap
class VoxelMap : public Reference {
2017-03-25 01:23:36 +01:00
GDCLASS(VoxelMap, Reference)
public:
2017-01-01 04:40:16 +01:00
// Converts voxel coodinates into block coordinates
static _FORCE_INLINE_ Vector3i voxel_to_block(Vector3i pos) {
return Vector3i(
pos.x >> VoxelBlock::SIZE_POW2,
pos.y >> VoxelBlock::SIZE_POW2,
pos.z >> VoxelBlock::SIZE_POW2
);
}
static _FORCE_INLINE_ Vector3i to_local(Vector3i pos) {
return Vector3i(
pos.x & VoxelBlock::SIZE_MASK,
pos.y & VoxelBlock::SIZE_MASK,
pos.z & VoxelBlock::SIZE_MASK
);
}
2017-01-01 04:40:16 +01:00
// Converts block coodinates into voxel coordinates
static _FORCE_INLINE_ Vector3i block_to_voxel(Vector3i bpos) {
return bpos * VoxelBlock::SIZE;
}
2017-01-03 02:50:19 +01:00
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);
2017-01-01 04:40:16 +01:00
// 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 channels_mask = 1);
2017-01-01 04:40:16 +01:00
// Moves the given buffer into a block of the map. The buffer is referenced, no copy is made.
void set_block_buffer(Vector3i bpos, Ref<VoxelBuffer> buffer);
2017-01-01 04:40:16 +01:00
void remove_blocks_not_in_area(Vector3i min, Vector3i max);
2017-01-03 02:50:19 +01:00
VoxelBlock * get_block(Vector3i bpos);
2017-01-01 04:40:16 +01:00
bool has_block(Vector3i pos) const;
bool is_block_surrounded(Vector3i pos) const;
2017-01-03 02:50:19 +01:00
void clear();
private:
2017-01-01 04:40:16 +01:00
void set_block(Vector3i bpos, VoxelBlock * block);
2017-01-01 04:40:16 +01:00
_FORCE_INLINE_ int get_block_size() const { return VoxelBlock::SIZE; }
2017-01-01 04:40:16 +01:00
static void _bind_methods();
2017-01-01 04:40:16 +01:00
_FORCE_INLINE_ int _get_voxel_binding(int x, int y, int z, unsigned int c = 0) { return get_voxel(Vector3i(x, y, z), c); }
_FORCE_INLINE_ void _set_voxel_binding(int value, int x, int y, int z, unsigned int c = 0) { set_voxel(value, Vector3i(x, y, z), c); }
_FORCE_INLINE_ int _get_voxel_v_binding(Vector3 pos, unsigned int c = 0) { return get_voxel(Vector3i(pos), c); }
_FORCE_INLINE_ void _set_voxel_v_binding(int value, Vector3 pos, unsigned int c = 0) { set_voxel(value, Vector3i(pos), c); }
2017-01-01 04:40:16 +01:00
_FORCE_INLINE_ bool _has_block_binding(int x, int y, int z) { return has_block(Vector3i(x, y, z)); }
_FORCE_INLINE_ Vector3 _voxel_to_block_binding(Vector3 pos) const { return voxel_to_block(Vector3i(pos)).to_vec3(); }
_FORCE_INLINE_ Vector3 _block_to_voxel_binding(Vector3 pos) const { return block_to_voxel(Vector3i(pos)).to_vec3(); }
bool _is_block_surrounded(Vector3 pos) const { return is_block_surrounded(Vector3i(pos)); }
void _get_buffer_copy_binding(Vector3 pos, Ref<VoxelBuffer> dst_buffer_ref, unsigned int channel = 0);
void _set_block_buffer_binding(Vector3 bpos, Ref<VoxelBuffer> buffer) { set_block_buffer(Vector3i(bpos), buffer); }
2017-01-02 02:19:02 +01:00
private:
// Voxel values that will be returned if access is out of map bounds
uint8_t _default_voxel[VoxelBuffer::MAX_CHANNELS];
// Blocks stored with a spatial hash in all 3D directions
2017-01-03 02:50:19 +01:00
HashMap<Vector3i, VoxelBlock*, Vector3iHasher> _blocks;
2017-01-02 02:19:02 +01:00
// 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;
};
#endif // VOXEL_MAP_H