Implemented Ao generation, and started working on light support.

This commit is contained in:
Relintai 2019-07-16 16:18:09 +02:00
parent 370702cc1e
commit 7f0a832677
6 changed files with 194 additions and 25 deletions

View File

@ -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");
}

View File

@ -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

View File

@ -428,6 +428,15 @@ void VoxelCubePoints::setup(const Ref<VoxelBuffer> 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);

View File

@ -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;

View File

@ -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);

View File

@ -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<VoxelBufferLight> _lights;
};
VARIANT_ENUM_CAST(VoxelBuffer::ChannelId)