From 7f0a832677f4e67126b94a7f4000e12c44925164 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 16 Jul 2019 16:18:09 +0200 Subject: [PATCH] Implemented Ao generation, and started working on light support. --- data/voxel_light.cpp | 80 ++++++++++++++++++++-- data/voxel_light.h | 35 +++++----- meshers/cubic_mesher/voxel_cube_points.cpp | 26 ++++++- meshers/cubic_mesher/voxel_cube_points.h | 4 ++ world/voxel_buffer.cpp | 59 ++++++++++++++++ world/voxel_buffer.h | 15 ++++ 6 files changed, 194 insertions(+), 25 deletions(-) diff --git a/data/voxel_light.cpp b/data/voxel_light.cpp index bb325f7..9506b92 100644 --- a/data/voxel_light.cpp +++ b/data/voxel_light.cpp @@ -1,16 +1,82 @@ #include "voxel_light.h" -VoxelLight::VoxelLight() { +int VoxelLight::get_chunk_position_x() { + return _chunk_position.x; +} +int VoxelLight::get_chunk_position_y() { + return _chunk_position.y; +} +int VoxelLight::get_chunk_position_z() { + return _chunk_position.z; +} +Vector3i VoxelLight::get_chunk_position() { + return _chunk_position; +} +void VoxelLight::set_chunk_position(int x, int y, int z) { + _chunk_position.x = x; + _chunk_position.y = y; + _chunk_position.z = z; } -VoxelLight::VoxelLight(Vector3i position, Color color, float strength, Vector3 WorldPosition, Vector3 offset) { +int VoxelLight::get_world_position_x() { + return _world_position.x; +} +int VoxelLight::get_world_position_y() { + return _world_position.y; +} +int VoxelLight::get_world_position_z() { + return _world_position.z; +} +Vector3i VoxelLight::get_world_position() { + return _world_position; + +} +void VoxelLight::set_world_position(int x, int y, int z) { + _world_position.x = x; + _world_position.y = y; + _world_position.z = z; +} - _world_position = WorldPosition + offset; - _local_position = position; - _offset = offset; - _color = color; - _strength = strength; +Color VoxelLight::get_color() { + return _color; + +} +void VoxelLight::set_color(Color color) { + _color = color; + +} + +float VoxelLight::get_size() { + return _size; + +} +void VoxelLight::set_size(float size) { + _size = size; +} + +VoxelLight::VoxelLight() { + _size = 0; } VoxelLight::~VoxelLight() { } + +void VoxelLight::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_chunk_position_x"), &VoxelLight::get_chunk_position_x); + ClassDB::bind_method(D_METHOD("get_chunk_position_y"), &VoxelLight::get_chunk_position_y); + ClassDB::bind_method(D_METHOD("get_chunk_position_z"), &VoxelLight::get_chunk_position_z); + ClassDB::bind_method(D_METHOD("set_chunk_position", "x", "y", "z"), &VoxelLight::set_chunk_position); + + ClassDB::bind_method(D_METHOD("get_world_position_x"), &VoxelLight::get_world_position_x); + ClassDB::bind_method(D_METHOD("get_world_position_y"), &VoxelLight::get_world_position_y); + ClassDB::bind_method(D_METHOD("get_world_position_z"), &VoxelLight::get_world_position_z); + ClassDB::bind_method(D_METHOD("set_world_position", "x", "y", "z"), &VoxelLight::set_world_position); + + ClassDB::bind_method(D_METHOD("get_color"), &VoxelLight::get_color); + ClassDB::bind_method(D_METHOD("set_color"), &VoxelLight::set_color); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + + ClassDB::bind_method(D_METHOD("get_size"), &VoxelLight::get_size); + ClassDB::bind_method(D_METHOD("set_size"), &VoxelLight::set_size); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size"), "set_size", "get_size"); +} diff --git a/data/voxel_light.h b/data/voxel_light.h index 991f12a..6ec4ad8 100644 --- a/data/voxel_light.h +++ b/data/voxel_light.h @@ -11,34 +11,35 @@ class VoxelLight : public Reference { GDCLASS(VoxelLight, Reference); public: - Vector3i get_local_position() { return _local_position; } - void set_local_position(Vector3i neighbours) { _local_position = neighbours; } + int get_chunk_position_x(); + int get_chunk_position_y(); + int get_chunk_position_z(); + Vector3i get_chunk_position(); + void set_chunk_position(int x, int y, int z); - Vector3 get_world_position() { return _world_position; } - void set_world_position(Vector3 world_position) { _world_position = world_position; } + int get_world_position_x(); + int get_world_position_y(); + int get_world_position_z(); + Vector3i get_world_position(); + void set_world_position(int x, int y, int z); - Vector3 get_offset() { return _offset; } - void set_offset(Vector3 offset) { _offset = offset; } + Color get_color(); + void set_color(Color color); - Color get_color() { return _color; } - void set_color(Color color) { _color = color; } - - float get_strength() { return _strength; } - void set_strength(float strength) { _strength = strength; } + float get_size(); + void set_size(float strength); VoxelLight(); - VoxelLight(Vector3i position, Color color, float strength, Vector3 WorldPosition, Vector3 offset); ~VoxelLight(); private: - static void _bind_methods() {} + static void _bind_methods(); private: - Vector3i _local_position; - Vector3 _world_position; - Vector3 _offset; + Vector3i _chunk_position; + Vector3i _world_position; Color _color; - float _strength; + int _size; }; #endif diff --git a/meshers/cubic_mesher/voxel_cube_points.cpp b/meshers/cubic_mesher/voxel_cube_points.cpp index 7cce21c..ba69d0f 100644 --- a/meshers/cubic_mesher/voxel_cube_points.cpp +++ b/meshers/cubic_mesher/voxel_cube_points.cpp @@ -428,6 +428,15 @@ void VoxelCubePoints::setup(const Ref buffer, int x, int y, int z, _point_fills[P101] = buffer->get_voxel(x + size, y, z + size, VoxelBuffer::CHANNEL_ISOLEVEL); _point_fills[P111] = buffer->get_voxel(x + size, y + size, z + size, VoxelBuffer::CHANNEL_ISOLEVEL); + _point_aos[P000] = buffer->get_voxel(x, y, z, VoxelBuffer::CHANNEL_AO); + _point_aos[P100] = buffer->get_voxel(x + size, y, z, VoxelBuffer::CHANNEL_AO); + _point_aos[P010] = buffer->get_voxel(x, y + size, z, VoxelBuffer::CHANNEL_AO); + _point_aos[P001] = buffer->get_voxel(x, y, z + size, VoxelBuffer::CHANNEL_AO); + _point_aos[P110] = buffer->get_voxel(x + size, y + size, z, VoxelBuffer::CHANNEL_AO); + _point_aos[P011] = buffer->get_voxel(x, y + size, z + size, VoxelBuffer::CHANNEL_AO); + _point_aos[P101] = buffer->get_voxel(x + size, y, z + size, VoxelBuffer::CHANNEL_AO); + _point_aos[P111] = buffer->get_voxel(x + size, y + size, z + size, VoxelBuffer::CHANNEL_AO); + refresh_neighbours(buffer); refresh_points(); @@ -564,6 +573,18 @@ int VoxelCubePoints::get_point_neighbours(int index) { return _point_neighbours[index]; } +int VoxelCubePoints::get_point_ao(int index) { + ERR_FAIL_INDEX_V(index, POINT_COUNT, 0); + + return _point_aos[index]; +} + +int VoxelCubePoints::get_face_point_ao(int face, int index) { + int indx = get_point_index(face, index); + + return _point_aos[indx]; +} + Vector3 VoxelCubePoints::get_point(int index) { ERR_FAIL_INDEX_V(index, POINT_COUNT, Vector3()); @@ -729,7 +750,10 @@ void VoxelCubePoints::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_type", "index"), &VoxelCubePoints::get_point_type); ClassDB::bind_method(D_METHOD("get_point_fill", "index"), &VoxelCubePoints::get_point_fill); ClassDB::bind_method(D_METHOD("get_point_neighbours", "index"), &VoxelCubePoints::get_point_neighbours); - + + ClassDB::bind_method(D_METHOD("get_point_ao", "index"), &VoxelCubePoints::get_point_ao); + ClassDB::bind_method(D_METHOD("get_face_point_ao", "face", "index"), &VoxelCubePoints::get_face_point_ao); + ClassDB::bind_method(D_METHOD("get_point", "index"), &VoxelCubePoints::get_point); ClassDB::bind_method(D_METHOD("get_top_left_point", "face"), &VoxelCubePoints::get_top_left_point); diff --git a/meshers/cubic_mesher/voxel_cube_points.h b/meshers/cubic_mesher/voxel_cube_points.h index 5553fee..c2bd9e5 100644 --- a/meshers/cubic_mesher/voxel_cube_points.h +++ b/meshers/cubic_mesher/voxel_cube_points.h @@ -113,6 +113,9 @@ public: int get_point_type(int index); int get_point_fill(int index); int get_point_neighbours(int index); + + int get_point_ao(int index); + int get_face_point_ao(int face, int index); Vector3 get_point(int index); Vector3 get_top_left_point(int face); @@ -140,6 +143,7 @@ private: uint8_t _point_types[POINT_COUNT]; uint8_t _point_fills[POINT_COUNT]; + uint8_t _point_aos[POINT_COUNT]; unsigned int _point_neighbours[POINT_COUNT]; int _size; diff --git a/world/voxel_buffer.cpp b/world/voxel_buffer.cpp index 934cb2f..a33dd2b 100644 --- a/world/voxel_buffer.cpp +++ b/world/voxel_buffer.cpp @@ -284,6 +284,60 @@ uint8_t *VoxelBuffer::get_channel_raw(unsigned int channel_index) const { return channel.data; } +void VoxelBuffer::generate_ao() { + unsigned int size_x = _size.x; + unsigned int size_y = _size.y; + unsigned int size_z = _size.z; + + ERR_FAIL_COND(size_x == 0 || size_y == 0 || size_z == 0); + + for (unsigned int y = 1; y < size_y - 1; ++y) { + for (unsigned int z = 1; z < size_z - 1; ++z) { + for (unsigned int x = 1; x < size_x - 1; ++x) { + int current = get_voxel(x, y, z, CHANNEL_ISOLEVEL); + + int sum = get_voxel(x + 1, y, z, CHANNEL_ISOLEVEL); + sum += get_voxel(x - 1, y, z, CHANNEL_ISOLEVEL); + sum += get_voxel(x, y + 1, z, CHANNEL_ISOLEVEL); + sum += get_voxel(x, y - 1, z, CHANNEL_ISOLEVEL); + sum += get_voxel(x, y, z + 1, CHANNEL_ISOLEVEL); + sum += get_voxel(x, y, z - 1, CHANNEL_ISOLEVEL); + + sum /= 6; + + sum -= current; + + if (sum < 0) + sum = 0; + + set_voxel(sum, x, y, z, CHANNEL_AO); + } + } + } +} + +void VoxelBuffer::add_light(int local_x, int local_y, int local_z, int size, Color color){ + VoxelBufferLight l; + + l.x = local_x; + l.y = local_y; + l.z = local_z; + l.color = color; + l.size = size; + + _lights.push_back(l); +} +void VoxelBuffer::remove_light(int local_x, int local_y, int local_z) { + for (int i = 0; i < _lights.size(); ++i) { + VoxelBufferLight l = _lights.get(i); + + if (l.x == local_x && l.y == local_y && l-z == local_z) { + _lights.remove(i); + return; + } + } +} + void VoxelBuffer::create_channel(int i, Vector3i size, uint8_t defval) { create_channel_noinit(i, size); memset(_channels[i].data, defval, get_volume() * sizeof(uint8_t)); @@ -327,6 +381,11 @@ void VoxelBuffer::_bind_methods() { ClassDB::bind_method(D_METHOD("is_uniform", "channel"), &VoxelBuffer::is_uniform); ClassDB::bind_method(D_METHOD("optimize"), &VoxelBuffer::compress_uniform_channels); + ClassDB::bind_method(D_METHOD("generate_ao"), &VoxelBuffer::generate_ao); + + ClassDB::bind_method(D_METHOD("add_light", "local_x", "local_y", "local_z", "size", "color"), &VoxelBuffer::add_light); + ClassDB::bind_method(D_METHOD("remove_light", "local_x", "local_y", "local_z"), &VoxelBuffer::remove_light); + BIND_ENUM_CONSTANT(CHANNEL_TYPE); BIND_ENUM_CONSTANT(CHANNEL_ISOLEVEL); BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_R); diff --git a/world/voxel_buffer.h b/world/voxel_buffer.h index a33dfec..fdec3ca 100644 --- a/world/voxel_buffer.h +++ b/world/voxel_buffer.h @@ -38,6 +38,7 @@ public: CHANNEL_LIGHT_COLOR_R, CHANNEL_LIGHT_COLOR_G, CHANNEL_LIGHT_COLOR_B, + CHANNEL_AO, CHANNEL_DATA1, CHANNEL_DATA2, // Arbitrary value, 8 should be enough. Tweak for your needs. @@ -121,6 +122,10 @@ public: } uint8_t *get_channel_raw(unsigned int channel_index) const; + + void generate_ao(); + void add_light(int local_x, int local_y, int local_z, int size, Color color); + void remove_light(int local_x, int local_y, int local_z); private: void create_channel_noinit(int i, Vector3i size); @@ -142,6 +147,14 @@ protected: _FORCE_INLINE_ void _fill_area_binding(int defval, Vector3 min, Vector3 max, unsigned int channel_index) { fill_area(defval, Vector3i(min), Vector3i(max), channel_index); } _FORCE_INLINE_ void _set_voxel_f_binding(real_t value, int x, int y, int z, unsigned int channel) { set_voxel_f(value, x, y, z, channel); } + struct VoxelBufferLight { + int x; + int y; + int z; + Color _color; + int _size; + }; + private: struct Channel { // Allocated when the channel is populated. @@ -162,6 +175,8 @@ private: // How many voxels are there in the three directions. All populated channels have the same size. Vector3i _size; + + Vector _lights; }; VARIANT_ENUM_CAST(VoxelBuffer::ChannelId)