Cleaned up the light baking api.

This commit is contained in:
Relintai 2020-04-15 12:41:52 +02:00
parent 17b033e707
commit 7a3e4ecbe3
6 changed files with 302 additions and 223 deletions

View File

@ -118,6 +118,13 @@ void VoxelChunkDefault::set_max_build_phase(const int value) {
_max_build_phases = value;
}
bool VoxelChunkDefault::get_lights_dirty() const {
return _lights_dirty;
}
void VoxelChunkDefault::set_lights_dirty(const bool value) {
_lights_dirty = value;
}
int VoxelChunkDefault::get_lod_num() const {
return _lod_num;
}
@ -319,10 +326,6 @@ void VoxelChunkDefault::next_phase() {
}
}
void VoxelChunkDefault::clear() {
_voxel_lights.clear();
}
void VoxelChunkDefault::emit_build_finished() {
emit_signal("mesh_generation_finished", this);
@ -705,6 +708,16 @@ void VoxelChunkDefault::update_transforms() {
}
}
//Lights
Ref<VoxelLight> VoxelChunkDefault::get_light(const int index) {
ERR_FAIL_INDEX_V(index, _lights.size(), Ref<VoxelLight>());
return _lights.get(index);
}
int VoxelChunkDefault::get_light_count() const {
return _lights.size();
}
void VoxelChunkDefault::create_debug_immediate_geometry() {
ERR_FAIL_COND(_voxel_world == NULL);
ERR_FAIL_COND(_debug_drawer != NULL);
@ -806,8 +819,8 @@ void VoxelChunkDefault::draw_debug_voxel_lights() {
_debug_drawer->begin(Mesh::PrimitiveType::PRIMITIVE_LINES);
_debug_drawer->set_color(Color(1, 1, 1));
for (int i = 0; i < _voxel_lights.size(); ++i) {
Ref<VoxelLight> v = _voxel_lights[i];
for (int i = 0; i < _lights.size(); ++i) {
Ref<VoxelLight> v = _lights[i];
int pos_x = v->get_world_position_x() - (_size_x * _position_x);
int pos_y = v->get_world_position_y() - (_size_y * _position_y);
@ -915,11 +928,106 @@ void VoxelChunkDefault::_world_transform_changed() {
update_transforms();
}
void VoxelChunkDefault::_bake_lights() {
clear_baked_lights();
for (int i = 0; i < _lights.size(); ++i) {
bake_light(_lights.get(i));
}
}
void VoxelChunkDefault::_bake_light(Ref<VoxelLight> light) {
ERR_FAIL_COND(!light.is_valid());
Color color = light->get_color();
int size = light->get_size();
int local_x = light->get_world_position_x() - (_position_x * _size_x);
int local_y = light->get_world_position_y() - (_position_y * _size_y);
int local_z = light->get_world_position_z() - (_position_z * _size_z);
ERR_FAIL_COND(size < 0);
//float sizef = static_cast<float>(size);
//float rf = (color.r / sizef);
//float gf = (color.g / sizef);
//float bf = (color.b / sizef);
int64_t dsx = static_cast<int64_t>(_data_size_x);
int64_t dsy = static_cast<int64_t>(_data_size_y);
int64_t dsz = static_cast<int64_t>(_data_size_z);
for (int y = local_y - size; y <= local_y + size; ++y) {
if (y < 0 || y >= dsy)
continue;
for (int z = local_z - size; z <= local_z + size; ++z) {
if (z < 0 || z >= dsz)
continue;
for (int x = local_x - size; x <= local_x + size; ++x) {
if (x < 0 || x >= dsx)
continue;
int lx = x - local_x;
int ly = y - local_y;
int lz = z - local_z;
float str = size - (((float)lx * lx + ly * ly + lz * lz));
str /= size;
if (str < 0)
continue;
int r = color.r * str * 255.0;
int g = color.g * str * 255.0;
int b = color.b * str * 255.0;
r += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_R);
g += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_G);
b += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_B);
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
set_voxel(r, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_R);
set_voxel(g, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_G);
set_voxel(b, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_B);
}
}
}
}
void VoxelChunkDefault::_clear_baked_lights() {
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_R);
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_G);
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_B);
}
void VoxelChunkDefault::_world_light_added(const Ref<VoxelLight> &light) {
_lights.push_back(light);
set_lights_dirty(true);
}
void VoxelChunkDefault::_world_light_removed(const Ref<VoxelLight> &light) {
int index = _lights.find(light);
if (index != -1) {
_lights.remove(index);
set_lights_dirty(true);
}
}
void VoxelChunkDefault::free_chunk() {
free_rids();
}
VoxelChunkDefault::VoxelChunkDefault() {
_lights_dirty = false;
_is_generating = false;
_is_build_threaded = false;
_abort_build = false;
@ -969,6 +1077,8 @@ VoxelChunkDefault::~VoxelChunkDefault() {
_abort_build = true;
wait_and_finish_thread();
}
_lights.clear();
}
void VoxelChunkDefault::_setup_channels() {
@ -1238,70 +1348,6 @@ void VoxelChunkDefault::_build_phase_physics_process(int phase) {
}
}
void VoxelChunkDefault::_add_light(int local_x, int local_y, int local_z, int size, Color color) {
ERR_FAIL_COND(size < 0);
//float sizef = static_cast<float>(size);
//float rf = (color.r / sizef);
//float gf = (color.g / sizef);
//float bf = (color.b / sizef);
int64_t dsx = static_cast<int64_t>(_data_size_x);
int64_t dsy = static_cast<int64_t>(_data_size_y);
int64_t dsz = static_cast<int64_t>(_data_size_z);
for (int y = local_y - size; y <= local_y + size; ++y) {
if (y < 0 || y >= dsy)
continue;
for (int z = local_z - size; z <= local_z + size; ++z) {
if (z < 0 || z >= dsz)
continue;
for (int x = local_x - size; x <= local_x + size; ++x) {
if (x < 0 || x >= dsx)
continue;
int lx = x - local_x;
int ly = y - local_y;
int lz = z - local_z;
float str = size - (((float)lx * lx + ly * ly + lz * lz));
str /= size;
if (str < 0)
continue;
int r = color.r * str * 255.0;
int g = color.g * str * 255.0;
int b = color.b * str * 255.0;
r += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_R);
g += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_G);
b += get_voxel(x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_B);
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
set_voxel(r, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_R);
set_voxel(g, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_G);
set_voxel(b, x, y, z, DEFAULT_CHANNEL_LIGHT_COLOR_B);
}
}
}
}
void VoxelChunkDefault::_clear_baked_lights() {
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_R);
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_G);
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_B);
}
void VoxelChunkDefault::_create_meshers() {
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
@ -1356,6 +1402,10 @@ void VoxelChunkDefault::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_build_phase", "value"), &VoxelChunkDefault::set_max_build_phase);
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_build_phase"), "set_max_build_phase", "get_max_build_phase");
ClassDB::bind_method(D_METHOD("get_lights_dirty"), &VoxelChunkDefault::get_lights_dirty);
ClassDB::bind_method(D_METHOD("set_lights_dirty", "value"), &VoxelChunkDefault::set_lights_dirty);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lights_dirty", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_lights_dirty", "get_lights_dirty");
ClassDB::bind_method(D_METHOD("get_lod_num"), &VoxelChunkDefault::get_lod_num);
ClassDB::bind_method(D_METHOD("set_lod_num"), &VoxelChunkDefault::set_lod_num);
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_num"), "set_lod_num", "get_lod_num");
@ -1364,14 +1414,10 @@ void VoxelChunkDefault::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_current_lod_level"), &VoxelChunkDefault::set_current_lod_level);
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_lod_level"), "set_current_lod_level", "get_current_lod_level");
//Voxel Data
//Data Management functions
ClassDB::bind_method(D_METHOD("generate_ao"), &VoxelChunkDefault::generate_ao);
ClassDB::bind_method(D_METHOD("add_light", "local_x", "local_y", "local_z", "size", "color"), &VoxelChunkDefault::add_light);
ClassDB::bind_method(D_METHOD("clear_baked_lights"), &VoxelChunkDefault::clear_baked_lights);
//Meshes
//Meshing
BIND_VMETHOD(MethodInfo("_build_phase", PropertyInfo(Variant::INT, "phase")));
BIND_VMETHOD(MethodInfo("_build_phase_process", PropertyInfo(Variant::INT, "phase")));
BIND_VMETHOD(MethodInfo("_build_phase_physics_process", PropertyInfo(Variant::INT, "phase")));
@ -1410,13 +1456,14 @@ void VoxelChunkDefault::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_colliders", "mesh_index", "layer_mask"), &VoxelChunkDefault::create_colliders, DEFVAL(1));
ClassDB::bind_method(D_METHOD("free_colliders", "mesh_index"), &VoxelChunkDefault::free_colliders);
//Lights
ClassDB::bind_method(D_METHOD("get_light", "index"), &VoxelChunkDefault::get_light);
ClassDB::bind_method(D_METHOD("get_light_count"), &VoxelChunkDefault::get_light_count);
//Debug
ClassDB::bind_method(D_METHOD("create_debug_immediate_geometry"), &VoxelChunkDefault::create_debug_immediate_geometry);
ClassDB::bind_method(D_METHOD("free_debug_immediate_geometry"), &VoxelChunkDefault::free_debug_immediate_geometry);
ClassDB::bind_method(D_METHOD("free_chunk"), &VoxelChunkDefault::free_chunk);
ClassDB::bind_method(D_METHOD("emit_build_finished"), &VoxelChunkDefault::emit_build_finished);
BIND_VMETHOD(MethodInfo("_draw_debug_voxel_lights", PropertyInfo(Variant::OBJECT, "debug_drawer", PROPERTY_HINT_RESOURCE_TYPE, "ImmediateGeometry")));
ClassDB::bind_method(D_METHOD("draw_cross_voxels", "max"), &VoxelChunkDefault::draw_cross_voxels);
@ -1425,23 +1472,35 @@ void VoxelChunkDefault::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_debug_voxel_lights"), &VoxelChunkDefault::draw_debug_voxel_lights);
//Free
ClassDB::bind_method(D_METHOD("free_chunk"), &VoxelChunkDefault::free_chunk);
//etc
ClassDB::bind_method(D_METHOD("emit_build_finished"), &VoxelChunkDefault::emit_build_finished);
ClassDB::bind_method(D_METHOD("generate_random_ao", "seed", "octaves", "period", "persistence", "scale_factor"), &VoxelChunkDefault::generate_random_ao, DEFVAL(4), DEFVAL(30), DEFVAL(0.3), DEFVAL(0.6));
//virtuals
ClassDB::bind_method(D_METHOD("_setup_channels"), &VoxelChunkDefault::_setup_channels);
ClassDB::bind_method(D_METHOD("_build_phase", "phase"), &VoxelChunkDefault::_build_phase);
ClassDB::bind_method(D_METHOD("_build_phase_process", "phase"), &VoxelChunkDefault::_build_phase_process);
ClassDB::bind_method(D_METHOD("_build_phase_physics_process", "phase"), &VoxelChunkDefault::_build_phase_physics_process);
ClassDB::bind_method(D_METHOD("_add_light", "local_x", "local_y", "local_z", "size", "color"), &VoxelChunkDefault::_add_light);
ClassDB::bind_method(D_METHOD("_clear_baked_lights"), &VoxelChunkDefault::_clear_baked_lights);
ClassDB::bind_method(D_METHOD("_create_meshers"), &VoxelChunkDefault::_create_meshers);
ClassDB::bind_method(D_METHOD("_build", "immediate"), &VoxelChunkDefault::_build);
ClassDB::bind_method(D_METHOD("_visibility_changed", "visible"), &VoxelChunkDefault::_visibility_changed);
ClassDB::bind_method(D_METHOD("_exit_tree"), &VoxelChunkDefault::_exit_tree);
ClassDB::bind_method(D_METHOD("_process", "delta"), &VoxelChunkDefault::_process);
ClassDB::bind_method(D_METHOD("_physics_process", "delta"), &VoxelChunkDefault::_physics_process);
ClassDB::bind_method(D_METHOD("_visibility_changed", "visible"), &VoxelChunkDefault::_visibility_changed);
//lights
ClassDB::bind_method(D_METHOD("_bake_lights"), &VoxelChunkDefault::_bake_lights);
ClassDB::bind_method(D_METHOD("_bake_light", "light"), &VoxelChunkDefault::_bake_light);
ClassDB::bind_method(D_METHOD("_clear_baked_lights"), &VoxelChunkDefault::_clear_baked_lights);
ClassDB::bind_method(D_METHOD("_world_light_added", "light"), &VoxelChunkDefault::_world_light_added);
ClassDB::bind_method(D_METHOD("_world_light_removed", "light"), &VoxelChunkDefault::_world_light_removed);
BIND_CONSTANT(BUILD_PHASE_DONE);
BIND_CONSTANT(BUILD_PHASE_SETUP);

View File

@ -156,6 +156,9 @@ public:
int get_max_build_phase() const;
void set_max_build_phase(const int value);
bool get_lights_dirty() const;
void set_lights_dirty(const bool value);
//Lod
int get_lod_num() const;
void set_lod_num(const int value);
@ -180,8 +183,6 @@ public:
bool has_next_phase();
void next_phase();
void clear();
//Meshes
Dictionary get_mesh_rids();
void set_mesh_rids(const Dictionary &rids);
@ -209,6 +210,10 @@ public:
//Transform
void update_transforms();
//Lights
Ref<VoxelLight> get_light(const int index);
int get_light_count() const;
//Debug
void create_debug_immediate_geometry();
void free_debug_immediate_geometry();
@ -218,11 +223,13 @@ public:
void draw_debug_voxels(int max, Color color = Color(1, 1, 1));
void draw_debug_voxel_lights();
//Visibility
void visibility_changed(bool visible);
//free
void free_chunk();
//etc
void emit_build_finished();
void generate_random_ao(const int seed, const int octaves = 4, const int period = 30, const float persistence = 0.3, const float scale_factor = 0.6);
@ -236,8 +243,6 @@ protected:
virtual void _build_phase_process(int phase);
virtual void _build_phase_physics_process(int phase);
virtual void _add_light(int local_x, int local_y, int local_z, int size, Color color);
virtual void _clear_baked_lights();
virtual void _create_meshers();
virtual void _build(bool immediate);
virtual void _visibility_changed(bool visible);
@ -247,6 +252,13 @@ protected:
virtual void _physics_process(float delta);
virtual void _world_transform_changed();
//lights
virtual void _bake_lights();
virtual void _bake_light(Ref<VoxelLight> light);
virtual void _clear_baked_lights();
virtual void _world_light_added(const Ref<VoxelLight> &light);
virtual void _world_light_removed(const Ref<VoxelLight> &light);
void wait_and_finish_thread();
static void _bind_methods();
@ -260,6 +272,8 @@ protected:
int _max_build_phases;
bool _enabled;
bool _lights_dirty;
int _lod_size;
//lod
@ -281,6 +295,8 @@ protected:
PoolVector<Vector3> temp_arr_collider;
ActiveBuildPhaseType _active_build_phase_type;
Vector<Ref<VoxelLight> > _lights;
};
VARIANT_ENUM_CAST(VoxelChunkDefault::DefaultChannels);

View File

@ -610,111 +610,20 @@ Array VoxelChunk::bake_mesh_array_uv(Array arr, Ref<Texture> tex, float mul_colo
return arr;
}
void VoxelChunk::add_lights(Array lights) {
for (int i = 0; i < lights.size(); ++i) {
Ref<VoxelLight> light = Ref<VoxelLight>(lights.get(i));
if (light.is_valid()) {
add_voxel_light(light);
}
}
}
void VoxelChunk::add_voxel_light(Ref<VoxelLight> light) {
_voxel_lights.push_back(light);
}
void VoxelChunk::create_voxel_light(const Color color, const int size, const int x, const int y, const int z) {
Ref<VoxelLight> light;
light.instance();
light->set_world_position(_position_x * _size_x + x, _position_y * _size_y + y, _position_z * _size_z + z);
light->set_color(color);
light->set_size(size);
add_voxel_light(light);
}
void VoxelChunk::remove_voxel_light(Ref<VoxelLight> light) {
for (int i = 0; i < _voxel_lights.size(); ++i) {
if (_voxel_lights[i] == light) {
_voxel_lights.remove(i);
return;
}
}
}
void VoxelChunk::clear_voxel_lights() {
_voxel_lights.clear();
}
void VoxelChunk::add_lights_into(Array target) {
for (int i = 0; i < _voxel_lights.size(); ++i) {
target.append(_voxel_lights[i]);
}
}
void VoxelChunk::add_unique_lights_into(Array target) {
for (int i = 0; i < _voxel_lights.size(); ++i) {
Ref<VoxelLight> l = _voxel_lights.get(i);
bool append = true;
for (int j = 0; j < target.size(); ++j) {
Ref<VoxelLight> l2 = target.get(j);
if (!l2.is_valid())
continue;
if (l2->get_world_position() == l->get_world_position() && l2->get_size() == l->get_size()) {
append = false;
break;
}
}
if (append)
target.append(l);
}
}
Array VoxelChunk::get_lights() {
Array target;
for (int i = 0; i < _voxel_lights.size(); ++i) {
target.append(_voxel_lights[i]);
}
return target;
}
void VoxelChunk::bake_lights() {
clear_baked_lights();
for (int i = 0; i < _voxel_lights.size(); ++i) {
bake_light(_voxel_lights[i]);
}
if (has_method("_bake_lights"))
call("_bake_lights");
}
void VoxelChunk::bake_light(Ref<VoxelLight> light) {
ERR_FAIL_COND(!light.is_valid());
if (!light.is_valid())
return;
int wpx = light->get_world_position_x() - (_position_x * _size_x);
int wpy = light->get_world_position_y() - (_position_y * _size_y);
int wpz = light->get_world_position_z() - (_position_z * _size_z);
add_light(wpx, wpy, wpz, light->get_size(), light->get_color());
if (has_method("_bake_lights"))
call("_bake_light", light);
}
void VoxelChunk::clear_baked_lights() {
ERR_FAIL_COND_MSG(!has_method("_clear_baked_lights"), "VoxelChunk: _clear_baked_lights() is missing! Please implement it!");
call("_clear_baked_lights");
}
void VoxelChunk::add_light(int local_x, int local_y, int local_z, int size, Color color) {
ERR_FAIL_COND_MSG(!has_method("_add_light"), "VoxelChunk: _add_light() is missing! Please implement it!");
call("_add_light", local_x, local_y, local_z, size, color);
}
void VoxelChunk::add_prop_light(Ref<VoxelLight> light) {
bake_light(light);
if (has_method("_clear_baked_lights"))
call("_clear_baked_lights");
}
void VoxelChunk::add_prop(Ref<VoxelChunkPropData> prop) {
@ -767,6 +676,14 @@ void VoxelChunk::visibility_changed(bool visible) {
if (has_method("_visibility_changed"))
call("_visibility_changed", _is_visible);
}
void VoxelChunk::world_light_added(const Ref<VoxelLight> &light) {
if (has_method("_world_light_added"))
call("_world_light_added", light);
}
void VoxelChunk::world_light_removed(const Ref<VoxelLight> &light) {
if (has_method("_world_light_removed"))
call("_world_light_removed", light);
}
Transform VoxelChunk::get_transform() const {
return _transform;
@ -806,8 +723,6 @@ VoxelChunk::VoxelChunk() {
}
VoxelChunk::~VoxelChunk() {
_voxel_lights.clear();
_meshers.clear();
if (_library.is_valid()) {
@ -886,7 +801,14 @@ void VoxelChunk::_bind_methods() {
BIND_VMETHOD(MethodInfo("_prop_added", PropertyInfo(Variant::OBJECT, "prop", PROPERTY_HINT_RESOURCE_TYPE, "VoxelChunkPropData")));
BIND_VMETHOD(MethodInfo("_create_meshers"));
BIND_VMETHOD(MethodInfo("_setup_channels"));
BIND_VMETHOD(MethodInfo("_add_light", PropertyInfo(Variant::INT, "local_x"), PropertyInfo(Variant::INT, "local_y"), PropertyInfo(Variant::INT, "local_z"), PropertyInfo(Variant::INT, "size"), PropertyInfo(Variant::COLOR, "color")));
BIND_VMETHOD(MethodInfo("_bake_lights"));
BIND_VMETHOD(MethodInfo("_bake_light", PropertyInfo(Variant::OBJECT, "light", PROPERTY_HINT_RESOURCE_TYPE, "VoxelLight")));
BIND_VMETHOD(MethodInfo("_clear_baked_lights"));
ClassDB::bind_method(D_METHOD("bake_lights"), &VoxelChunk::bake_lights);
ClassDB::bind_method(D_METHOD("bake_light", "light"), &VoxelChunk::bake_light);
ClassDB::bind_method(D_METHOD("clear_baked_lights"), &VoxelChunk::clear_baked_lights);
BIND_VMETHOD(MethodInfo("_enter_tree"));
BIND_VMETHOD(MethodInfo("_exit_tree"));
@ -894,8 +816,17 @@ void VoxelChunk::_bind_methods() {
BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::REAL, "delta")));
BIND_VMETHOD(MethodInfo("_world_transform_changed"));
BIND_VMETHOD(MethodInfo("_visibility_changed", PropertyInfo(Variant::BOOL, "visible")));
BIND_VMETHOD(MethodInfo("_world_light_added", PropertyInfo(Variant::OBJECT, "light", PROPERTY_HINT_RESOURCE_TYPE, "VoxelLight")));
BIND_VMETHOD(MethodInfo("_world_light_removed", PropertyInfo(Variant::OBJECT, "light", PROPERTY_HINT_RESOURCE_TYPE, "VoxelLight")));
ClassDB::bind_method(D_METHOD("enter_tree"), &VoxelChunk::enter_tree);
ClassDB::bind_method(D_METHOD("exit_tree"), &VoxelChunk::exit_tree);
ClassDB::bind_method(D_METHOD("process", "delta"), &VoxelChunk::process);
ClassDB::bind_method(D_METHOD("physics_process", "delta"), &VoxelChunk::physics_process);
ClassDB::bind_method(D_METHOD("world_transform_changed"), &VoxelChunk::world_transform_changed);
ClassDB::bind_method(D_METHOD("visibility_changed", "visible"), &VoxelChunk::visibility_changed);
ClassDB::bind_method(D_METHOD("world_light_added", "light"), &VoxelChunk::world_light_added);
ClassDB::bind_method(D_METHOD("world_light_removed", "light"), &VoxelChunk::world_light_removed);
ClassDB::bind_method(D_METHOD("get_process"), &VoxelChunk::get_process);
ClassDB::bind_method(D_METHOD("set_process", "value"), &VoxelChunk::set_process);
@ -1020,20 +951,6 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("bake_mesh_array_uv", "arr", "tex", "mul_color"), &VoxelChunk::bake_mesh_array_uv, DEFVAL(0.7));
//Meshes
ClassDB::bind_method(D_METHOD("add_lights", "lights"), &VoxelChunk::add_lights);
ClassDB::bind_method(D_METHOD("add_voxel_light", "light"), &VoxelChunk::add_voxel_light);
ClassDB::bind_method(D_METHOD("create_voxel_light", "color", "size", "x", "y", "z"), &VoxelChunk::create_voxel_light);
ClassDB::bind_method(D_METHOD("remove_voxel_light", "light"), &VoxelChunk::remove_voxel_light);
ClassDB::bind_method(D_METHOD("clear_voxel_lights"), &VoxelChunk::clear_voxel_lights);
ClassDB::bind_method(D_METHOD("add_lights_into", "lights"), &VoxelChunk::add_lights_into);
ClassDB::bind_method(D_METHOD("add_unique_lights_into", "lights"), &VoxelChunk::add_unique_lights_into);
ClassDB::bind_method(D_METHOD("get_lights"), &VoxelChunk::get_lights);
ClassDB::bind_method(D_METHOD("bake_lights"), &VoxelChunk::bake_lights);
ClassDB::bind_method(D_METHOD("bake_light", "light"), &VoxelChunk::bake_light);
ClassDB::bind_method(D_METHOD("add_prop_light", "light"), &VoxelChunk::add_prop_light);
ClassDB::bind_method(D_METHOD("add_prop", "prop"), &VoxelChunk::add_prop);
ClassDB::bind_method(D_METHOD("get_prop", "index"), &VoxelChunk::get_prop);

View File

@ -177,25 +177,11 @@ public:
Array merge_mesh_array(Array arr) const;
Array bake_mesh_array_uv(Array arr, Ref<Texture> tex, float mul_color = 0.7) const;
//lights
void add_lights(Array lights);
void add_voxel_light(Ref<VoxelLight> light);
void create_voxel_light(const Color color, const int size, const int x, const int y, const int z);
void remove_voxel_light(Ref<VoxelLight> light);
void clear_voxel_lights();
void add_lights_into(Array target);
void add_unique_lights_into(Array target);
Array get_lights();
//light Baking
void bake_lights();
void bake_light(Ref<VoxelLight> light);
void clear_baked_lights();
void add_light(int local_x, int local_y, int local_z, int size, Color color);
void add_prop_light(Ref<VoxelLight> light);
//props
void add_prop(Ref<VoxelChunkPropData> prop);
Ref<VoxelChunkPropData> get_prop(int index);
@ -211,6 +197,8 @@ public:
void physics_process(float delta);
void world_transform_changed();
void visibility_changed(bool visible);
void world_light_added(const Ref<VoxelLight> &light);
void world_light_removed(const Ref<VoxelLight> &light);
Transform get_transform() const;
void set_transform(const Transform &transform);
@ -256,8 +244,6 @@ protected:
Vector<uint8_t *> _channels;
Vector<Ref<VoxelLight> > _voxel_lights;
float _voxel_scale;
Ref<VoxelmanLibrary> _library;

View File

@ -279,7 +279,7 @@ int VoxelWorld::get_generation_size() {
return _generating.size();
}
void VoxelWorld::clear() {
void VoxelWorld::clear_chunks() {
for (int i = 0; i < _chunks_vector.size(); ++i) {
_chunks_vector.get(i)->exit_tree();
}
@ -413,6 +413,81 @@ void VoxelWorld::set_chunks(const Vector<Variant> &chunks) {
}
}
//Lights
void VoxelWorld::add_light(const Ref<VoxelLight> &light) {
_lights.push_back(light);
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
if (chunk.is_valid()) {
chunk->world_light_added(light);
}
}
}
Ref<VoxelLight> VoxelWorld::get_light(const int index) {
ERR_FAIL_INDEX_V(index, _lights.size(), Ref<VoxelLight>());
return _lights.get(index);
}
void VoxelWorld::remove_light(const int index) {
ERR_FAIL_INDEX(index, _lights.size());
Ref<VoxelLight> light = _lights[index];
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
if (chunk.is_valid()) {
chunk->world_light_removed(light);
}
}
}
int VoxelWorld::get_light_count() const {
return _lights.size();
}
void VoxelWorld::clear_lights() {
for (int i = 0; i < _lights.size(); ++i) {
Ref<VoxelLight> light = _lights[i];
if (!light.is_valid())
continue;
for (int j = 0; j < _chunks_vector.size(); ++j) {
Ref<VoxelChunk> chunk = _chunks_vector[j];
if (chunk.is_valid()) {
chunk->world_light_removed(light);
}
}
}
_lights.clear();
}
Vector<Variant> VoxelWorld::get_lights() {
Vector<Variant> r;
for (int i = 0; i < _lights.size(); i++) {
#if VERSION_MAJOR < 4
r.push_back(_lights[i].get_ref_ptr());
#else
r.push_back(_lights[i]);
#endif
}
return r;
}
void VoxelWorld::set_lights(const Vector<Variant> &chunks) {
clear_lights();
for (int i = 0; i < chunks.size(); ++i) {
Ref<VoxelLight> light = Ref<VoxelLight>(chunks[i]);
add_light(light);
}
}
VoxelWorld::VoxelWorld() {
_editable = false;
@ -448,6 +523,8 @@ VoxelWorld ::~VoxelWorld() {
_generation_queue.clear();
_generating.clear();
_lights.clear();
}
void VoxelWorld::_generate_chunk(Ref<VoxelChunk> chunk) {
@ -667,7 +744,7 @@ void VoxelWorld::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_generation_index", "index"), &VoxelWorld::remove_generation_index);
ClassDB::bind_method(D_METHOD("get_generation_size"), &VoxelWorld::get_generation_size);
ClassDB::bind_method(D_METHOD("clear"), &VoxelWorld::clear);
ClassDB::bind_method(D_METHOD("clear_chunks"), &VoxelWorld::clear_chunks);
ADD_SIGNAL(MethodInfo("generation_finished"));
BIND_VMETHOD(MethodInfo("_generation_finished"));
@ -685,4 +762,14 @@ void VoxelWorld::_bind_methods() {
ClassDB::bind_method(D_METHOD("can_chunk_do_build_step"), &VoxelWorld::can_chunk_do_build_step);
ClassDB::bind_method(D_METHOD("is_position_walkable", "position"), &VoxelWorld::is_position_walkable);
ClassDB::bind_method(D_METHOD("on_chunk_mesh_generation_finished", "chunk"), &VoxelWorld::on_chunk_mesh_generation_finished);
//Lights
ClassDB::bind_method(D_METHOD("add_light", "light"), &VoxelWorld::add_light);
ClassDB::bind_method(D_METHOD("get_light", "index"), &VoxelWorld::get_light);
ClassDB::bind_method(D_METHOD("remove_light", "index"), &VoxelWorld::remove_light);
ClassDB::bind_method(D_METHOD("get_light_count"), &VoxelWorld::get_light_count);
ClassDB::bind_method(D_METHOD("clear_lights"), &VoxelWorld::clear_lights);
ClassDB::bind_method(D_METHOD("get_lights"), &VoxelWorld::get_lights);
ClassDB::bind_method(D_METHOD("set_lights", "chunks"), &VoxelWorld::set_lights);
}

View File

@ -100,12 +100,14 @@ public:
void set_player(Spatial *player);
void set_player_bind(Node *player);
//World Areas
Ref<WorldArea> get_world_area(const int index) const;
void add_world_area(Ref<WorldArea> area);
void remove_world_area(const int index);
void clear_world_areas();
int get_world_area_count() const;
//Chunks
void add_chunk(Ref<VoxelChunk> chunk, const int x, const int y, const int z);
bool has_chunk(const int x, const int y, const int z) const;
Ref<VoxelChunk> get_chunk(const int x, const int y, const int z);
@ -125,7 +127,7 @@ public:
void remove_generation_index(int index);
int get_generation_size();
void clear();
void clear_chunks();
Ref<VoxelChunk> get_or_create_chunk(int x, int y, int z);
Ref<VoxelChunk> create_chunk(int x, int y, int z);
@ -140,6 +142,16 @@ public:
Vector<Variant> get_chunks();
void set_chunks(const Vector<Variant> &chunks);
//Lights
void add_light(const Ref<VoxelLight> &light);
Ref<VoxelLight> get_light(const int index);
void remove_light(const int index);
int get_light_count() const;
void clear_lights();
Vector<Variant> get_lights();
void set_lights(const Vector<Variant> &chunks);
VoxelWorld();
~VoxelWorld();
@ -214,6 +226,8 @@ private:
Vector<Ref<VoxelChunk> > _generating;
int _max_frame_chunk_build_steps;
int _num_frame_chunk_build_steps;
Vector<Ref<VoxelLight> > _lights;
};
_FORCE_INLINE_ bool operator==(const VoxelWorld::IntPos &a, const VoxelWorld::IntPos &b) {