diff --git a/SCsub b/SCsub index dd4a8c7..4905a4e 100644 --- a/SCsub +++ b/SCsub @@ -17,3 +17,5 @@ env.add_source_files(env.modules_sources,"meshers/transvoxel_tables.cpp") env.add_source_files(env.modules_sources,"utility/marching_cubes_voxel_query.cpp") env.add_source_files(env.modules_sources,"world/voxel_buffer.cpp") +env.add_source_files(env.modules_sources,"world/voxel_world.cpp") +env.add_source_files(env.modules_sources,"world/voxel_chunk.cpp") diff --git a/meshers/voxel_mesher.cpp b/meshers/voxel_mesher.cpp index 5a0b2f1..180116a 100644 --- a/meshers/voxel_mesher.cpp +++ b/meshers/voxel_mesher.cpp @@ -3,13 +3,6 @@ VoxelMesher::VoxelMesher(Ref library) { _library = library; - _vertices = memnew(Vector()); - _normals = memnew(Vector()); - _colors = memnew(Vector()); - _uvs = memnew(Vector()); - _indices = memnew(Vector()); - _bones = memnew(Vector()); - _debug_voxel_face = false; size = (float)1; vertexOffset = Vector3((float)0.5, (float)0.5, (float)0.5); @@ -18,13 +11,6 @@ VoxelMesher::VoxelMesher(Ref library) { } VoxelMesher::VoxelMesher() { - _vertices = memnew(Vector()); - _normals = memnew(Vector()); - _colors = memnew(Vector()); - _uvs = memnew(Vector()); - _indices = memnew(Vector()); - _bones = memnew(Vector()); - _debug_voxel_face = false; size = (float)1; vertexOffset = Vector3((float)0.5, (float)0.5, (float)0.5); @@ -33,12 +19,12 @@ VoxelMesher::VoxelMesher() { } VoxelMesher::~VoxelMesher() { - memdelete(_vertices); - memdelete(_normals); - memdelete(_colors); - memdelete(_uvs); - memdelete(_indices); - memdelete(_bones); + _vertices.clear(); + _normals.clear(); + _colors.clear(); + _uvs.clear(); + _indices.clear(); + _bones.clear(); memdelete(_surface_tool); } @@ -46,26 +32,26 @@ Ref VoxelMesher::build_mesh() { _surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES); _surface_tool->set_material(_library->get_material()); - int len = _vertices->size(); + int len = _vertices.size(); for (int i = 0; i < len; ++i) { - if (_normals->size() > 0) { - _surface_tool->add_normal(_normals->get(i)); + if (_normals.size() > 0) { + _surface_tool->add_normal(_normals.get(i)); } - if (_colors->size() > 0) { - _surface_tool->add_color(_colors->get(i)); + if (_colors.size() > 0) { + _surface_tool->add_color(_colors.get(i)); } - if (_uvs->size() > 0) { - _surface_tool->add_uv(_uvs->get(i)); + if (_uvs.size() > 0) { + _surface_tool->add_uv(_uvs.get(i)); } - _surface_tool->add_vertex(_vertices->get(i)); + _surface_tool->add_vertex(_vertices.get(i)); } - for (int i = 0; i < _indices->size(); ++i) { - _surface_tool->add_index(_indices->get(i)); + for (int i = 0; i < _indices.size(); ++i) { + _surface_tool->add_index(_indices.get(i)); } _surface_tool->generate_normals(); @@ -76,12 +62,12 @@ Ref VoxelMesher::build_mesh() { } void VoxelMesher::reset() { - _vertices->clear(); - _normals->clear(); - _colors->clear(); - _uvs->clear(); - _indices->clear(); - _bones->clear(); + _vertices.clear(); + _normals.clear(); + _colors.clear(); + _uvs.clear(); + _indices.clear(); + _bones.clear(); } void VoxelMesher::create_mesh_for_marching_cubes_query(Ref query) { @@ -91,49 +77,33 @@ void VoxelMesher::create_mesh_for_marching_cubes_query(Ref > *voxels) { - ERR_FAIL_COND(!has_method("_add_voxels")); - - Array arr; - - const int *k = NULL; - while (k = voxels->next(k)) { - Ref v = voxels->get(*k); - - arr.append(v); - } - - call("_add_voxels", arr); -}*/ - -void VoxelMesher::add_voxel(Ref voxels) { +void VoxelMesher::add_buffer(Ref voxels) { ERR_FAIL_COND(!has_method("_add_voxel")); call("_add_voxel", voxels); } void VoxelMesher::create_trimesh_shape(Ref shape) const { - if (_vertices->size() == 0) + if (_vertices.size() == 0) return; PoolVector face_points; - if (_indices->size() == 0) { + if (_indices.size() == 0) { - //face_points.resize(_vertices->size()); + //face_points.resize(_vertices.size()); - int len = (_vertices->size() / 4); + int len = (_vertices.size() / 4); for (int i = 0; i < len; ++i) { - face_points.push_back(_vertices->get(i * 4)); - face_points.push_back(_vertices->get((i * 4) + 2)); - face_points.push_back(_vertices->get((i * 4) + 1)); + face_points.push_back(_vertices.get(i * 4)); + face_points.push_back(_vertices.get((i * 4) + 2)); + face_points.push_back(_vertices.get((i * 4) + 1)); - face_points.push_back(_vertices->get(i * 4)); - face_points.push_back(_vertices->get((i * 4) + 3)); - face_points.push_back(_vertices->get((i * 4) + 2)); + face_points.push_back(_vertices.get(i * 4)); + face_points.push_back(_vertices.get((i * 4) + 3)); + face_points.push_back(_vertices.get((i * 4) + 2)); } shape->set_faces(face_points); @@ -141,31 +111,32 @@ void VoxelMesher::create_trimesh_shape(Ref shape) const { return; } - face_points.resize(_indices->size()); + face_points.resize(_indices.size()); for (int i = 0; i < face_points.size(); i++) { - face_points.set(i, _vertices->get(_indices->get(i))); + face_points.set(i, _vertices.get(_indices.get(i))); } shape->set_faces(face_points); } -void VoxelMesher::bake_lights(MeshInstance *node, Vector > *lights) { +void VoxelMesher::bake_lights(MeshInstance *node, Vector > &lights) { + ERR_FAIL_COND(node == NULL); Color darkColor(0, 0, 0, 1); - for (int v = 0; v < _vertices->size(); ++v) { + for (int v = 0; v < _vertices.size(); ++v) { - Vector3 vet = _vertices->get(v); + Vector3 vet = _vertices.get(v); Vector3 vertex = node->to_global(vet); //grab normal - Vector3 normal = _normals->get(v); + Vector3 normal = _normals.get(v); Vector3 v_lightDiffuse; //calculate the lights value - for (int i = 0; i < lights->size(); ++i) { - Ref light = lights->get(i); + for (int i = 0; i < lights.size(); ++i) { + Ref light = lights.get(i); Vector3 lightDir = light->get_world_position() - vertex; @@ -199,7 +170,7 @@ void VoxelMesher::bake_lights(MeshInstance *node, Vector > *ligh v_lightDiffuse += value;*/ } - Color f = _colors->get(v); + Color f = _colors.get(v); //Color f = darkColor; Vector3 cv2(f.r, f.g, f.b); @@ -226,7 +197,7 @@ void VoxelMesher::bake_lights(MeshInstance *node, Vector > *ligh //f.g = v_lightDiffuse.y; //f.b = v_lightDiffuse.z; - _colors->set(v, f); + _colors.set(v, f); } // for (int i = 0; i < _colors->size(); ++i) { @@ -235,111 +206,110 @@ void VoxelMesher::bake_lights(MeshInstance *node, Vector > *ligh } Vector *VoxelMesher::get_vertices() { - return _vertices; + return &_vertices; } int VoxelMesher::get_vertex_count() { - return _vertices->size(); + return _vertices.size(); } void VoxelMesher::add_vertex(Vector3 vertex) { - _vertices->push_back(vertex); + _vertices.push_back(vertex); } Vector3 VoxelMesher::get_vertex(int idx) { - return _vertices->get(idx); + return _vertices.get(idx); } void VoxelMesher::remove_vertex(int idx) { - _vertices->remove(idx); + _vertices.remove(idx); } Vector *VoxelMesher::get_normals() { - return _normals; + return &_normals; } int VoxelMesher::get_normal_count() { - return _normals->size(); + return _normals.size(); } void VoxelMesher::add_normal(Vector3 normal) { - _normals->push_back(normal); + _normals.push_back(normal); } Vector3 VoxelMesher::get_normal(int idx) { - return _normals->get(idx); + return _normals.get(idx); } void VoxelMesher::remove_normal(int idx) { - _normals->remove(idx); + _normals.remove(idx); } Vector *VoxelMesher::get_colors() { - return _colors; + return &_colors; } int VoxelMesher::get_color_count() { - return _colors->size(); + return _colors.size(); } void VoxelMesher::add_color(Color color) { - _colors->push_back(color); + _colors.push_back(color); } Color VoxelMesher::get_color(int idx) { - return _colors->get(idx); + return _colors.get(idx); } void VoxelMesher::remove_color(int idx) { - _colors->remove(idx); + _colors.remove(idx); } Vector *VoxelMesher::get_uvs() { - return _uvs; + return &_uvs; } int VoxelMesher::get_uv_count() { - return _uvs->size(); + return _uvs.size(); } void VoxelMesher::add_uv(Vector2 uv) { - _uvs->push_back(uv); + _uvs.push_back(uv); } Vector2 VoxelMesher::get_uv(int idx) { - return _uvs->get(idx); + return _uvs.get(idx); } void VoxelMesher::remove_uv(int idx) { - _uvs->remove(idx); + _uvs.remove(idx); } Vector *VoxelMesher::get_indices() { - return _indices; + return &_indices; } int VoxelMesher::get_indices_count() { - return _indices->size(); + return _indices.size(); } void VoxelMesher::add_indices(int index) { - _indices->push_back(index); + _indices.push_back(index); } int VoxelMesher::get_indice(int idx) { - return _indices->get(idx); + return _indices.get(idx); } void VoxelMesher::remove_indices(int idx) { - _indices->remove(idx); + _indices.remove(idx); } void VoxelMesher::_bind_methods() { //BIND_VMETHOD(MethodInfo("_build_mesh", PropertyInfo(Variant::BOOL, "recal", PROPERTY_HINT_RESOURCE_TYPE, "SpellCastInfo"))); - BIND_VMETHOD(MethodInfo("_add_voxels", PropertyInfo(Variant::ARRAY, "voxels"))); - BIND_VMETHOD(MethodInfo("_add_voxel", PropertyInfo(Variant::OBJECT, "voxel", PROPERTY_HINT_RESOURCE_TYPE, "Voxel"))); + BIND_VMETHOD(MethodInfo("_add_voxels", PropertyInfo(Variant::OBJECT, "buffer", PROPERTY_HINT_RESOURCE_TYPE, "VoxelBuffer"))); BIND_VMETHOD(MethodInfo("_create_mesh_for_marching_cubes_query", PropertyInfo(Variant::OBJECT, "query", PROPERTY_HINT_RESOURCE_TYPE, "MarchingCubesVoxelQuery"))); ClassDB::bind_method(D_METHOD("get_library"), &VoxelMesher::get_library); diff --git a/meshers/voxel_mesher.h b/meshers/voxel_mesher.h index cf1c2a9..6dfdf4f 100644 --- a/meshers/voxel_mesher.h +++ b/meshers/voxel_mesher.h @@ -17,9 +17,8 @@ #include "../library/voxelman_library.h" #include "../math/vector3i.h" -#include "../data/voxel.h" -#include "../library/voxelman_library.h" #include "../utility/marching_cubes_voxel_query.h" +#include "../world/voxel_buffer.h" const double PI_2 = 3.141592653589793238463 / 2; const double PI = 3.141592653589793238463; @@ -36,12 +35,11 @@ public: void reset(); - //void add_voxels(Hash3DMap > *voxels); - void add_voxel(Ref voxels); + void add_buffer(Ref voxels); void create_mesh_for_marching_cubes_query(Ref query); void create_trimesh_shape(Ref shape) const; - void bake_lights(MeshInstance *node, Vector > *lights); + void bake_lights(MeshInstance *node, Vector > &lights); Ref build_mesh(); @@ -83,12 +81,12 @@ protected: static void _bind_methods(); private: - Vector *_vertices; - Vector *_normals; - Vector *_colors; - Vector *_uvs; - Vector *_indices; - Vector *_bones; + Vector _vertices; + Vector _normals; + Vector _colors; + Vector _uvs; + Vector _indices; + Vector _bones; Ref _library; diff --git a/register_types.cpp b/register_types.cpp index 73e9c45..2b103a5 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -11,6 +11,8 @@ #include "utility/marching_cubes_voxel_query.h" #include "world/voxel_buffer.h" +#include "world/voxel_world.h" +#include "world/voxel_chunk.h" void register_voxelman_types() { ClassDB::register_class(); @@ -27,6 +29,8 @@ void register_voxelman_types() { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); } void unregister_voxelman_types() { diff --git a/world/voxel_buffer.cpp b/world/voxel_buffer.cpp index 980ac09..934cb2f 100644 --- a/world/voxel_buffer.cpp +++ b/world/voxel_buffer.cpp @@ -329,12 +329,11 @@ void VoxelBuffer::_bind_methods() { BIND_ENUM_CONSTANT(CHANNEL_TYPE); BIND_ENUM_CONSTANT(CHANNEL_ISOLEVEL); + BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_R); + BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_G); + BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_B); + BIND_ENUM_CONSTANT(CHANNEL_DATA1); BIND_ENUM_CONSTANT(CHANNEL_DATA2); - BIND_ENUM_CONSTANT(CHANNEL_DATA3); - BIND_ENUM_CONSTANT(CHANNEL_DATA4); - BIND_ENUM_CONSTANT(CHANNEL_DATA5); - BIND_ENUM_CONSTANT(CHANNEL_DATA6); - BIND_ENUM_CONSTANT(CHANNEL_DATA7); BIND_ENUM_CONSTANT(MAX_CHANNELS); } diff --git a/world/voxel_buffer.h b/world/voxel_buffer.h index 1c97287..a33dfec 100644 --- a/world/voxel_buffer.h +++ b/world/voxel_buffer.h @@ -35,12 +35,11 @@ public: enum ChannelId { CHANNEL_TYPE = 0, CHANNEL_ISOLEVEL, + CHANNEL_LIGHT_COLOR_R, + CHANNEL_LIGHT_COLOR_G, + CHANNEL_LIGHT_COLOR_B, + CHANNEL_DATA1, CHANNEL_DATA2, - CHANNEL_DATA3, - CHANNEL_DATA4, - CHANNEL_DATA5, - CHANNEL_DATA6, - CHANNEL_DATA7, // Arbitrary value, 8 should be enough. Tweak for your needs. MAX_CHANNELS }; diff --git a/world/voxel_chunk.cpp b/world/voxel_chunk.cpp new file mode 100644 index 0000000..b0039b8 --- /dev/null +++ b/world/voxel_chunk.cpp @@ -0,0 +1,497 @@ +#include "voxel_chunk.h" + +NodePath VoxelChunk::get_library_path() { + return _library_path; +} +void VoxelChunk::set_library_path(NodePath value) { + _library_path = value; +} + +NodePath VoxelChunk::get_mesh_instance_path() { + return _mesh_instance_path; +} +void VoxelChunk::set_mesh_instance_path(NodePath value) { + _mesh_instance_path = value; +} + +Ref VoxelChunk::get_library() { + return _library; +} +void VoxelChunk::set_library(Ref value) { + _library = value; +} + +float VoxelChunk::get_voxel_scale() { + return _voxel_scale; +} +void VoxelChunk::set_voxel_scale(float value) { + _voxel_scale = value; +} + +Ref VoxelChunk::get_mesher() const { + return _mesher; +} +void VoxelChunk::set_mesher(Ref mesher) { + _mesher = mesher; +} + +bool VoxelChunk::get_build_mesh() { + return _build_mesh; +} +void VoxelChunk::set_build_mesh(bool value) { + _build_mesh = value; +} + +bool VoxelChunk::get_create_collider() { + return _create_collider; +} +void VoxelChunk::set_create_collider(bool value) { + _create_collider = value; +} + +bool VoxelChunk::get_bake_lights() { + return _bake_lights; +} +void VoxelChunk::set_bake_lights(bool value) { + _bake_lights = value; +} + +bool VoxelChunk::get_bake_ambient_occlusion() { + return _bake_ambient_occlusion; +} +void VoxelChunk::set_bake_ambient_occlusion(bool value) { + _bake_ambient_occlusion = value; +} + +float VoxelChunk::get_ao_radius() { + return _ao_radius; +} +void VoxelChunk::set_ao_radius(float value) { + _ao_radius = value; +} + +float VoxelChunk::get_ao_intensity() { + return _ao_intensity; +} +void VoxelChunk::set_ao_intensity(float value) { + _ao_intensity = value; +} + +int VoxelChunk::get_ao_sample_count() { + return _ao_sample_count; +} +void VoxelChunk::set_ao_sample_count(int value) { + _ao_sample_count = value; +} + +NodePath VoxelChunk::get_debug_drawer_path() { + return _debug_drawer_path; +} +void VoxelChunk::set_debug_drawer_path(NodePath value) { + _debug_drawer_path = value; +} + +Ref VoxelChunk::get_buffer() const { + return _buffer; +} + +void VoxelChunk::clear() { + _voxel_lights.clear(); +} + +void VoxelChunk::build() { + ERR_FAIL_COND(!_library.is_valid()); + ERR_FAIL_COND(!_mesher.is_valid()); + + _mesher->set_library(_library); + + if (_debug_drawer == NULL) { + Node *n = get_node(_debug_drawer_path); + + if (n != NULL) { + _debug_drawer = Object::cast_to(n); + } + } + + _mesher->add_buffer(_buffer); + + if (get_build_mesh()) { + ERR_FAIL_COND(!has_method("_build_mesh")); + + call("_build_mesh"); + + finalize_mesh(); + } + + if (get_create_collider()) { + update_collider(); + } +} + +void VoxelChunk::finalize_mesh() { + _mesher->set_library(_library); + + Node *node = get_node(_mesh_instance_path); + + if (node != NULL) { + + _mesh_instance = Object::cast_to(node); + + if (_mesh_instance != NULL) { + //if (get_bake_ambient_occlusion()) { + // set_enabled(true); + //} else { + Ref mesh = get_mesher()->build_mesh(); + + _mesh_instance->set_mesh(mesh); + //} + } + } +} + +void VoxelChunk::update_collider() { + //_mesh_instance->create_trimesh_collision(); + //StaticBody *static_body = Object::cast_to(create_trimesh_collision_node()); + + StaticBody *static_body = create_trimesh_collision_node(); + ERR_FAIL_COND(!static_body); + static_body->set_name(String(get_name()) + "_col"); + + add_child(static_body); + if (get_owner()) { + CollisionShape *cshape = Object::cast_to(static_body->get_child(0)); + static_body->set_owner(get_owner()); + cshape->set_owner(get_owner()); + } +} + +StaticBody *VoxelChunk::create_trimesh_collision_node() { + + Ref shape = memnew(ConcavePolygonShape); + + _mesher->create_trimesh_shape(shape); + + StaticBody *static_body = memnew(StaticBody); + CollisionShape *cshape = memnew(CollisionShape); + cshape->set_shape(shape); + static_body->add_child(cshape); + return static_body; +} + +void VoxelChunk::query_marching_cubes_data(Ref query) { + ERR_FAIL_COND(!query.is_valid()); + + Vector3i position = query->get_position(); + int size = query->get_size(); + /* + query->set_entries(Ref(_VoxelChunk->getptr(position)), Ref(_VoxelChunk->getptr(Vector3i(size, 0, 0) + position)), + Ref(_VoxelChunk->getptr(Vector3i(0, size, 0) + position)), Ref(_VoxelChunk->getptr(Vector3i(size, size, 0) + position)), + Ref(_VoxelChunk->getptr(Vector3i(0, 0, size) + position)), Ref(_VoxelChunk->getptr(Vector3i(size, 0, size) + position)), + Ref(_VoxelChunk->getptr(Vector3i(0, size, size) + position)), Ref(_VoxelChunk->getptr(Vector3i(size, size, size) + position)));*/ +} + +void VoxelChunk::create_mesh_for_marching_cubes_query(Ref query) { + ERR_FAIL_COND(!query.is_valid()); + ERR_FAIL_COND(!_mesher.is_valid()); + + _mesher->create_mesh_for_marching_cubes_query(query); +} + +void VoxelChunk::set_enabled(bool p_enabled) { + + _enabled = p_enabled; + + if (is_inside_tree()) + set_physics_process_internal(p_enabled); +} + +bool VoxelChunk::is_enabled() const { + return _enabled; +} + +void VoxelChunk::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + if (!_mesher.is_valid()) { + if (has_method("_create_mesher")) { + call("_create_mesher"); + + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_COND(!_mesher.is_valid()); + } + } else { + _mesher = Ref(memnew(VoxelMesher())); + } + } + } break; + case NOTIFICATION_EXIT_TREE: { + + //if (_mesher != NULL) { + // memdelete(_mesher); + //} + + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + + //if (!_enabled) + // break; + + //if (_mesh_instance != NULL) { + // if (get_bake_ambient_occlusion()) { + //get_mesher()->calculate_vertex_ambient_occlusion(_mesh_instance, get_ao_radius(), get_ao_intensity(), get_ao_sample_count()); + // } + + //Ref mesh = get_mesher()->build_mesh(); + + //_mesh_instance->set_mesh(mesh); + //} + + //set_enabled(false); + + } break; + } +} + +void VoxelChunk::add_voxel_light_bind(Vector3 position, Color color, float strength) { + add_voxel_light(position, color, strength); +} + +Ref VoxelChunk::add_voxel_light(Vector3i position, Color color, float strength, Vector3 offset) { + Vector3 pos(position.x, position.y, position.z); + + Ref light = Ref(memnew(VoxelLight(position, color, strength, to_global(pos + Vector3((float)0.5, (float)0.5, (float)0.5) * _voxel_scale), offset))); + + _voxel_lights.push_back(light); + + return light; +} + +void VoxelChunk::draw_cross_voxels(Vector3 pos) { + pos *= _voxel_scale; + + _debug_drawer->add_vertex(pos + Vector3(0, 0, -0.2)); + _debug_drawer->add_vertex(pos + Vector3(0, 0, 0.2)); + + _debug_drawer->add_vertex(pos + Vector3(0, -0.2, 0)); + _debug_drawer->add_vertex(pos + Vector3(0, 0.2, 0)); + + _debug_drawer->add_vertex(pos + Vector3(-0.2, 0, 0)); + _debug_drawer->add_vertex(pos + Vector3(0.2, 0, 0)); +} + +void VoxelChunk::draw_cross_voxels(Vector3 pos, float fill) { + pos *= _voxel_scale; + + _debug_drawer->add_vertex(pos + Vector3(0, 0, -0.5 * fill)); + _debug_drawer->add_vertex(pos + Vector3(0, 0, 0.5 * fill)); + + _debug_drawer->add_vertex(pos + Vector3(0, -0.5 * fill, 0)); + _debug_drawer->add_vertex(pos + Vector3(0, 0.5 * fill, 0)); + + _debug_drawer->add_vertex(pos + Vector3(-0.5 * fill, 0, 0)); + _debug_drawer->add_vertex(pos + Vector3(0.5 * fill, 0, 0)); +} + +void VoxelChunk::draw_debug_voxels(int max, Color color) { + /* + if (_debug_drawer == NULL) { + Node *n = get_node(_debug_drawer_path); + + if (n != NULL) { + _debug_drawer = Object::cast_to(n); + } + } + + ERR_FAIL_COND(_debug_drawer == NULL); + + //if (_debug_drawer->emt) + + _debug_drawer->clear(); + _debug_drawer->begin(Mesh::PRIMITIVE_LINES); + _debug_drawer->set_color(color); + + HashMap > *map = _voxels->get_map(); + + ERR_FAIL_COND(map == NULL); + + const int *k = NULL; + + //Vector3 pos = get_transform().get_origin(); + + int a = 0; + while ((k = map->next(k))) { + Ref v = map->get(*k); + ERR_FAIL_COND(!v.is_valid()); + + Vector3i lp = v->get_local_position(); + //print_error(Vector3(lp.x, lp.y, lp.z)); + draw_cross_voxels(Vector3(lp.x + 0.5, lp.y + 0.5, lp.z + 0.5), v->get_fill() / 255.0); + + a++; + + if (a > max) { + break; + } + } + + //for (int x = 0; x < 30; x++) { + // for (int y = 0; y < 30; y++) { + // for (int z = 0; z < 30; z++) { + //draw_cross_voxels(Vector3(x, y, z)); + // + // } + // } + //} + //_debug_drawer->add_sphere(4, 4, 0.5, true); + + _debug_drawer->end();*/ +} + +void VoxelChunk::draw_debug_voxel_lights(int max, bool localPosition) { + /* + if (_debug_drawer == NULL) { + Node *n = get_node(_debug_drawer_path); + + if (n != NULL) { + _debug_drawer = Object::cast_to(n); + } + } + + if (_debug_drawer == NULL) { + return; + } + + _debug_drawer->clear(); + _debug_drawer->begin(Mesh::PrimitiveType::PRIMITIVE_LINES); + _debug_drawer->set_color(Color(1, 1, 1)); + + const int *k = NULL; + + Vector3 pos = get_transform().get_origin(); + + int a = 0; + while ((k = _voxel_lights->next(k))) { + Ref v = _voxel_lights->get(*k); + + if (localPosition) { + Vector3i lp = v->get_local_position(); + draw_cross_voxels(pos + Vector3(lp.x, lp.y, lp.z), (float)v->get_strength() / (float)10); + } else { + Vector3i wp = v->get_world_position(); + draw_cross_voxels(pos + Vector3(wp.x, wp.y, wp.z), (float)v->get_strength() / (float)10); + } + ++a; + + if (a > max) { + break; + } + } + + _debug_drawer->end();*/ +} + +void VoxelChunk::_bind_methods() { + BIND_VMETHOD(MethodInfo("_create_mesher")); + BIND_VMETHOD(MethodInfo("_build_mesh")); + + ClassDB::bind_method(D_METHOD("get_library_path"), &VoxelChunk::get_library_path); + ClassDB::bind_method(D_METHOD("set_library_path", "value"), &VoxelChunk::set_library_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "library_path"), "set_library_path", "get_library_path"); + + ClassDB::bind_method(D_METHOD("get_mesh_instance_path"), &VoxelChunk::get_mesh_instance_path); + ClassDB::bind_method(D_METHOD("set_mesh_instance_path", "value"), &VoxelChunk::set_mesh_instance_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "mesh_instance_path"), "set_mesh_instance_path", "get_mesh_instance_path"); + + ClassDB::bind_method(D_METHOD("get_library"), &VoxelChunk::get_library); + ClassDB::bind_method(D_METHOD("set_library", "value"), &VoxelChunk::set_library); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "VoxelmanLibrary"), "set_library", "get_library"); + + ClassDB::bind_method(D_METHOD("get_voxel_scale"), &VoxelChunk::get_voxel_scale); + ClassDB::bind_method(D_METHOD("set_voxel_scale", "value"), &VoxelChunk::set_voxel_scale); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "voxel_scale"), "set_voxel_scale", "get_voxel_scale"); + + ClassDB::bind_method(D_METHOD("get_buffer"), &VoxelChunk::get_buffer); + + ADD_GROUP("Meshing", "meshing"); + + ClassDB::bind_method(D_METHOD("meshing_get_build_mesh"), &VoxelChunk::get_build_mesh); + ClassDB::bind_method(D_METHOD("meshing_set_build_mesh", "value"), &VoxelChunk::set_build_mesh); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_build_mesh"), "meshing_set_build_mesh", "meshing_get_build_mesh"); + + ClassDB::bind_method(D_METHOD("meshing_get_create_collider"), &VoxelChunk::get_create_collider); + ClassDB::bind_method(D_METHOD("meshing_set_create_collider", "value"), &VoxelChunk::set_create_collider); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_create_collider"), "meshing_set_create_collider", "meshing_get_create_collider"); + + ClassDB::bind_method(D_METHOD("meshing_get_bake_lights"), &VoxelChunk::get_bake_lights); + ClassDB::bind_method(D_METHOD("meshing_set_bake_lights", "value"), &VoxelChunk::set_bake_lights); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_bake_lights"), "meshing_set_bake_lights", "meshing_get_bake_lights"); + + ClassDB::bind_method(D_METHOD("meshing_get_bake_ambient_occlusion"), &VoxelChunk::get_bake_ambient_occlusion); + ClassDB::bind_method(D_METHOD("meshing_set_bake_ambient_occlusion", "value"), &VoxelChunk::set_bake_ambient_occlusion); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meshing_bake_ambient_occlusion"), "meshing_set_bake_ambient_occlusion", "meshing_get_bake_ambient_occlusion"); + + ADD_GROUP("Settings", "setting"); + + ClassDB::bind_method(D_METHOD("get_debug_drawer_path"), &VoxelChunk::get_debug_drawer_path); + ClassDB::bind_method(D_METHOD("set_debug_drawer_path", "value"), &VoxelChunk::set_debug_drawer_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "debug_drawer_path"), "set_debug_drawer_path", "get_debug_drawer_path"); + + ADD_GROUP("Ambient Occlusion", "ao"); + ClassDB::bind_method(D_METHOD("get_ao_radius"), &VoxelChunk::get_ao_radius); + ClassDB::bind_method(D_METHOD("set_ao_radius", "value"), &VoxelChunk::set_ao_radius); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_radius"), "set_ao_radius", "get_ao_radius"); + + ClassDB::bind_method(D_METHOD("get_ao_intensity"), &VoxelChunk::get_ao_intensity); + ClassDB::bind_method(D_METHOD("set_ao_intensity", "value"), &VoxelChunk::set_ao_intensity); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_intensity"), "set_ao_intensity", "get_ao_intensity"); + + ClassDB::bind_method(D_METHOD("get_ao_sample_count"), &VoxelChunk::get_ao_sample_count); + ClassDB::bind_method(D_METHOD("set_ao_sample_count", "value"), &VoxelChunk::set_ao_sample_count); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_sample_count"), "set_ao_sample_count", "get_ao_sample_count"); + + ClassDB::bind_method(D_METHOD("get_mesher"), &VoxelChunk::get_mesher); + ClassDB::bind_method(D_METHOD("set_mesher", "Mesher"), &VoxelChunk::set_mesher); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesher", PROPERTY_HINT_RESOURCE_TYPE, "VoxelMesher"), "set_mesher", "get_mesher"); + + ClassDB::bind_method(D_METHOD("build"), &VoxelChunk::build); + ClassDB::bind_method(D_METHOD("finalize_mesh"), &VoxelChunk::finalize_mesh); + + ClassDB::bind_method(D_METHOD("clear"), &VoxelChunk::clear); + + ClassDB::bind_method(D_METHOD("query_marching_cubes_data", "query"), &VoxelChunk::query_marching_cubes_data); + ClassDB::bind_method(D_METHOD("create_mesh_for_marching_cubes_query", "query"), &VoxelChunk::create_mesh_for_marching_cubes_query); + + ClassDB::bind_method(D_METHOD("draw_debug_voxels", "max"), &VoxelChunk::draw_debug_voxels, DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("draw_debug_voxel_lights", "max", "localPosition"), &VoxelChunk::draw_debug_voxel_lights); +} + +VoxelChunk::VoxelChunk() { + _build_mesh = true; + _create_collider = true; + _bake_lights = true; + _bake_ambient_occlusion = true; + + _ao_radius = 6; + _ao_intensity = 1; + _ao_sample_count = 5; + + _voxel_scale = 1; + + _buffer.instance(); + + _debug_drawer = NULL; +} + +VoxelChunk::~VoxelChunk() { + _voxel_lights.clear(); + + if (_mesher.is_valid()) { + _mesher.unref(); + } + + _buffer.unref(); + + _debug_drawer = NULL; +} diff --git a/world/voxel_chunk.h b/world/voxel_chunk.h new file mode 100644 index 0000000..113f395 --- /dev/null +++ b/world/voxel_chunk.h @@ -0,0 +1,129 @@ +#ifndef VOXEL_CHUNK_H +#define VOXEL_CHUNK_H + +#include "core/engine.h" +#include "core/object.h" +#include "core/ustring.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/spatial.h" +#include "scene/3d/collision_shape.h" +#include "scene/3d/physics_body.h" +#include "scene/resources/concave_polygon_shape.h" + +#include "../data/voxel.h" +#include "../data/voxel_light.h" + +#include "../meshers/voxel_mesher.h" + +#include "../library/voxel_surface.h" +#include "../library/voxelman_library.h" + +#include "../utility/marching_cubes_voxel_query.h" +#include "voxel_buffer.h" + + +class VoxelChunk : public Spatial { + GDCLASS(VoxelChunk, Spatial); + +public: + NodePath get_library_path(); + void set_library_path(NodePath value); + + NodePath get_mesh_instance_path(); + void set_mesh_instance_path(NodePath value); + + Ref get_library(); + void set_library(Ref value); + + float get_voxel_scale(); + void set_voxel_scale(float value); + + Ref get_mesher() const; + void set_mesher(Ref mesher); + + bool get_build_mesh(); + void set_build_mesh(bool value); + + bool get_create_collider(); + void set_create_collider(bool value); + + bool get_bake_lights(); + void set_bake_lights(bool value); + + bool get_bake_ambient_occlusion(); + void set_bake_ambient_occlusion(bool value); + + float get_ao_radius(); + void set_ao_radius(float value); + + float get_ao_intensity(); + void set_ao_intensity(float value); + + int get_ao_sample_count(); + void set_ao_sample_count(int value); + + NodePath get_debug_drawer_path(); + void set_debug_drawer_path(NodePath value); + + Ref get_buffer() const; + + void finalize_mesh(); + + void clear(); + void build(); + + void update_collider(); + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + Ref add_voxel_light(Vector3i position, Color color, float strength, Vector3 offset = Vector3()); + void add_voxel_light_bind(Vector3 position, Color color, float strength); + + StaticBody *create_trimesh_collision_node(); + + void query_marching_cubes_data(Ref query); + void create_mesh_for_marching_cubes_query(Ref query); + + VoxelChunk(); + virtual ~VoxelChunk(); + + void draw_debug_voxels(int max, Color color = Color(1, 1, 1)); + void draw_debug_voxel_lights(int max, bool localPosition = false); + void draw_cross_voxels(Vector3 pos); + void draw_cross_voxels(Vector3 pos, float fill); + +protected: + static void _bind_methods(); + void _notification(int p_what); + + bool _enabled; + + Ref _buffer; + Vector > _voxel_lights; + float _voxel_scale; + + NodePath _library_path; + Ref _library; + + NodePath _mesh_instance_path; + MeshInstance *_mesh_instance; + Ref _mesh; + + Ref _mesher; + + ImmediateGeometry *_debug_drawer; + NodePath _debug_drawer_path; + + bool _build_mesh; + bool _create_collider; + + bool _bake_lights; + bool _bake_ambient_occlusion; + + float _ao_radius; + float _ao_intensity; + int _ao_sample_count; +}; + +#endif diff --git a/world/voxel_world.cpp b/world/voxel_world.cpp new file mode 100644 index 0000000..ea61a73 --- /dev/null +++ b/world/voxel_world.cpp @@ -0,0 +1,15 @@ +#include "voxel_world.h" + +NodePath VoxelWorld::get_player_path() { + return _player_path; +} + +void VoxelWorld::set_player_path(NodePath player_path) { + _player_path = player_path; +} + +void VoxelWorld::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_player_path"), &VoxelWorld::get_player_path); + ClassDB::bind_method(D_METHOD("set_player_path", "value"), &VoxelWorld::set_player_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "player_path"), "set_player_path", "get_player_path"); +} diff --git a/world/voxel_world.h b/world/voxel_world.h new file mode 100644 index 0000000..9f9d9fb --- /dev/null +++ b/world/voxel_world.h @@ -0,0 +1,29 @@ +#ifndef VOXEL_WORLD_H +#define VOXEL_WORLD_H + +#include "scene/3d/spatial.h" +#include "core/hash_map.h" + +#include "../math/vector3i.h" +#include "voxel_buffer.h" + +class VoxelWorld : public Spatial { + GDCLASS(VoxelWorld, Spatial); + +public: + NodePath get_player_path(); + void set_player_path(NodePath player_path); + + VoxelWorld() {} + +protected: + static void _bind_methods(); + +private: + HashMap > _chunks; + + NodePath _player_path; + Spatial *_player; +}; + +#endif