#pragma once #include #include #include "../data/math.hpp" #include "../data/safe_queue.hpp" #include "../data/safe_priority_queue.hpp" #include "../data/circular_buffer.hpp" #include "../data/geometry/Ray.hpp" #include "../data/geometry/Frustum.hpp" #include "forward.h" #include "Area.hpp" #include "Voxel.hpp" namespace contouring { class Abstract; }; namespace buffer { class Abstract; } using namespace data; /// Universe data namespace world { /// Whole universe container class Universe { public: /// Distance management struct options { /// Radius in chunks to load if missing int loadDistance = 5; /// Radius in chunks to keep in memory int keepDistance = 6; /// Storage path std::string folderPath = "world"; }; Universe(const options &); ~Universe(); /// Update physics and contouring void update(const voxel_pos &pos, float deltaTime); /// Apply new options void setOptions(const options &); struct ray_target { area_ pos; Voxel value; voxel_pos offset; }; /// Get nearest voxel colliding ray /// @note ray in world scale std::optional raycast(const geometry::Ray &ray) const; /// Set voxel at pos std::optional set(const area_ &pos, const Voxel &val); /// Set cube of voxel with pos as center /// MAYBE: allow set multi area ItemList setCube(const area_ &pos, const Voxel &val, int radius); /// Check for collision on movement bool collide(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius = 0) const; /// Move with collision check /// @note must remove velocity after colision bool move(glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius = 0) const; /// Entities commun properties struct Entity { Entity(buffer::Abstract* buffer, const glm::vec3& size = glm::vec3(1), const glm::vec3& scale = glm::vec3(1)): buffer(buffer), size(size), scale(scale) { }; buffer::Abstract* buffer; glm::vec3 size; glm::vec3 scale; struct Instance { glm::ifvec3 pos; glm::vec3 velocity; }; data::generational::vector instances; }; /// Instante entity entity_instance_id addEntity(entity_id type, const Entity::Instance &instance); void getEntitiesModels(std::vector, buffer::Abstract *const>> &buffers, const std::optional &frustum, const glm::llvec3 &offset, int density); /// Change contouring worker void setContouring(const std::shared_ptr& ct); /// Get current contouring worker std::shared_ptr getContouring() const { return contouring; } private: chunk_pos last_pos = chunk_pos(INT_MAX); /// Alive areas containing chunks area_map areas; using area_it_t = robin_hood::pair>; /// Dead areas data::generational::vector far_areas; void saveAreas() const; data::generational::vector entities; bool running = true; std::vector workers; safe_priority_queue_map, std::shared_ptr, int, area_hash> loadQueue; //NOTE: consider Area const (getRegion uses mutex) safe_queue, std::shared_ptr>> loadedQueue; using save_task_t = std::pair>>; data::safe_queue saveQueue; //NOTE: consider Area and Chunk const int loadDistance; int keepDistance; std::string folderPath; dict_set dicts; /// Contouring worker std::shared_ptr contouring; }; }