VoxelChunk now inherits from Resource instead of from Spatial. This is to make the scene cleaner (especially after I implement the world editor plugin). As a small bonus this should also make multithreading-related crashes harder to create, as manipulating the Scenetree from a thread by accident is now a lot harder.

This commit is contained in:
Relintai 2020-04-02 21:28:19 +02:00
parent 599b3eb8ea
commit 9da5d2e2d0
21 changed files with 438 additions and 330 deletions

View File

@ -24,31 +24,17 @@ SOFTWARE.
#include "../world/voxel_chunk.h"
bool GroundClutter::should_spawn(VoxelChunk *chunk, int x, int y, int z) {
bool GroundClutter::should_spawn(Ref<VoxelChunk> chunk, int x, int y, int z) {
if (has_method("_should_spawn"))
return call("_should_spawn", chunk, x, y, z);
return false;
}
bool GroundClutter::should_spawn_bind(Node *chunk, int x, int y, int z) {
VoxelChunk *c = Object::cast_to<VoxelChunk>(chunk);
ERR_FAIL_COND_V(!ObjectDB::instance_validate(c), false);
return should_spawn(c, x, y, z);
}
void GroundClutter::add_meshes_to(Ref<VoxelMesher> mesher, VoxelChunk *chunk, int x, int y, int z) {
void GroundClutter::add_meshes_to(Ref<VoxelMesher> mesher, Ref<VoxelChunk> chunk, int x, int y, int z) {
if (has_method("_add_meshes_to"))
call("_add_meshes_to", mesher, chunk, x, y, z);
}
void GroundClutter::add_meshes_to_bind(Ref<VoxelMesher> mesher, Node *chunk, int x, int y, int z) {
VoxelChunk *c = Object::cast_to<VoxelChunk>(chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(c));
add_meshes_to(mesher, c, x, y, z);
}
void GroundClutter::add_textures_to(Ref<TexturePacker> packer) {
if (has_method("_add_textures_to"))
@ -66,7 +52,7 @@ void GroundClutter::_bind_methods() {
BIND_VMETHOD(MethodInfo("_add_meshes_to", PropertyInfo(Variant::OBJECT, "mesher", PROPERTY_HINT_RESOURCE_TYPE, "VoxelMesher"), PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "VoxelChunk"), PropertyInfo(Variant::INT, "x"), PropertyInfo(Variant::INT, "y"), PropertyInfo(Variant::INT, "z")));
BIND_VMETHOD(MethodInfo("_add_textures_to", PropertyInfo(Variant::OBJECT, "packer", PROPERTY_HINT_RESOURCE_TYPE, "TexturePacker")));
ClassDB::bind_method(D_METHOD("should_spawn", "chunk", "x", "y", "z"), &GroundClutter::should_spawn_bind);
ClassDB::bind_method(D_METHOD("add_meshes_to", "mesher", "chunk", "x", "y", "z"), &GroundClutter::add_meshes_to_bind);
ClassDB::bind_method(D_METHOD("should_spawn", "chunk", "x", "y", "z"), &GroundClutter::should_spawn);
ClassDB::bind_method(D_METHOD("add_meshes_to", "mesher", "chunk", "x", "y", "z"), &GroundClutter::add_meshes_to);
ClassDB::bind_method(D_METHOD("add_textures_to", "packer"), &GroundClutter::add_textures_to);
}

View File

@ -35,11 +35,9 @@ class GroundClutter : public Resource {
GDCLASS(GroundClutter, Resource);
public:
bool should_spawn(VoxelChunk *chunk, int x, int y, int z);
bool should_spawn_bind(Node *chunk, int x, int y, int z);
bool should_spawn(Ref<VoxelChunk> chunk, int x, int y, int z);
void add_meshes_to(Ref<VoxelMesher> mesher, VoxelChunk *chunk, int x, int y, int z);
void add_meshes_to_bind(Ref<VoxelMesher> mesher, Node *chunk, int x, int y, int z);
void add_meshes_to(Ref<VoxelMesher> mesher, Ref<VoxelChunk> chunk, int x, int y, int z);
void add_textures_to(Ref<TexturePacker> packer);
GroundClutter();

View File

@ -24,10 +24,7 @@ SOFTWARE.
#include "../world/voxel_chunk.h"
void VoxelmanLevelGenerator::generate_chunk_bind(Node *chunk) {
generate_chunk(Object::cast_to<VoxelChunk>(chunk));
}
void VoxelmanLevelGenerator::generate_chunk(VoxelChunk *chunk) {
void VoxelmanLevelGenerator::generate_chunk(Ref<VoxelChunk> chunk) {
if (has_method("_generate_chunk")) {
call("_generate_chunk", chunk);
}
@ -42,5 +39,5 @@ VoxelmanLevelGenerator::~VoxelmanLevelGenerator() {
void VoxelmanLevelGenerator::_bind_methods() {
BIND_VMETHOD(MethodInfo("_generate_chunk", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "VoxelChunk")));
ClassDB::bind_method(D_METHOD("generate_chunk", "chunk"), &VoxelmanLevelGenerator::generate_chunk_bind);
ClassDB::bind_method(D_METHOD("generate_chunk", "chunk"), &VoxelmanLevelGenerator::generate_chunk);
}

View File

@ -31,8 +31,7 @@ class VoxelmanLevelGenerator : public Resource {
GDCLASS(VoxelmanLevelGenerator, Resource);
public:
void generate_chunk_bind(Node *chunk);
void generate_chunk(VoxelChunk *chunk);
void generate_chunk(Ref<VoxelChunk> chunk);
VoxelmanLevelGenerator();
~VoxelmanLevelGenerator();

View File

@ -192,8 +192,8 @@ void VoxelCubePoints::recalculate_point(int point) {
_points[point] = dynamic_offset;
}
void VoxelCubePoints::refresh_neighbours(VoxelChunk *chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelCubePoints::refresh_neighbours(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
int neighbours = 0;
@ -429,12 +429,8 @@ void VoxelCubePoints::refresh_neighbours(VoxelChunk *chunk) {
_point_neighbours[P111] = neighbours;
}
void VoxelCubePoints::setup_bind(Node *chunk, int x, int y, int z, int size) {
setup(Object::cast_to<VoxelChunk>(chunk), x, y, z, size);
}
void VoxelCubePoints::setup(VoxelChunk *chunk, int x, int y, int z, int size) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelCubePoints::setup(Ref<VoxelChunk> chunk, int x, int y, int z, int size) {
ERR_FAIL_COND(!chunk.is_valid());
ERR_FAIL_COND(size <= 0);
ERR_FAIL_COND(!chunk->validate_channel_data_position(x + size, y + size, z + size) || !chunk->validate_channel_data_position(x, y, z));
@ -783,7 +779,7 @@ void VoxelCubePoints::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "size"), "set_size", "get_size");
ClassDB::bind_method(D_METHOD("refresh_points"), &VoxelCubePoints::refresh_points);
ClassDB::bind_method(D_METHOD("setup", "chunk", "x", "y", "z", "size"), &VoxelCubePoints::setup_bind, DEFVAL(1));
ClassDB::bind_method(D_METHOD("setup", "chunk", "x", "y", "z", "size"), &VoxelCubePoints::setup, DEFVAL(1));
ClassDB::bind_method(D_METHOD("get_point_index", "face", "index"), &VoxelCubePoints::get_point_index);
ClassDB::bind_method(D_METHOD("get_point_uv_direction", "face", "index"), &VoxelCubePoints::get_point_uv_direction);

View File

@ -112,9 +112,8 @@ public:
void refresh_points();
void recalculate_point(int point);
void refresh_neighbours(VoxelChunk *chunk);
void setup_bind(Node *chunk, int x, int y, int z, int size = 1);
void setup(VoxelChunk *chunk, int x, int y, int z, int size = 1);
void refresh_neighbours(Ref<VoxelChunk> chunk);
void setup(Ref<VoxelChunk> chunk, int x, int y, int z, int size = 1);
void reset();

View File

@ -24,10 +24,10 @@ SOFTWARE.
#include "../../world/voxel_chunk_default.h"
void VoxelMesherCubic::_add_chunk(Node *p_chunk) {
VoxelChunkDefault *chunk = Object::cast_to<VoxelChunkDefault>(p_chunk);
void VoxelMesherCubic::_add_chunk(Ref<VoxelChunk> p_chunk) {
Ref<VoxelChunkDefault> chunk = p_chunk;
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
ERR_FAIL_COND(!chunk.is_valid());
chunk->generate_ao();

View File

@ -35,7 +35,7 @@ class VoxelMesherCubic : public VoxelMesher {
GDCLASS(VoxelMesherCubic, VoxelMesher);
public:
void _add_chunk(Node *p_chunk);
void _add_chunk(Ref<VoxelChunk> p_chunk);
VoxelMesherCubic();
~VoxelMesherCubic();

View File

@ -35,7 +35,7 @@ void VoxelMesherTransvoxel::set_texture_scale(const int value) {
_texture_scale = value;
}
void VoxelMesherTransvoxel::get_voxel_type_array(int *arr, VoxelChunk *chunk, const int x, const int y, const int z, const int size) {
void VoxelMesherTransvoxel::get_voxel_type_array(int *arr, Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size) {
arr[0] = chunk->get_voxel(x, y, z, VoxelChunkDefault::DEFAULT_CHANNEL_TYPE);
arr[1] = chunk->get_voxel(x, y + size, z, VoxelChunkDefault::DEFAULT_CHANNEL_TYPE);
arr[2] = chunk->get_voxel(x, y, z + size, VoxelChunkDefault::DEFAULT_CHANNEL_TYPE);
@ -74,7 +74,7 @@ int VoxelMesherTransvoxel::get_case_code_from_arr(const int *data) {
return case_code;
}
int VoxelMesherTransvoxel::get_case_code(VoxelChunk *chunk, const int x, const int y, const int z, const int size) {
int VoxelMesherTransvoxel::get_case_code(Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size) {
int case_code = 0;
if (chunk->get_voxel(x, y, z, VoxelChunkDefault::DEFAULT_CHANNEL_TYPE) != 0)
@ -104,7 +104,7 @@ int VoxelMesherTransvoxel::get_case_code(VoxelChunk *chunk, const int x, const i
return case_code;
}
int VoxelMesherTransvoxel::get_voxel_type(VoxelChunk *chunk, const int x, const int y, const int z, const int size) {
int VoxelMesherTransvoxel::get_voxel_type(Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size) {
int type = 0;
type = chunk->get_voxel(x, y + size, z, VoxelChunkDefault::DEFAULT_CHANNEL_TYPE);
@ -147,10 +147,10 @@ int VoxelMesherTransvoxel::get_voxel_type(VoxelChunk *chunk, const int x, const
return type;
}
void VoxelMesherTransvoxel::_add_chunk(Node *p_chunk) {
VoxelChunkDefault *chunk = Object::cast_to<VoxelChunkDefault>(p_chunk);
void VoxelMesherTransvoxel::_add_chunk(Ref<VoxelChunk> p_chunk) {
Ref<VoxelChunkDefault> chunk = p_chunk;
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
ERR_FAIL_COND(!chunk.is_valid());
chunk->generate_ao();

View File

@ -69,11 +69,11 @@ public:
void set_texture_scale(const int value);
//arr should have a size of 8
void get_voxel_type_array(int *arr, VoxelChunk *chunk, const int x, const int y, const int z, const int size = 1);
void get_voxel_type_array(int *arr, Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size = 1);
int get_case_code_from_arr(const int *data);
int get_case_code(VoxelChunk *chunk, const int x, const int y, const int z, const int size = 1);
int get_voxel_type(VoxelChunk *chunk, const int x, const int y, const int z, const int size = 1);
void _add_chunk(Node *p_chunk);
int get_case_code(Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size = 1);
int get_voxel_type(Ref<VoxelChunk> chunk, const int x, const int y, const int z, const int size = 1);
void _add_chunk(Ref<VoxelChunk> p_chunk);
Vector3 corner_id_to_vertex(int corner_id) const;

View File

@ -394,26 +394,16 @@ void VoxelMesher::reset() {
_last_tangent = Plane();
}
void VoxelMesher::add_chunk_bind(Node *chunk) {
VoxelChunk *vchunk = Object::cast_to<VoxelChunk>(chunk);
add_chunk(vchunk);
}
void VoxelMesher::add_chunk(VoxelChunk *chunk) {
void VoxelMesher::add_chunk(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!has_method("_add_chunk"));
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
ERR_FAIL_COND(!chunk.is_valid());
call("_add_chunk", chunk);
}
void VoxelMesher::add_chunk_liquid_bind(Node *chunk) {
VoxelChunk *vchunk = Object::cast_to<VoxelChunk>(chunk);
add_chunk_liquid(vchunk);
}
void VoxelMesher::add_chunk_liquid(VoxelChunk *chunk) {
void VoxelMesher::add_chunk_liquid(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!has_method("_add_chunk_liquid"));
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
ERR_FAIL_COND(!chunk.is_valid());
call("_add_chunk_liquid", chunk);
}
@ -568,21 +558,14 @@ void VoxelMesher::_add_mesher(const Ref<VoxelMesher> &mesher) {
}
}
void VoxelMesher::bake_colors_bind(Node *chunk) {
VoxelChunk *vchunk = Object::cast_to<VoxelChunk>(chunk);
bake_colors(vchunk);
}
void VoxelMesher::bake_colors(VoxelChunk *chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelMesher::bake_colors(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
if (has_method("_bake_colors"))
call("_bake_colors", chunk);
}
void VoxelMesher::_bake_colors(Node *p_chunk) {
VoxelChunk *chunk = Object::cast_to<VoxelChunk>(p_chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelMesher::_bake_colors(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
if (_vertices.size() == 0)
return;
@ -637,21 +620,14 @@ void VoxelMesher::_bake_colors(Node *p_chunk) {
}
}
void VoxelMesher::bake_liquid_colors_bind(Node *chunk) {
VoxelChunk *vchunk = Object::cast_to<VoxelChunk>(chunk);
bake_liquid_colors(vchunk);
}
void VoxelMesher::bake_liquid_colors(VoxelChunk *chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelMesher::bake_liquid_colors(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
if (has_method("_bake_liquid_colors"))
call("_bake_liquid_colors", chunk);
}
void VoxelMesher::_bake_liquid_colors(Node *p_chunk) {
VoxelChunk *chunk = Object::cast_to<VoxelChunk>(p_chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelMesher::_bake_liquid_colors(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
if (_vertices.size() == 0)
return;
@ -1095,8 +1071,8 @@ void VoxelMesher::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_uv_margin", "value"), &VoxelMesher::set_uv_margin);
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "uv_margin"), "set_uv_margin", "get_uv_margin");
ClassDB::bind_method(D_METHOD("add_chunk", "chunk"), &VoxelMesher::add_chunk_bind);
ClassDB::bind_method(D_METHOD("add_chunk_liquid", "chunk"), &VoxelMesher::add_chunk_liquid_bind);
ClassDB::bind_method(D_METHOD("add_chunk", "chunk"), &VoxelMesher::add_chunk);
ClassDB::bind_method(D_METHOD("add_chunk_liquid", "chunk"), &VoxelMesher::add_chunk_liquid);
ClassDB::bind_method(D_METHOD("add_mesh_data_resource", "mesh", "position", "rotation", "scale", "uv_rect"), &VoxelMesher::add_mesh_data_resource, DEFVAL(Rect2(0, 0, 1, 1)), DEFVAL(Vector3(1.0, 1.0, 1.0)), DEFVAL(Vector3()), DEFVAL(Vector3()));
ClassDB::bind_method(D_METHOD("add_mesh_data_resource_transform", "mesh", "transform", "uv_rect"), &VoxelMesher::add_mesh_data_resource_transform, DEFVAL(Rect2(0, 0, 1, 1)));
@ -1105,10 +1081,10 @@ void VoxelMesher::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_mesher", "mesher"), &VoxelMesher::add_mesher);
ClassDB::bind_method(D_METHOD("_add_mesher", "mesher"), &VoxelMesher::_add_mesher);
ClassDB::bind_method(D_METHOD("bake_colors", "chunk"), &VoxelMesher::bake_colors_bind);
ClassDB::bind_method(D_METHOD("bake_colors", "chunk"), &VoxelMesher::bake_colors);
ClassDB::bind_method(D_METHOD("_bake_colors", "chunk"), &VoxelMesher::_bake_colors);
ClassDB::bind_method(D_METHOD("bake_liquid_colors", "chunk"), &VoxelMesher::bake_liquid_colors_bind);
ClassDB::bind_method(D_METHOD("bake_liquid_colors", "chunk"), &VoxelMesher::bake_liquid_colors);
ClassDB::bind_method(D_METHOD("_bake_liquid_colors", "chunk"), &VoxelMesher::_bake_liquid_colors);
ClassDB::bind_method(D_METHOD("get_vertices"), &VoxelMesher::get_vertices);

View File

@ -110,11 +110,9 @@ public:
void reset();
void add_chunk_bind(Node *chunk);
void add_chunk(VoxelChunk *chunk);
void add_chunk(Ref<VoxelChunk> chunk);
void add_chunk_liquid_bind(Node *chunk);
void add_chunk_liquid(VoxelChunk *chunk);
void add_chunk_liquid(Ref<VoxelChunk> chunk);
void add_mesh_data_resource(Ref<MeshDataResource> mesh, const Vector3 position = Vector3(0, 0, 0), const Vector3 rotation = Vector3(0, 0, 0), const Vector3 scale = Vector3(1.0, 1.0, 1.0), const Rect2 uv_rect = Rect2(0, 0, 1, 1));
void add_mesh_data_resource_transform(Ref<MeshDataResource> mesh, const Transform transform, const Rect2 uv_rect = Rect2(0, 0, 1, 1));
@ -122,13 +120,11 @@ public:
void add_mesher(const Ref<VoxelMesher> &mesher);
void _add_mesher(const Ref<VoxelMesher> &mesher);
void bake_colors_bind(Node *chunk);
void bake_colors(VoxelChunk *chunk);
void _bake_colors(Node *p_chunk);
void bake_colors(Ref<VoxelChunk> chunk);
void _bake_colors(Ref<VoxelChunk> p_chunk);
void bake_liquid_colors_bind(Node *chunk);
void bake_liquid_colors(VoxelChunk *chunk);
void _bake_liquid_colors(Node *p_chunk);
void bake_liquid_colors(Ref<VoxelChunk> chunk);
void _bake_liquid_colors(Ref<VoxelChunk> p_chunk);
PoolVector<Vector3> build_collider() const;

View File

@ -105,8 +105,8 @@ void PropData::add_textures_into(Ref<TexturePacker> texture_packer) {
}
}
void PropData::add_prop_lights_into(VoxelChunk *chunk, Transform parent_transform, bool allow_snap) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void PropData::add_prop_lights_into(Ref<VoxelChunk> chunk, Transform parent_transform, bool allow_snap) {
ERR_FAIL_COND(!chunk.is_valid());
for (int i = 0; i < _props.size(); ++i) {
Ref<PropDataEntry> entry = _props.get(i);
@ -136,20 +136,13 @@ void PropData::add_prop_lights_into(VoxelChunk *chunk, Transform parent_transfor
if (pd->get_snap_to_mesh())
print_error(pd->get_name());
pd->add_prop_lights_into(chunk, get_next_snapped_prop_transform(chunk, parent_transform * pdataprop->get_transform(), pd->get_snap_to_mesh(), pd->get_snap_axis()), allow_snap);
pd->add_prop_lights_into(chunk, get_next_snapped_prop_transform(chunk->get_voxel_world(), parent_transform * pdataprop->get_transform(), pd->get_snap_to_mesh(), pd->get_snap_axis()), allow_snap);
} else {
pd->add_prop_lights_into(chunk, parent_transform * pdataprop->get_transform(), allow_snap);
}
}
}
}
void PropData::add_prop_lights_into_bind(Node *chunk, Transform parent_transform, bool allow_snap) {
VoxelChunk *c = Object::cast_to<VoxelChunk>(chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(c));
add_prop_lights_into(c, parent_transform, allow_snap);
}
void PropData::add_meshes_into(Ref<VoxelMesher> mesher, Ref<TexturePacker> texture_packer, Transform parent_transform, Spatial *snap_spatial) {
ERR_FAIL_COND(!mesher.is_valid());
@ -198,7 +191,7 @@ void PropData::add_meshes_into(Ref<VoxelMesher> mesher, Ref<TexturePacker> textu
}
}
void PropData::add_meshes_into_bind(Ref<VoxelMesher> mesher, Ref<TexturePacker> texture_packer, Transform parent_transform, Node *snap_spatial) {
Spatial *s = Object::cast_to<VoxelChunk>(snap_spatial);
Spatial *s = Object::cast_to<Spatial>(snap_spatial);
ERR_FAIL_COND(s != NULL && !ObjectDB::instance_validate(s));
@ -226,7 +219,7 @@ Transform PropData::get_next_snapped_prop_transform(Spatial *s, Transform parent
return parent_transform;
}
Transform PropData::get_next_snapped_prop_transform_bind(Node *spatial, Transform parent_transform, bool snap_to_mesh, Vector3 snap_axis) {
Spatial *s = Object::cast_to<VoxelChunk>(spatial);
Spatial *s = Object::cast_to<Spatial>(spatial);
ERR_FAIL_COND_V(!ObjectDB::instance_validate(s), parent_transform);
@ -263,7 +256,7 @@ void PropData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "props", PROPERTY_HINT_NONE, "17/17:PropDataEntry", PROPERTY_USAGE_DEFAULT, "PropDataEntry"), "set_props", "get_props");
ClassDB::bind_method(D_METHOD("add_textures_into", "texture_packer"), &PropData::add_textures_into);
ClassDB::bind_method(D_METHOD("add_prop_lights_into", "chunk", "parent_transform", "allow_snap"), &PropData::add_prop_lights_into_bind);
ClassDB::bind_method(D_METHOD("add_prop_lights_into", "chunk", "parent_transform", "allow_snap"), &PropData::add_prop_lights_into);
ClassDB::bind_method(D_METHOD("add_meshes_into", "mesher", "texture_packer", "parent_transform", "snap_spatial"), &PropData::add_meshes_into_bind);

View File

@ -66,8 +66,7 @@ public:
void set_props(const Vector<Variant> &props);
void add_textures_into(Ref<TexturePacker> texture_packer);
void add_prop_lights_into(VoxelChunk *chunk, Transform parent_transform, bool allow_snap);
void add_prop_lights_into_bind(Node *chunk, Transform parent_transform, bool allow_snap);
void add_prop_lights_into(Ref<VoxelChunk> chunk, Transform parent_transform, bool allow_snap);
void add_meshes_into(Ref<VoxelMesher> mesher, Ref<TexturePacker> texture_packer, Transform parent_transform, Spatial *snap_spatial = NULL);
void add_meshes_into_bind(Ref<VoxelMesher> mesher, Ref<TexturePacker> texture_packer, Transform parent_transform, Node *snap_spatial = NULL);

View File

@ -86,7 +86,7 @@ void BlockVoxelStructure::set_voxel_data(PoolByteArray p_arr, int p_x, int p_y,
}
//void BlockVoxelStructure::_write_to_chunk(Node *chunk) {
//VoxelChunk *c = Object::cast_to<VoxelChunk>(chunk);
//Ref<VoxelChunk> c = Object::cast_to<VoxelChunk>(chunk);
//}
void BlockVoxelStructure::clear() {

View File

@ -24,6 +24,29 @@ SOFTWARE.
#include "voxel_world.h"
_FORCE_INLINE_ bool VoxelChunk::get_process() const {
return _is_processing;
}
_FORCE_INLINE_ void VoxelChunk::set_process(const bool value) {
_is_processing = value;
}
_FORCE_INLINE_ bool VoxelChunk::get_physics_process() const {
return _is_phisics_processing;
}
_FORCE_INLINE_ void VoxelChunk::set_physics_process(const bool value) {
_is_phisics_processing = value;
}
bool VoxelChunk::get_visible() const {
return _is_visible;
}
void VoxelChunk::set_visible(const bool value) {
_is_visible = value;
visibility_changed(value);
}
_FORCE_INLINE_ bool VoxelChunk::get_is_generating() const {
return _is_generating;
}
@ -630,7 +653,43 @@ void VoxelChunk::free_spawn_props() {
_spawned_props.clear();
}
void VoxelChunk::enter_tree() {
if (has_method("_enter_tree"))
call("_enter_tree");
}
void VoxelChunk::exit_tree() {
if (has_method("_exit_tree"))
call("_exit_tree");
}
void VoxelChunk::process(float delta) {
if (has_method("_process"))
call("_process", delta);
}
void VoxelChunk::physics_process(float delta) {
if (has_method("_physics_process"))
call("_physics_process", delta);
}
void VoxelChunk::world_transform_changed() {
call("_world_transform_changed");
}
void VoxelChunk::visibility_changed(bool visible) {
if (has_method("_visibility_changed"))
call("_visibility_changed", _is_visible);
}
Transform VoxelChunk::get_transform() const {
return _transform;
}
void VoxelChunk::set_transform(const Transform &transform) {
_transform = transform;
}
VoxelChunk::VoxelChunk() {
_is_processing = false;
_is_phisics_processing = false;
_is_visible = true;
_is_generating = false;
_dirty = false;
_state = VOXEL_CHUNK_STATE_OK;
@ -675,6 +734,16 @@ VoxelChunk::~VoxelChunk() {
}
}
void VoxelChunk::_world_transform_changed() {
Transform wt;
if (_voxel_world != NULL) {
wt = _voxel_world->get_transform();
}
set_transform(wt * Transform(Basis(), Vector3(_position_x * static_cast<int>(_size_x) * _voxel_scale, _position_y * static_cast<int>(_size_y) * _voxel_scale, _position_z * static_cast<int>(_size_z) * _voxel_scale)));
}
/*
bool VoxelChunk::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
@ -728,6 +797,29 @@ void VoxelChunk::_bind_methods() {
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("_enter_tree"));
BIND_VMETHOD(MethodInfo("_exit_tree"));
BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::REAL, "delta")));
BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::REAL, "delta")));
BIND_VMETHOD(MethodInfo("_world_transform_changed"));
BIND_VMETHOD(MethodInfo("_visibility_changed", PropertyInfo(Variant::BOOL, "visible")));
ClassDB::bind_method(D_METHOD("visibility_changed", "visible"), &VoxelChunk::visibility_changed);
ClassDB::bind_method(D_METHOD("get_process"), &VoxelChunk::get_process);
ClassDB::bind_method(D_METHOD("set_process", "value"), &VoxelChunk::set_process);
ClassDB::bind_method(D_METHOD("get_physics_process"), &VoxelChunk::get_physics_process);
ClassDB::bind_method(D_METHOD("set_physics_process", "value"), &VoxelChunk::set_physics_process);
ClassDB::bind_method(D_METHOD("get_transform"), &VoxelChunk::get_transform);
ClassDB::bind_method(D_METHOD("set_transform", "value"), &VoxelChunk::set_transform);
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform");
ClassDB::bind_method(D_METHOD("get_visible"), &VoxelChunk::get_visible);
ClassDB::bind_method(D_METHOD("set_visible", "value"), &VoxelChunk::set_visible);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "get_visible");
ClassDB::bind_method(D_METHOD("get_is_generating"), &VoxelChunk::get_is_generating);
ClassDB::bind_method(D_METHOD("set_is_generating", "value"), &VoxelChunk::set_is_generating);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_generating"), "set_is_generating", "get_is_generating");
@ -857,4 +949,6 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("free_spawn_props"), &VoxelChunk::free_spawn_props);
ClassDB::bind_method(D_METHOD("create_meshers"), &VoxelChunk::create_meshers);
ClassDB::bind_method(D_METHOD("_world_transform_changed"), &VoxelChunk::_world_transform_changed);
}

View File

@ -23,7 +23,7 @@ SOFTWARE.
#ifndef VOXEL_CHUNK_H
#define VOXEL_CHUNK_H
#include "scene/3d/spatial.h"
#include "core/resource.h"
#include "core/engine.h"
#include "core/os/mutex.h"
@ -60,8 +60,8 @@ SOFTWARE.
class VoxelWorld;
class VoxelChunk : public Spatial {
GDCLASS(VoxelChunk, Spatial);
class VoxelChunk : public Resource {
GDCLASS(VoxelChunk, Resource);
_THREAD_SAFE_CLASS_
@ -71,6 +71,15 @@ public:
};
public:
bool get_process() const;
void set_process(const bool value);
bool get_physics_process() const;
void set_physics_process(const bool value);
bool get_visible() const;
void set_visible(const bool value);
bool get_is_generating() const;
void set_is_generating(bool value);
@ -189,10 +198,22 @@ public:
void free_spawn_props();
void enter_tree();
void exit_tree();
void process(float delta);
void physics_process(float delta);
void world_transform_changed();
void visibility_changed(bool visible);
Transform get_transform() const;
void set_transform(const Transform &transform);
VoxelChunk();
~VoxelChunk();
protected:
virtual void _world_transform_changed();
/*
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@ -200,6 +221,11 @@ protected:
*/
static void _bind_methods();
bool _is_processing;
bool _is_phisics_processing;
bool _is_visible;
bool _is_generating;
bool _dirty;
int _state;
@ -235,6 +261,8 @@ protected:
//spawned props
Vector<Node *> _spawned_props;
Transform _transform;
};
#endif

View File

@ -37,12 +37,21 @@ _FORCE_INLINE_ VoxelChunkDefault::ActiveBuildPhaseType VoxelChunkDefault::get_ac
return _active_build_phase_type;
}
_FORCE_INLINE_ void VoxelChunkDefault::set_active_build_phase_type(const VoxelChunkDefault::ActiveBuildPhaseType value) {
if (_active_build_phase_type == value)
return;
if (_active_build_phase_type == VoxelChunkDefault::BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
set_physics_process(false);
} else if (_active_build_phase_type == VoxelChunkDefault::BUILD_PHASE_TYPE_PROCESS) {
set_process(false);
}
_active_build_phase_type = value;
if (_active_build_phase_type == VoxelChunkDefault::BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
call_deferred("set_physics_process_internal", true);
} else {
call_deferred("set_physics_process_internal", false);
set_physics_process(true);
} else if (_active_build_phase_type == VoxelChunkDefault::BUILD_PHASE_TYPE_PROCESS) {
set_process(true);
}
}
@ -182,7 +191,7 @@ void VoxelChunkDefault::build_deferred() {
wait_and_finish_thread();
set_process_internal(true);
set_process(true);
_is_generating = true;
@ -201,7 +210,7 @@ void VoxelChunkDefault::build_prioritized() {
wait_and_finish_thread();
set_process_internal(true);
set_process(true);
_is_generating = true;
@ -528,7 +537,7 @@ void VoxelChunkDefault::create_meshes(const int mesh_index, const int mesh_count
VS::get_singleton()->instance_set_base(mesh_instance_rid, mesh_rid);
VS::get_singleton()->instance_set_transform(mesh_instance_rid, Transform(Basis(), Vector3(_position_x * _size_x * _voxel_scale, _position_y * _size_y * _voxel_scale, _position_z * _size_z * _voxel_scale)));
VS::get_singleton()->instance_set_transform(mesh_instance_rid, get_transform());
if (i != 0)
VS::get_singleton()->instance_set_visible(mesh_instance_rid, false);
@ -597,7 +606,7 @@ void VoxelChunkDefault::create_colliders(const int mesh_index, const int layer_m
PhysicsServer::get_singleton()->body_add_shape(body_rid, shape_rid);
PhysicsServer::get_singleton()->body_set_state(body_rid, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(_position_x * _size_x * _voxel_scale, _position_y * _size_y * _voxel_scale, _position_z * _size_z * _voxel_scale)));
PhysicsServer::get_singleton()->body_set_state(body_rid, PhysicsServer::BODY_STATE_TRANSFORM, get_transform());
PhysicsServer::get_singleton()->body_set_space(body_rid, get_voxel_world()->get_world()->get_space());
m[MESH_TYPE_INDEX_BODY] = body_rid;
@ -672,10 +681,10 @@ void VoxelChunkDefault::create_debug_immediate_geometry() {
_debug_drawer = memnew(ImmediateGeometry());
add_child(_debug_drawer);
_voxel_world->add_child(_debug_drawer);
if (Engine::get_singleton()->is_editor_hint())
_debug_drawer->set_owner(get_tree()->get_edited_scene_root());
_debug_drawer->set_owner(_voxel_world->get_tree()->get_edited_scene_root());
//_debug_drawer->set_transform(Transform(Basis(), Vector3(_position.x * _size.x * _voxel_scale, _position.y * _size.y * _voxel_scale, _position.z * _size.z * _voxel_scale)));
//_debug_drawer->set_transform(Transform(Basis(), Vector3(_position.x * _size.x * _voxel_scale, _position.y * _size.y * _voxel_scale, _position.z * _size.z * _voxel_scale)));
@ -783,10 +792,6 @@ void VoxelChunkDefault::draw_debug_voxel_lights() {
_debug_drawer->end();
}
void VoxelChunkDefault::visibility_changed(bool visible) {
call("visibility_changed", visible);
}
void VoxelChunkDefault::_visibility_changed(bool visible) {
if (visible) {
set_current_lod_level(_current_lod_level);
@ -801,6 +806,85 @@ void VoxelChunkDefault::_visibility_changed(bool visible) {
}
}
void VoxelChunkDefault::_exit_tree() {
if (_build_thread) {
_abort_build = true;
wait_and_finish_thread();
}
free_rids();
}
void VoxelChunkDefault::_process(float delta) {
if (!get_is_generating()) {
set_process(false);
}
if (!get_is_generating() || !has_next_phase() || _build_step_in_progress) {
return;
}
switch (_active_build_phase_type) {
case BUILD_PHASE_TYPE_PROCESS: {
if (!_voxel_world->can_chunk_do_build_step())
return;
_build_step_in_progress = true;
while (has_next_phase() && _active_build_phase_type == BUILD_PHASE_TYPE_PROCESS) {
build_phase_process();
if (!get_build_phase_done())
break;
}
_build_step_in_progress = false;
return;
}
case BUILD_PHASE_TYPE_NORMAL: {
//normal mode -> build step is not in progress -> need to restart building
if (!_voxel_world->can_chunk_do_build_step())
return;
build_step();
return;
}
case BUILD_PHASE_TYPE_PHYSICS_PROCESS:
return;
}
}
void VoxelChunkDefault::_physics_process(float delta) {
if (!get_is_generating() || !has_next_phase() || _build_step_in_progress) {
return;
}
if (_active_build_phase_type == BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
if (!_voxel_world->can_chunk_do_build_step())
return;
_build_step_in_progress = true;
while (has_next_phase() && _active_build_phase_type == BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
build_phase_physics_process();
if (!get_build_phase_done())
break;
}
_build_step_in_progress = false;
return;
}
}
void VoxelChunkDefault::_world_transform_changed() {
VoxelChunk::_world_transform_changed();
update_transforms();
}
void VoxelChunkDefault::free_chunk() {
free_rids();
}
@ -1278,96 +1362,6 @@ void VoxelChunkDefault::_build(bool immediate) {
build_deferred();
}
void VoxelChunkDefault::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (is_inside_tree())
visibility_changed(is_visible_in_tree());
}
case NOTIFICATION_ENTER_TREE: {
set_notify_transform(true);
} break;
case NOTIFICATION_EXIT_TREE: {
if (_build_thread) {
_abort_build = true;
wait_and_finish_thread();
}
free_rids();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
if (!get_is_generating()) {
set_process_internal(false);
}
if (!get_is_generating() || !has_next_phase() || _build_step_in_progress) {
return;
}
switch (_active_build_phase_type) {
case BUILD_PHASE_TYPE_PROCESS: {
if (!_voxel_world->can_chunk_do_build_step())
return;
_build_step_in_progress = true;
while (has_next_phase() && _active_build_phase_type == BUILD_PHASE_TYPE_PROCESS) {
build_phase_process();
if (!get_build_phase_done())
break;
}
_build_step_in_progress = false;
return;
}
case BUILD_PHASE_TYPE_NORMAL: {
//normal mode -> build step is not in progress -> need to restart building
if (!_voxel_world->can_chunk_do_build_step())
return;
build_step();
return;
}
case BUILD_PHASE_TYPE_PHYSICS_PROCESS:
return;
}
break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (!get_is_generating() || !has_next_phase() || _build_step_in_progress) {
return;
}
if (_active_build_phase_type == BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
if (!_voxel_world->can_chunk_do_build_step())
return;
_build_step_in_progress = true;
while (has_next_phase() && _active_build_phase_type == BUILD_PHASE_TYPE_PHYSICS_PROCESS) {
build_phase_physics_process();
if (!get_build_phase_done())
break;
}
_build_step_in_progress = false;
return;
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
update_transforms();
} break;
}
}
}
void VoxelChunkDefault::wait_and_finish_thread() {
if (_build_thread) {
Thread::wait_to_finish(_build_thread);
@ -1490,8 +1484,9 @@ void VoxelChunkDefault::_bind_methods() {
ClassDB::bind_method(D_METHOD("_create_meshers"), &VoxelChunkDefault::_create_meshers);
ClassDB::bind_method(D_METHOD("_build", "immediate"), &VoxelChunkDefault::_build);
BIND_VMETHOD(MethodInfo("_visibility_changed", PropertyInfo(Variant::BOOL, "visible")));
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);
BIND_CONSTANT(BUILD_PHASE_DONE);

View File

@ -239,9 +239,12 @@ protected:
virtual void _build(bool immediate);
virtual void _visibility_changed(bool visible);
void wait_and_finish_thread();
virtual void _exit_tree();
virtual void _process(float delta);
virtual void _physics_process(float delta);
virtual void _world_transform_changed();
void _notification(int p_what);
void wait_and_finish_thread();
static void _bind_methods();

View File

@ -160,29 +160,26 @@ int VoxelWorld::get_world_area_count() const {
return _world_areas.size();
}
void VoxelWorld::add_chunk(VoxelChunk *chunk, const int x, const int y, const int z) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelWorld::add_chunk(Ref<VoxelChunk> chunk, const int x, const int y, const int z) {
ERR_FAIL_COND(!chunk.is_valid());
IntPos pos(x, y, z);
ERR_FAIL_COND(_chunks.has(pos));
chunk->set_voxel_world(this);
chunk->set_position(x, y, z);
chunk->world_transform_changed();
_chunks.set(pos, chunk);
_chunks_vector.push_back(chunk);
}
void VoxelWorld::add_chunk_bind(Node *chunk, const int x, const int y, const int z) {
VoxelChunk *v = Object::cast_to<VoxelChunk>(chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(v));
add_chunk(v, x, y, z);
chunk->enter_tree();
}
bool VoxelWorld::has_chunk(const int x, const int y, const int z) const {
return _chunks.has(IntPos(x, y, z));
}
VoxelChunk *VoxelWorld::get_chunk(const int x, const int y, const int z) {
Ref<VoxelChunk> VoxelWorld::get_chunk(const int x, const int y, const int z) {
IntPos pos(x, y, z);
if (_chunks.has(pos))
@ -190,13 +187,13 @@ VoxelChunk *VoxelWorld::get_chunk(const int x, const int y, const int z) {
return NULL;
}
VoxelChunk *VoxelWorld::remove_chunk(const int x, const int y, const int z) {
Ref<VoxelChunk> VoxelWorld::remove_chunk(const int x, const int y, const int z) {
IntPos pos(x, y, z);
if (!_chunks.has(pos))
return NULL;
VoxelChunk *chunk = _chunks.get(pos);
Ref<VoxelChunk> chunk = _chunks.get(pos);
for (int i = 0; i < _chunks_vector.size(); ++i) {
if (_chunks_vector.get(i) == chunk) {
@ -205,23 +202,26 @@ VoxelChunk *VoxelWorld::remove_chunk(const int x, const int y, const int z) {
}
}
chunk->exit_tree();
ERR_FAIL_COND_V(!_chunks.erase(pos), NULL);
//_chunks.erase(pos);
return chunk;
}
VoxelChunk *VoxelWorld::remove_chunk_index(const int index) {
Ref<VoxelChunk> VoxelWorld::remove_chunk_index(const int index) {
ERR_FAIL_INDEX_V(index, _chunks_vector.size(), NULL);
VoxelChunk *chunk = _chunks_vector.get(index);
Ref<VoxelChunk> chunk = _chunks_vector.get(index);
_chunks_vector.remove(index);
_chunks.erase(IntPos(chunk->get_position_x(), chunk->get_position_y(), chunk->get_position_z()));
chunk->exit_tree();
return chunk;
}
VoxelChunk *VoxelWorld::get_chunk_index(const int index) {
Ref<VoxelChunk> VoxelWorld::get_chunk_index(const int index) {
ERR_FAIL_INDEX_V(index, _chunks_vector.size(), NULL);
return _chunks_vector.get(index);
@ -230,17 +230,14 @@ int VoxelWorld::get_chunk_count() const {
return _chunks_vector.size();
}
void VoxelWorld::add_to_generation_queue_bind(Node *chunk) {
add_to_generation_queue(Object::cast_to<VoxelChunk>(chunk));
}
void VoxelWorld::add_to_generation_queue(VoxelChunk *chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelWorld::add_to_generation_queue(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
set_process_internal(true);
_generation_queue.push_back(chunk);
}
VoxelChunk *VoxelWorld::get_generation_queue_index(int index) {
Ref<VoxelChunk> VoxelWorld::get_generation_queue_index(int index) {
ERR_FAIL_INDEX_V(index, _generation_queue.size(), NULL);
return _generation_queue.get(index);
@ -254,15 +251,12 @@ int VoxelWorld::get_generation_queue_size() {
return _generation_queue.size();
}
void VoxelWorld::add_to_generation_bind(Node *chunk) {
add_to_generation(Object::cast_to<VoxelChunk>(chunk));
}
void VoxelWorld::add_to_generation(VoxelChunk *chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelWorld::add_to_generation(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
_generating.push_back(chunk);
}
VoxelChunk *VoxelWorld::get_generation_index(int index) {
Ref<VoxelChunk> VoxelWorld::get_generation_index(int index) {
ERR_FAIL_INDEX_V(index, _generating.size(), NULL);
return _generating.get(index);
@ -278,7 +272,7 @@ int VoxelWorld::get_generation_size() {
void VoxelWorld::clear() {
for (int i = 0; i < _chunks_vector.size(); ++i) {
_chunks_vector.get(i)->queue_delete();
_chunks_vector.get(i)->exit_tree();
}
_chunks_vector.clear();
@ -289,29 +283,19 @@ void VoxelWorld::clear() {
_generating.clear();
}
VoxelChunk *VoxelWorld::create_chunk(int x, int y, int z) {
Node *np = NULL;
Ref<VoxelChunk> VoxelWorld::create_chunk(int x, int y, int z) {
Ref<VoxelChunk> c = call("_create_chunk", x, y, z, Ref<VoxelChunk>());
Node *n = call("_create_chunk", x, y, z, np);
return (Object::cast_to<VoxelChunk>(n));
return c;
}
VoxelChunk *VoxelWorld::_create_chunk(int x, int y, int z, Node *p_chunk) {
VoxelChunk *chunk;
if (p_chunk != NULL) {
chunk = Object::cast_to<VoxelChunk>(p_chunk);
} else {
chunk = memnew(VoxelChunk);
Ref<VoxelChunk> VoxelWorld::_create_chunk(int x, int y, int z, Ref<VoxelChunk> chunk) {
if (!chunk.is_valid()) {
chunk.instance();
}
ERR_FAIL_COND_V(!ObjectDB::instance_validate(chunk), NULL);
ERR_FAIL_COND_V(!chunk.is_valid(), NULL);
chunk->set_name("Chunk[" + String::num(x) + "," + String::num(y) + "," + String::num(z) + "]");
add_child(chunk);
if (Engine::get_singleton()->is_editor_hint())
chunk->set_owner(get_tree()->get_edited_scene_root());
chunk->set_voxel_world(this);
@ -323,7 +307,7 @@ VoxelChunk *VoxelWorld::_create_chunk(int x, int y, int z, Node *p_chunk) {
chunk->set_library(_library);
chunk->set_voxel_scale(_voxel_scale);
chunk->set_size(_chunk_size_x, _chunk_size_y, _chunk_size_z, _data_margin_start, _data_margin_end);
chunk->set_translation(Vector3(x * _chunk_size_x * _voxel_scale, y * _chunk_size_y * _voxel_scale, z * _chunk_size_z * _voxel_scale));
//chunk->set_translation(Vector3(x * _chunk_size_x * _voxel_scale, y * _chunk_size_y * _voxel_scale, z * _chunk_size_z * _voxel_scale));
add_chunk(chunk, x, y, z);
@ -332,20 +316,17 @@ VoxelChunk *VoxelWorld::_create_chunk(int x, int y, int z, Node *p_chunk) {
return chunk;
}
void VoxelWorld::generate_chunk_bind(Node *p_chunk) {
generate_chunk(Object::cast_to<VoxelChunk>(p_chunk));
}
void VoxelWorld::generate_chunk(VoxelChunk *p_chunk) {
ERR_FAIL_COND(!ObjectDB::instance_validate(p_chunk));
void VoxelWorld::generate_chunk(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
p_chunk->set_is_generating(true);
chunk->set_is_generating(true);
if (has_method("_prepare_chunk_for_generation"))
call("_prepare_chunk_for_generation", p_chunk);
call("_prepare_chunk_for_generation", chunk);
call("_generate_chunk", p_chunk);
call("_generate_chunk", chunk);
p_chunk->build();
chunk->build();
}
bool VoxelWorld::can_chunk_do_build_step() {
@ -362,29 +343,44 @@ bool VoxelWorld::is_position_walkable(const Vector3 &p_pos) {
int y = static_cast<int>(Math::floor(p_pos.y / (_chunk_size_y * _voxel_scale)));
int z = static_cast<int>(Math::floor(p_pos.z / (_chunk_size_z * _voxel_scale)));
VoxelChunk *c = get_chunk(x, y, z);
Ref<VoxelChunk> c = get_chunk(x, y, z);
if (!ObjectDB::instance_validate(c))
if (!c.is_valid())
return false;
return !c->get_is_generating();
}
void VoxelWorld::on_chunk_mesh_generation_finished(VoxelChunk *p_chunk) {
void VoxelWorld::on_chunk_mesh_generation_finished(Ref<VoxelChunk> p_chunk) {
emit_signal("chunk_mesh_generation_finished", p_chunk);
}
void VoxelWorld::on_chunk_mesh_generation_finished_bind(Node *p_chunk) {
VoxelChunk *c = Object::cast_to<VoxelChunk>(p_chunk);
Vector<Variant> VoxelWorld::get_chunks() {
Vector<Variant> r;
for (int i = 0; i < _chunks_vector.size(); i++) {
r.push_back(_chunks_vector[i].get_ref_ptr());
}
return r;
}
ERR_FAIL_COND(!ObjectDB::instance_validate(c));
void VoxelWorld::set_chunks(const Vector<Variant> &chunks) {
clear();
on_chunk_mesh_generation_finished(c);
for (int i = 0; i < chunks.size(); i++) {
Ref<VoxelChunk> chunk = Ref<VoxelChunk>(chunks[i]);
if (!chunk.is_valid())
continue;
add_chunk(chunk, chunk->get_position_x(), chunk->get_position_y(), chunk->get_position_z());
}
}
VoxelWorld::VoxelWorld() {
_editable = false;
_is_priority_generation = true;
_chunk_size_x = 16;
_chunk_size_y = 16;
_chunk_size_z = 16;
@ -417,10 +413,8 @@ VoxelWorld ::~VoxelWorld() {
_generating.clear();
}
void VoxelWorld::_generate_chunk(Node *p_chunk) {
VoxelChunk *chunk = Object::cast_to<VoxelChunk>(p_chunk);
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
void VoxelWorld::_generate_chunk(Ref<VoxelChunk> chunk) {
ERR_FAIL_COND(!chunk.is_valid());
ERR_FAIL_COND(!_level_generator.is_valid());
_level_generator->generate_chunk(chunk);
@ -429,27 +423,48 @@ void VoxelWorld::_generate_chunk(Node *p_chunk) {
void VoxelWorld::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
set_process_internal(false);
set_process_internal(true);
set_physics_process_internal(true);
set_notify_transform(true);
if (!Engine::get_singleton()->is_editor_hint() && _library.is_valid())
_library->refresh_rects();
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
if (chunk.is_valid()) {
chunk->enter_tree();
}
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
_num_frame_chunk_build_steps = 0;
if (_generation_queue.empty() && _generating.empty()) {
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
ERR_CONTINUE(!chunk.is_valid());
if (chunk->get_process()) {
chunk->process(get_physics_process_delta_time());
}
}
if (_is_priority_generation && _generation_queue.empty() && _generating.empty()) {
_is_priority_generation = false;
call("_generation_finished");
emit_signal("generation_finished");
set_process_internal(false);
return;
}
for (int i = 0; i < _generating.size(); ++i) {
VoxelChunk *chunk = _generating.get(i);
Ref<VoxelChunk> chunk = _generating.get(i);
if (!ObjectDB::instance_validate(chunk) || !chunk->get_is_generating()) {
if (!chunk.is_valid() || !chunk->get_is_generating()) {
_generating.remove(i);
--i;
continue;
@ -463,17 +478,47 @@ void VoxelWorld::_notification(int p_what) {
return;
while (_generating.size() < _max_concurrent_generations && _generation_queue.size() != 0) {
VoxelChunk *chunk = _generation_queue.get(0);
Ref<VoxelChunk> chunk = _generation_queue.get(0);
_generation_queue.remove(0);
ERR_FAIL_COND(!ObjectDB::instance_validate(chunk));
ERR_FAIL_COND(!chunk.is_valid());
_generating.push_back(chunk);
generate_chunk(chunk);
}
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
ERR_CONTINUE(!chunk.is_valid());
if (chunk->get_process()) {
chunk->physics_process(get_physics_process_delta_time());
}
}
} break;
case NOTIFICATION_EXIT_TREE: {
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
if (chunk.is_valid()) {
chunk->exit_tree();
}
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
for (int i = 0; i < _chunks_vector.size(); ++i) {
Ref<VoxelChunk> chunk = _chunks_vector[i];
if (chunk.is_valid()) {
chunk->world_transform_changed();
}
}
} break;
}
}
@ -545,13 +590,17 @@ void VoxelWorld::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_player", "player"), &VoxelWorld::set_player_bind);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "player", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"), "set_player", "get_player");
ClassDB::bind_method(D_METHOD("get_chunks"), &VoxelWorld::get_chunks);
ClassDB::bind_method(D_METHOD("set_chunks"), &VoxelWorld::set_chunks);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "chunks", PROPERTY_HINT_NONE, "17/17:VoxelChunk", PROPERTY_USAGE_DEFAULT, "VoxelChunk"), "set_chunks", "get_chunks");
ClassDB::bind_method(D_METHOD("get_world_area", "index"), &VoxelWorld::get_world_area);
ClassDB::bind_method(D_METHOD("add_world_area", "area"), &VoxelWorld::add_world_area);
ClassDB::bind_method(D_METHOD("remove_world_area", "index"), &VoxelWorld::remove_world_area);
ClassDB::bind_method(D_METHOD("clear_world_areas"), &VoxelWorld::clear_world_areas);
ClassDB::bind_method(D_METHOD("get_world_area_count"), &VoxelWorld::get_world_area_count);
ClassDB::bind_method(D_METHOD("add_chunk", "chunk", "x", "y", "z"), &VoxelWorld::add_chunk_bind);
ClassDB::bind_method(D_METHOD("add_chunk", "chunk", "x", "y", "z"), &VoxelWorld::add_chunk);
ClassDB::bind_method(D_METHOD("has_chunk", "x", "y", "z"), &VoxelWorld::has_chunk);
ClassDB::bind_method(D_METHOD("get_chunk", "x", "y", "z"), &VoxelWorld::get_chunk);
ClassDB::bind_method(D_METHOD("remove_chunk", "x", "y", "z"), &VoxelWorld::remove_chunk);
@ -560,12 +609,12 @@ void VoxelWorld::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_chunk_index", "index"), &VoxelWorld::get_chunk_index);
ClassDB::bind_method(D_METHOD("get_chunk_count"), &VoxelWorld::get_chunk_count);
ClassDB::bind_method(D_METHOD("add_to_generation_queue", "chunk"), &VoxelWorld::add_to_generation_queue_bind);
ClassDB::bind_method(D_METHOD("add_to_generation_queue", "chunk"), &VoxelWorld::add_to_generation_queue);
ClassDB::bind_method(D_METHOD("get_generation_queue_index", "index"), &VoxelWorld::get_generation_queue_index);
ClassDB::bind_method(D_METHOD("remove_generation_queue_index", "index"), &VoxelWorld::remove_generation_queue_index);
ClassDB::bind_method(D_METHOD("get_generation_queue_size"), &VoxelWorld::get_generation_queue_size);
ClassDB::bind_method(D_METHOD("add_to_generation", "chunk"), &VoxelWorld::add_to_generation_bind);
ClassDB::bind_method(D_METHOD("add_to_generation", "chunk"), &VoxelWorld::add_to_generation);
ClassDB::bind_method(D_METHOD("get_generation_index", "index"), &VoxelWorld::get_generation_index);
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);
@ -586,5 +635,5 @@ 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_bind);
ClassDB::bind_method(D_METHOD("on_chunk_mesh_generation_finished", "chunk"), &VoxelWorld::on_chunk_mesh_generation_finished);
}

View File

@ -94,47 +94,45 @@ public:
void clear_world_areas();
int get_world_area_count() const;
void add_chunk(VoxelChunk *chunk, const int x, const int y, const int z);
void add_chunk_bind(Node *chunk, const int x, const int y, const int z);
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;
VoxelChunk *get_chunk(const int x, const int y, const int z);
VoxelChunk *remove_chunk(const int x, const int y, const int z);
VoxelChunk *remove_chunk_index(const int index);
Ref<VoxelChunk> get_chunk(const int x, const int y, const int z);
Ref<VoxelChunk> remove_chunk(const int x, const int y, const int z);
Ref<VoxelChunk> remove_chunk_index(const int index);
Ref<VoxelChunk> get_chunk_index(const int index);
VoxelChunk *get_chunk_index(const int index);
int get_chunk_count() const;
void add_to_generation_queue_bind(Node *chunk);
void add_to_generation_queue(VoxelChunk *chunk);
VoxelChunk *get_generation_queue_index(int index);
void add_to_generation_queue(Ref<VoxelChunk> chunk);
Ref<VoxelChunk> get_generation_queue_index(int index);
void remove_generation_queue_index(int index);
int get_generation_queue_size();
void add_to_generation_bind(Node *chunk);
void add_to_generation(VoxelChunk *chunk);
VoxelChunk *get_generation_index(int index);
void add_to_generation(Ref<VoxelChunk> chunk);
Ref<VoxelChunk> get_generation_index(int index);
void remove_generation_index(int index);
int get_generation_size();
void clear();
VoxelChunk *create_chunk(int x, int y, int z);
VoxelChunk *_create_chunk(int x, int y, int z, Node *p_chunk);
Ref<VoxelChunk> create_chunk(int x, int y, int z);
Ref<VoxelChunk> _create_chunk(int x, int y, int z, Ref<VoxelChunk> p_chunk);
void generate_chunk_bind(Node *p_chunk);
void generate_chunk(VoxelChunk *p_chunk);
void generate_chunk(Ref<VoxelChunk> chunk);
bool can_chunk_do_build_step();
bool is_position_walkable(const Vector3 &p_pos);
void on_chunk_mesh_generation_finished(VoxelChunk *p_chunk);
void on_chunk_mesh_generation_finished_bind(Node *p_chunk);
void on_chunk_mesh_generation_finished(Ref<VoxelChunk> p_chunk);
Vector<Variant> get_chunks();
void set_chunks(const Vector<Variant> &chunks);
VoxelWorld();
~VoxelWorld();
protected:
void _generate_chunk(Node *p_chunk);
void _generate_chunk(Ref<VoxelChunk> chunk);
virtual void _notification(int p_what);
static void _bind_methods();
@ -175,6 +173,8 @@ public:
private:
bool _editable;
bool _is_priority_generation;
int _chunk_size_x;
int _chunk_size_y;
int _chunk_size_z;
@ -187,8 +187,8 @@ private:
float _voxel_scale;
int _chunk_spawn_range;
HashMap<IntPos, VoxelChunk *, IntPosHasher> _chunks;
Vector<VoxelChunk *> _chunks_vector;
HashMap<IntPos, Ref<VoxelChunk>, IntPosHasher> _chunks;
Vector<Ref<VoxelChunk> > _chunks_vector;
Vector<Ref<WorldArea> > _world_areas;
@ -197,8 +197,8 @@ private:
bool _use_threads;
int _max_concurrent_generations;
Vector<VoxelChunk *> _generation_queue;
Vector<VoxelChunk *> _generating;
Vector<Ref<VoxelChunk> > _generation_queue;
Vector<Ref<VoxelChunk> > _generating;
int _max_frame_chunk_build_steps;
int _num_frame_chunk_build_steps;
};