#ifndef VOXEL_WORLD_H #define VOXEL_WORLD_H /*************************************************************************/ /* voxel_world.h */ /*************************************************************************/ /* This file is part of: */ /* PANDEMONIUM ENGINE */ /* https://github.com/Relintai/pandemonium_engine */ /*************************************************************************/ /* Copyright (c) 2022-present Péter Magyar. */ /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "core/config/engine.h" #include "core/containers/hash_map.h" #include "../defines.h" #include "scene/main/spatial.h" #include "../areas/world_area.h" #include "../level_generator/voxel_level_generator.h" #include "../library/voxel_library.h" #include "core/os/os.h" #include "modules/modules_enabled.gen.h" #ifdef MODULE_PROPS_ENABLED #include "../../props/props/prop_data.h" #endif class VoxelStructure; class VoxelChunk; class PropData; class VoxelWorld : public Spatial { GDCLASS(VoxelWorld, Spatial); public: enum ChannelTypeInfo { CHANNEL_TYPE_INFO_TYPE = 0, CHANNEL_TYPE_INFO_ISOLEVEL, CHANNEL_TYPE_INFO_LIQUID_FLOW, }; static const String BINDING_STRING_CHANNEL_TYPE_INFO; public: bool get_editable() const; void set_editable(const bool value); int get_chunk_size_x() const; void set_chunk_size_x(const int value); int get_chunk_size_y() const; void set_chunk_size_y(const int value); int get_chunk_size_z() const; void set_chunk_size_z(const int value); int get_data_margin_start() const; void set_data_margin_start(const int value); int get_data_margin_end() const; void set_data_margin_end(const int value); int get_current_seed() const; void set_current_seed(const int value); bool get_use_threads() const; void set_use_threads(const bool value); int get_max_concurrent_generations() const; void set_max_concurrent_generations(const int value); int get_max_frame_chunk_build_steps() const; void set_max_frame_chunk_build_steps(const int value); Ref get_library(); void set_library(const Ref &library); Ref get_level_generator() const; void set_level_generator(const Ref &level_generator); float get_voxel_scale() const; void set_voxel_scale(const float value); int get_chunk_spawn_range() const; void set_chunk_spawn_range(const int value); NodePath get_player_path() const; void set_player_path(const NodePath &player_path); Spatial *get_player() const; void set_player(Spatial *player); void set_player_bind(Node *player); //World Areas Ref world_area_get(const int index) const; void world_area_add(const Ref &area); void world_area_remove(const int index); void world_areas_clear(); int world_area_get_count() const; //Voxel Structures Ref voxel_structure_get(const int index) const; void voxel_structure_add(const Ref &structure); void voxel_structure_remove(const Ref &structure); void voxel_structure_remove_index(const int index); void voxel_structures_clear(); int voxel_structure_get_count() const; void voxel_structure_add_at_position(Ref structure, const Vector3 &world_position); Vector voxel_structures_get(); void voxel_structures_set(const Vector &structures); //Chunks void chunk_add(Ref chunk, const int x, const int y, const int z); bool chunk_has(const int x, const int y, const int z) const; Ref chunk_get(const int x, const int y, const int z); Ref chunk_remove(const int x, const int y, const int z); Ref chunk_remove_index(const int index); Ref chunk_get_index(const int index); int chunk_get_count() const; void chunks_clear(); Ref chunk_get_or_create(const int x, const int y, const int z); Ref chunk_create(const int x, const int y, const int z); void chunk_setup(Ref chunk); void chunk_generate(Ref chunk); Vector chunks_get(); void chunks_set(const Vector &chunks); bool can_chunk_do_build_step(); bool is_position_walkable(const Vector3 &p_pos); void on_chunk_mesh_generation_finished(Ref p_chunk); void generation_queue_add_to(const Ref &chunk); Ref generation_queue_get_index(const int index); void generation_queue_remove_index(const int index); int generation_queue_get_size() const; void generation_add_to(const Ref &chunk); Ref generation_get_index(const int index); void generation_remove_index(const int index); int generation_get_size() const; #ifdef MODULE_PROPS_ENABLED void prop_add(Transform tarnsform, const Ref &prop, const bool apply_voxel_scael = true); #endif //Lights void light_add(const Ref &light); Ref light_get(const int index); void light_remove(const int index); int light_get_count() const; void lights_clear(); Vector lights_get(); void lights_set(const Vector &chunks); //Helpers uint8_t get_voxel_at_world_position(const Vector3 &world_position, const int channel_index); void set_voxel_at_world_position(const Vector3 &world_position, const uint8_t data, const int channel_index, const bool rebuild = true); Ref get_chunk_at_world_position(const Vector3 &world_position); Ref get_or_create_chunk_at_world_position(const Vector3 &world_position); void set_voxel_with_tool(const bool mode_add, const Vector3 hit_position, const Vector3 hit_normal, const int selected_voxel, const int isolevel); int get_channel_index_info(const ChannelTypeInfo channel_type); VoxelWorld(); ~VoxelWorld(); protected: virtual void _generate_chunk(Ref chunk); virtual Ref _create_chunk(int x, int y, int z, Ref p_chunk); virtual int _get_channel_index_info(const ChannelTypeInfo channel_type); virtual void _set_voxel_with_tool(const bool mode_add, const Vector3 hit_position, const Vector3 hit_normal, const int selected_voxel, const int isolevel); virtual void _notification(int p_what); static void _bind_methods(); public: struct IntPos { int x; int y; int z; IntPos() { x = 0; y = 0; z = 0; } IntPos(int p_x, int p_y, int p_z) { x = p_x; y = p_y; z = p_z; } IntPos(const Vector3 &p) { x = p.x; y = p.y; z = p.z; } }; struct IntPosHasher { static _FORCE_INLINE_ uint32_t hash(const IntPos &v) { uint32_t hash = hash_djb2_one_32(v.x); hash = hash_djb2_one_32(v.y, hash); return hash_djb2_one_32(v.z, hash); } }; private: bool _editable; bool _is_priority_generation; int _chunk_size_x; int _chunk_size_y; int _chunk_size_z; int _current_seed; int _data_margin_start; int _data_margin_end; Ref _library; Ref _level_generator; float _voxel_scale; int _chunk_spawn_range; HashMap, IntPosHasher> _chunks; Vector> _chunks_vector; Vector> _world_areas; Vector> _voxel_structures; NodePath _player_path; Spatial *_player; bool _use_threads; int _max_concurrent_generations; Vector> _generation_queue; Vector> _generating; int _max_frame_chunk_build_steps; int _num_frame_chunk_build_steps; Vector> _lights; }; _FORCE_INLINE_ bool operator==(const VoxelWorld::IntPos &a, const VoxelWorld::IntPos &b) { return a.x == b.x && a.y == b.y && a.z == b.z; } VARIANT_ENUM_CAST(VoxelWorld::ChannelTypeInfo); #endif