Compare commits
No commits in common. "dev" and "main" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,7 +5,6 @@
|
|||||||
*.dbscn
|
*.dbscn
|
||||||
*.make
|
*.make
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
as.predefined
|
|
||||||
Makefile
|
Makefile
|
||||||
|
|
||||||
as.predefined_tmp
|
as.predefined_tmp
|
||||||
|
|||||||
@ -19,12 +19,9 @@ project "DeerService"
|
|||||||
"vendor/entt/include",
|
"vendor/entt/include",
|
||||||
"vendor/cereal/include",
|
"vendor/cereal/include",
|
||||||
"vendor/angelScript/include",
|
"vendor/angelScript/include",
|
||||||
"vendor/smallVector",
|
"vendor/smallVector"
|
||||||
"vendor/enet/include"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
links {"enet"}
|
|
||||||
|
|
||||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||||
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,8 @@ project "Deer"
|
|||||||
staticruntime "off"
|
staticruntime "off"
|
||||||
|
|
||||||
files {
|
files {
|
||||||
"src/DeerCore/**.h",
|
"src/Deer/**.h",
|
||||||
"src/DeerCore/**.cpp",
|
"src/Deer/**.cpp",
|
||||||
"src/DeerRender/**.h",
|
"src/DeerRender/**.h",
|
||||||
"src/DeerRender/**.cpp",
|
"src/DeerRender/**.cpp",
|
||||||
"src/Plattform/OpenGL/**.h",
|
"src/Plattform/OpenGL/**.h",
|
||||||
@ -35,8 +35,7 @@ project "Deer"
|
|||||||
"vendor/cereal/include",
|
"vendor/cereal/include",
|
||||||
"vendor/objload/include/objload",
|
"vendor/objload/include/objload",
|
||||||
"vendor/angelScript/include",
|
"vendor/angelScript/include",
|
||||||
"vendor/smallVector",
|
"vendor/smallVector"
|
||||||
"vendor/enet/include"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||||
@ -82,8 +81,7 @@ project "Deer"
|
|||||||
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
||||||
"gio-2.0", -- GIO library
|
"gio-2.0", -- GIO library
|
||||||
"gobject-2.0", -- GObject library
|
"gobject-2.0", -- GObject library
|
||||||
"pthread", -- POSIX threads library
|
"pthread" -- POSIX threads library
|
||||||
"enet"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
Deer/Include/Deer/Application.h
Executable file
32
Deer/Include/Deer/Application.h
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class ImGuiLayer;
|
||||||
|
namespace Core {
|
||||||
|
extern int argc;
|
||||||
|
extern char** argv;
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
|
class Timestep {
|
||||||
|
public:
|
||||||
|
Timestep(float time = 0.0f) : m_time(time) {}
|
||||||
|
|
||||||
|
float getSeconds() const { return m_time; }
|
||||||
|
float getMilliseconds() const { return m_time * 1000; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Application {
|
||||||
|
using Function = void (*)();
|
||||||
|
|
||||||
|
extern bool running;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
void setTickCallback(Function);
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
} // namespace Application
|
||||||
|
} // namespace Deer
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
#include "DeerCore/Tools/SmallVector.h"
|
#include "Deer/Tools/SmallVector.h"
|
||||||
|
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "DeerCore/Log.h"
|
#include "Deer/Log.h"
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
#include "glm/gtc/quaternion.hpp"
|
#include "glm/gtc/quaternion.hpp"
|
||||||
|
|
||||||
@ -18,16 +18,10 @@
|
|||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class ComponentScriptInstance;
|
class ComponentScriptInstance;
|
||||||
enum class EntityNetworkBehaviour : uint32_t {
|
|
||||||
PARENT = 0,
|
|
||||||
SERVER = 1 << 0,
|
|
||||||
CLIENT = 1 << 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TagComponent {
|
struct TagComponent {
|
||||||
std::string tag;
|
std::string tag;
|
||||||
uint32_t entityUID;
|
uint32_t entityUID;
|
||||||
EntityNetworkBehaviour networkBehaviour = EntityNetworkBehaviour::PARENT;
|
|
||||||
|
|
||||||
TagComponent() = default;
|
TagComponent() = default;
|
||||||
TagComponent(const TagComponent&) = default;
|
TagComponent(const TagComponent&) = default;
|
||||||
@ -36,18 +30,18 @@ namespace Deer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RelationshipComponent {
|
struct RelationshipComponent {
|
||||||
u_int32_t parent_id = 0;
|
uint16_t parent_id = 0;
|
||||||
|
|
||||||
// Use p-ranav's small_vector for children storage
|
// Use p-ranav's small_vector for children storage
|
||||||
// Inline capacity ENTITY_MAX_CHILDREN, fallback to heap if exceeded
|
// Inline capacity ENTITY_MAX_CHILDREN, fallback to heap if exceeded
|
||||||
ankerl::svector<u_int32_t, ENTITY_BUFFER_CHILDREN> children;
|
ankerl::svector<uint16_t, ENTITY_BUFFER_CHILDREN> children;
|
||||||
|
|
||||||
inline u_int32_t getChildId(size_t i) const {
|
inline uint16_t getChildId(size_t i) const {
|
||||||
DEER_CORE_ASSERT(i < children.size() && children[i] != 0, "Invalid child request {0}", i);
|
DEER_CORE_ASSERT(i < children.size() && children[i] != 0, "Invalid child request {0}", i);
|
||||||
return children[i];
|
return children[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void addChildId(u_int32_t childId) {
|
inline void addChildId(uint16_t childId) {
|
||||||
// Prevent duplicates
|
// Prevent duplicates
|
||||||
for (auto id : children)
|
for (auto id : children)
|
||||||
if (id == childId)
|
if (id == childId)
|
||||||
@ -55,7 +49,7 @@ namespace Deer {
|
|||||||
children.push_back(childId);
|
children.push_back(childId);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool removeChild(u_int32_t childId) {
|
inline bool removeChild(uint16_t childId) {
|
||||||
for (size_t i = 0; i < children.size(); ++i) {
|
for (size_t i = 0; i < children.size(); ++i) {
|
||||||
if (children[i] == childId) {
|
if (children[i] == childId) {
|
||||||
// Swap-remove for O(1)
|
// Swap-remove for O(1)
|
||||||
@ -73,7 +67,7 @@ namespace Deer {
|
|||||||
|
|
||||||
RelationshipComponent() = default;
|
RelationshipComponent() = default;
|
||||||
RelationshipComponent(const RelationshipComponent&) = default;
|
RelationshipComponent(const RelationshipComponent&) = default;
|
||||||
RelationshipComponent(u_int32_t _parent) : parent_id(_parent) {}
|
RelationshipComponent(uint16_t _parent) : parent_id(_parent) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransformComponent {
|
struct TransformComponent {
|
||||||
@ -81,9 +75,9 @@ namespace Deer {
|
|||||||
glm::vec3 scale = glm::vec3(1.0f);
|
glm::vec3 scale = glm::vec3(1.0f);
|
||||||
glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
TransformComponent() {}
|
TransformComponent() = default;
|
||||||
TransformComponent(glm::vec3 _position) : position(_position) {}
|
TransformComponent(glm::vec3 _position) : position(_position) {}
|
||||||
TransformComponent(const TransformComponent&) {}
|
TransformComponent(const TransformComponent&) = default;
|
||||||
|
|
||||||
inline const glm::vec3 getEulerAngles() {
|
inline const glm::vec3 getEulerAngles() {
|
||||||
return glm::degrees(glm::eulerAngles(rotation));
|
return glm::degrees(glm::eulerAngles(rotation));
|
||||||
83
Deer/Include/Deer/DataManagment.h
Normal file
83
Deer/Include/Deer/DataManagment.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
#include "Deer/Tools/TypeDefs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
/*
|
||||||
|
class DataSource {
|
||||||
|
public:
|
||||||
|
using DataImporter = [ClassOfTheDataImporter]
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
using StorageMetadata = std::unordered_map<std::string, std::string>;
|
||||||
|
template <typename T>
|
||||||
|
concept HasMetadata = requires(const std::string& location) {
|
||||||
|
{ T::loadMetadata(location) } -> std::same_as<StorageMetadata>;
|
||||||
|
{ T::saveMetadata(StorageMetadata{}, location) };
|
||||||
|
};
|
||||||
|
|
||||||
|
class StorageData {
|
||||||
|
public:
|
||||||
|
StorageData() = default;
|
||||||
|
StorageData(uint32_t dataSize) : size(dataSize), data(MakeScope<uint8_t[]>(dataSize)) {}
|
||||||
|
|
||||||
|
inline uint8_t* getData() { return data.get(); }
|
||||||
|
inline const uint8_t* getData() const { return data.get(); }
|
||||||
|
inline uint32_t getSize() const { return size; }
|
||||||
|
inline StorageMetadata& getMetadata() { return metadata; }
|
||||||
|
|
||||||
|
template <typename DataImporter, typename T>
|
||||||
|
Scope<T> deserialize();
|
||||||
|
|
||||||
|
template <typename DataImporter, typename T>
|
||||||
|
static StorageData serialize(const T&);
|
||||||
|
|
||||||
|
inline explicit operator bool() const { return size != 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
StorageMetadata metadata;
|
||||||
|
Scope<uint8_t[]> data = nullptr;
|
||||||
|
uint32_t size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DataSource>
|
||||||
|
class StorageBackend {
|
||||||
|
public:
|
||||||
|
static StorageData loadData(const std::string& location);
|
||||||
|
static void saveData(const std::string& location, const StorageData& data);
|
||||||
|
|
||||||
|
static StorageMetadata loadMetadata(const std::string& location);
|
||||||
|
static void saveMetadata(const StorageMetadata& metadata, const std::string& location);
|
||||||
|
|
||||||
|
static std::vector<std::string> indexResources(const std::string& location);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DataSource>
|
||||||
|
class DataManager {
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
static Scope<T> load(const std::string& dataId) {
|
||||||
|
StorageData data = StorageBackend<DataSource>::loadData(dataId);
|
||||||
|
|
||||||
|
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||||
|
data.getMetadata() = StorageBackend<DataSource>::loadMetadata(dataId);
|
||||||
|
data.getMetadata()["dataId"] = dataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.deserialize<typename DataSource::DataImporter, T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void store(const std::string& dataId, T& value) {
|
||||||
|
StorageData data = StorageData::serialize<typename DataSource::DataImporter, T>(value);
|
||||||
|
StorageBackend<DataSource>::saveData(dataId, data);
|
||||||
|
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||||
|
StorageBackend<DataSource>::saveMetadata(data.getMetadata(), dataId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Deer
|
||||||
62
Deer/Include/Deer/DataStore.h
Executable file
62
Deer/Include/Deer/DataStore.h
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Deer/Tools/Path.h"
|
||||||
|
|
||||||
|
#define DEER_RESOURCE_PATH "Assets"
|
||||||
|
|
||||||
|
#define DEER_VOXEL_PATH "Voxels"
|
||||||
|
#define DEER_VOXEL_DATA_PATH "Voxels/Data"
|
||||||
|
#define DEER_VOXEL_ASPECT_PATH "Voxels/Visuals"
|
||||||
|
#define DEER_VOXEL_TEXTURE_PATH "Voxels/Textures"
|
||||||
|
#define DEER_VOXEL_SHADER_PATH "Voxels/Shaders"
|
||||||
|
|
||||||
|
#define DEER_EDITOR_PATH "Editor"
|
||||||
|
#define DEER_EDITOR_PANEL_PATH "Editor/Panels"
|
||||||
|
#define DEER_EDITOR_SERVICE_PATH "Editor/Services"
|
||||||
|
|
||||||
|
#define DEER_MESH_EXTENSION ".dmesh"
|
||||||
|
#define DEER_SHADER_EXTENSION ".glsl"
|
||||||
|
#define DEER_SCRIPT_EXTENSION ".as"
|
||||||
|
|
||||||
|
#define DEER_BIN_PATH "bin"
|
||||||
|
#define DEER_TEMP_PATH "tmp"
|
||||||
|
#define DEER_NULL_PATH "null"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
|
||||||
|
struct DirectoryData {
|
||||||
|
std::vector<Path> dirs;
|
||||||
|
std::vector<Path> elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Namespace to manage memory interactions
|
||||||
|
namespace DataStore {
|
||||||
|
// Clears the cache of dir data
|
||||||
|
void clearCache();
|
||||||
|
|
||||||
|
// Rerturns a directory data with the elements relative to the id
|
||||||
|
const DirectoryData& getDirData(const Path& id, const Path& dir, const char* extension);
|
||||||
|
|
||||||
|
// TODO: Add safety
|
||||||
|
// Returns the data of the specified file path
|
||||||
|
bool loadFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size);
|
||||||
|
// Returns the data of the specified file path avoiding extension
|
||||||
|
bool loadGlobalFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size);
|
||||||
|
void freeFileData(uint8_t*);
|
||||||
|
|
||||||
|
void createFolder(const Path& path);
|
||||||
|
|
||||||
|
void saveFile(const Path&, uint8_t* data, uint32_t size);
|
||||||
|
uint8_t* readFile(const Path&, uint32_t* size);
|
||||||
|
void deleteFile(const Path&);
|
||||||
|
|
||||||
|
// Refactor----
|
||||||
|
void compressFiles(std::vector<Path> files, const Path& path);
|
||||||
|
std::vector<Path> getFiles(const Path& path,
|
||||||
|
const std::string& extension);
|
||||||
|
// Refactor----
|
||||||
|
} // namespace DataStore
|
||||||
|
} // namespace Deer
|
||||||
@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Components.h"
|
#include "Deer/Components.h"
|
||||||
#include "DeerCore/Log.h"
|
#include "Deer/Log.h"
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
#include "entt/entt.hpp"
|
#include "entt/entt.hpp"
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
#include "DeerRender/Render/FrameBuffer.h"
|
#include "DeerRender/Render/FrameBuffer.h"
|
||||||
#include "DeerRender/World.h"
|
#include "DeerRender/Scene.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -19,28 +19,37 @@
|
|||||||
namespace Deer {
|
namespace Deer {
|
||||||
class Entity;
|
class Entity;
|
||||||
|
|
||||||
class EntityEnvironment {
|
class Environment {
|
||||||
|
// Note: Outdated note
|
||||||
|
///////// NOTES ///////////
|
||||||
|
// - The entity id means the position in a array defined in Environment
|
||||||
|
// - The entity id is relative to a Environment so it can be a complete
|
||||||
|
// diferent entity in other environments
|
||||||
|
// - The entity number 0 is allways the root
|
||||||
|
// - There is a limit defined by ENVIRONMENT_MAX_ENTITIES of how many
|
||||||
|
// entities can be in an Environment
|
||||||
|
///////// NOTES ///////////
|
||||||
public:
|
public:
|
||||||
EntityEnvironment();
|
Environment();
|
||||||
~EntityEnvironment();
|
~Environment();
|
||||||
// This class can not be copyed
|
// This class can not be copyed
|
||||||
EntityEnvironment(const EntityEnvironment&) = delete;
|
Environment(const Environment&) = delete;
|
||||||
EntityEnvironment& operator=(EntityEnvironment&) = delete;
|
Environment& operator=(Environment&) = delete;
|
||||||
|
|
||||||
// Clears all entities
|
// Clears all entities
|
||||||
void clear();
|
void clear();
|
||||||
// Obtains the entity
|
// Obtains the entity
|
||||||
Entity& getEntity(uint32_t id);
|
Entity& getEntity(uint16_t id);
|
||||||
bool entityExists(uint32_t id) const;
|
bool entityExists(uint16_t id) const;
|
||||||
uint32_t getEntityCount() const;
|
uint16_t getEntityCount() const;
|
||||||
|
|
||||||
// Creates a entity child at root
|
// Creates a entity child at root
|
||||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||||
Entity& createEntity(const std::string& name = "");
|
Entity& createEntity(const std::string& name = "");
|
||||||
// Can be slow! This has to empty the stack of empty entities in case its necessary so use it in ascendent order!
|
// Can be slow! This has to empty the stack of empty entities in case its necessary so use it in ascendent order!
|
||||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||||
Entity& createEntityWithId(uint32_t id, const std::string& name = "");
|
Entity& createEntityWithId(uint16_t id, const std::string& name = "");
|
||||||
void destroyEntity(uint32_t id);
|
void destroyEntity(uint16_t id);
|
||||||
|
|
||||||
// Special behaviour
|
// Special behaviour
|
||||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||||
@ -53,19 +62,20 @@ namespace Deer {
|
|||||||
// Obtains the entity that is on the root of the environment
|
// Obtains the entity that is on the root of the environment
|
||||||
inline Entity& getRoot() { return getEntity(0); }
|
inline Entity& getRoot() { return getEntity(0); }
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
void render(const WorldCamera& camera);
|
void render(SceneCamera& camera);
|
||||||
#endif
|
#endif
|
||||||
Scope<entt::registry> m_registry;
|
Scope<entt::registry> m_registry;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t m_mainCamera = 0;
|
uint16_t m_mainCamera = 0;
|
||||||
|
|
||||||
std::stack<u_int32_t> unused_entities_spaces;
|
std::stack<u_int16_t> unused_entities_spaces;
|
||||||
std::vector<Entity> entities;
|
std::vector<Entity> entities;
|
||||||
|
|
||||||
friend class Entity;
|
friend class Entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Warning: This calss does not initialize for performance
|
||||||
class Entity {
|
class Entity {
|
||||||
public:
|
public:
|
||||||
Entity() {}
|
Entity() {}
|
||||||
@ -77,18 +87,15 @@ namespace Deer {
|
|||||||
Entity& duplicate();
|
Entity& duplicate();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
uint32_t getId() const { return entId; }
|
uint16_t getId() const { return entId; }
|
||||||
Entity& getParent() const;
|
Entity& getParent() const;
|
||||||
inline uint32_t getParentId() const { return parentId; }
|
inline uint16_t getParentId() const { return parentId; }
|
||||||
|
|
||||||
EntityNetworkBehaviour getForcedNetworkBehaviour();
|
|
||||||
bool isValidNetworkBehaviour(EntityNetworkBehaviour nb = EntityNetworkBehaviour::PARENT);
|
|
||||||
|
|
||||||
// TODO, enable transfer entitys from difrent environments
|
// TODO, enable transfer entitys from difrent environments
|
||||||
void setParent(Entity& parent);
|
void setParent(Entity& parent);
|
||||||
bool isDescendantOf(Entity& parent) const;
|
bool isDescendantOf(Entity& parent) const;
|
||||||
|
|
||||||
EntityEnvironment* getEntityEnvironment() const { return environment; }
|
Environment* getEnvironment() const { return environment; }
|
||||||
|
|
||||||
bool isRoot() const { return entId == 0; }
|
bool isRoot() const { return entId == 0; }
|
||||||
glm::mat4 getWorldMatrix() const;
|
glm::mat4 getWorldMatrix() const;
|
||||||
@ -100,14 +107,14 @@ namespace Deer {
|
|||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EntityEnvironment* environment = nullptr;
|
Environment* environment = nullptr;
|
||||||
entt::entity entHandle = entt::null;
|
entt::entity entHandle = entt::null;
|
||||||
uint32_t entId = 0;
|
uint16_t entId = 0;
|
||||||
uint32_t parentId = 0;
|
uint16_t parentId = 0;
|
||||||
|
|
||||||
Entity(entt::entity handle, EntityEnvironment* scene, uint32_t entityID);
|
Entity(entt::entity handle, Environment* scene, uint16_t entityID);
|
||||||
|
|
||||||
friend class EntityEnvironment;
|
friend class Environment;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
@ -116,7 +123,8 @@ namespace Deer {
|
|||||||
!environment->m_registry->all_of<T>(entHandle),
|
!environment->m_registry->all_of<T>(entHandle),
|
||||||
"Entity already have component {0}", typeid(T).name());
|
"Entity already have component {0}", typeid(T).name());
|
||||||
|
|
||||||
return environment->m_registry->emplace<T>(entHandle, std::forward<Args>(args)...);
|
return environment->m_registry->emplace<T>(
|
||||||
|
entHandle, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
@ -9,17 +10,32 @@ namespace spdlog {
|
|||||||
// Simple file to define logs functions optimized depending on the compilation
|
// Simple file to define logs functions optimized depending on the compilation
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
namespace Log {
|
class Log {
|
||||||
void init();
|
public:
|
||||||
void shutdown();
|
static void init();
|
||||||
|
static void shutdown();
|
||||||
|
|
||||||
void coreTrace(const char* msg);
|
static void coreTrace(const char* msg);
|
||||||
|
|
||||||
spdlog::logger* getCoreLogger();
|
static inline Ref<spdlog::logger>& getCoreLogger() {
|
||||||
spdlog::logger* getClientLogger();
|
return coreLogger;
|
||||||
spdlog::logger* getScriptLogger();
|
}
|
||||||
spdlog::logger* getEditorEngineLogger();
|
static inline Ref<spdlog::logger>& getClientLogger() {
|
||||||
}; // namespace Log
|
return clientLogger;
|
||||||
|
}
|
||||||
|
static inline Ref<spdlog::logger>& getScriptLogger() {
|
||||||
|
return scriptLogger;
|
||||||
|
}
|
||||||
|
static inline Ref<spdlog::logger>& getEditorEngineLogger() {
|
||||||
|
return EditorEngineLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Ref<spdlog::logger> coreLogger;
|
||||||
|
static Ref<spdlog::logger> clientLogger;
|
||||||
|
static Ref<spdlog::logger> scriptLogger;
|
||||||
|
static Ref<spdlog::logger> EditorEngineLogger;
|
||||||
|
};
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
|
|
||||||
#define DEER_CORE_TRACE(...) Deer::Log::getCoreLogger()->trace(__VA_ARGS__)
|
#define DEER_CORE_TRACE(...) Deer::Log::getCoreLogger()->trace(__VA_ARGS__)
|
||||||
51
Deer/Include/Deer/Scene.h
Executable file
51
Deer/Include/Deer/Scene.h
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/DataStore.h"
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
#include "Deer/Tools/Path.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/GizmoRenderer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Environment;
|
||||||
|
class GizmoRenderer;
|
||||||
|
|
||||||
|
// A scene is a 3d simulation with its environment and voxel world in case
|
||||||
|
// of initialized, here things can be simulated
|
||||||
|
namespace Scene {
|
||||||
|
// Clears all the assets and memory the Scene had conained
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// This is the cycle to execution of scripts and physics
|
||||||
|
void initExecution();
|
||||||
|
void tickExecution();
|
||||||
|
void endExecution();
|
||||||
|
|
||||||
|
bool getExecutingState();
|
||||||
|
uint32_t getCurrentExTick();
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
// This function renders with the default camera in the environment
|
||||||
|
void render();
|
||||||
|
void render(SceneCamera);
|
||||||
|
|
||||||
|
extern GizmoRenderer gizmoRenderer;
|
||||||
|
#endif
|
||||||
|
extern Environment environment;
|
||||||
|
} // namespace Scene
|
||||||
|
|
||||||
|
// Namespace to manage scenes in memory
|
||||||
|
namespace DataStore {
|
||||||
|
void loadScene(const Path& name);
|
||||||
|
void exportScene(const Path& name);
|
||||||
|
|
||||||
|
void exportRuntimeScene();
|
||||||
|
void importRuntimeScene();
|
||||||
|
} // namespace DataStore
|
||||||
|
} // namespace Deer
|
||||||
296
Deer/Include/Deer/Voxel.h
Executable file
296
Deer/Include/Deer/Voxel.h
Executable file
@ -0,0 +1,296 @@
|
|||||||
|
// Structure definition for voxel and voxel manipulation
|
||||||
|
// copyright Copyright (c) 2025 Deer
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/VoxelAspect.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Texture2D;
|
||||||
|
class Shader;
|
||||||
|
} // namespace Deer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VOXEL_INFO_TYPE_AIR "air"
|
||||||
|
#define VOXEL_INFO_TYPE_VOXEL "voxel"
|
||||||
|
#define VOXEL_INFO_TYPE_TRANSPARENT_VOXEL "transparentVoxel"
|
||||||
|
#define VOXEL_INFO_TYPE_CUSTOM "custom"
|
||||||
|
|
||||||
|
#define CHUNK_SIZE_X 32
|
||||||
|
#define CHUNK_SIZE_Y 32
|
||||||
|
#define CHUNK_SIZE_Z 32
|
||||||
|
#define CHUNK_SIZE(axis) \
|
||||||
|
((axis == 0) ? CHUNK_SIZE_X : (axis == 1) ? CHUNK_SIZE_Y \
|
||||||
|
: CHUNK_SIZE_Z)
|
||||||
|
|
||||||
|
#define LAYER_VOXELS CHUNK_SIZE_X* CHUNK_SIZE_Z
|
||||||
|
#define CHUNK_VOXELS CHUNK_SIZE_X* CHUNK_SIZE_Y* CHUNK_SIZE_Z
|
||||||
|
|
||||||
|
// TODO: Change this to be a inline function
|
||||||
|
#define VOXEL_POSITION(id) \
|
||||||
|
id.z + id.y* CHUNK_SIZE_Z + id.x* CHUNK_SIZE_Z* CHUNK_SIZE_Y
|
||||||
|
#define LAYER_VOXEL_POSITION(id) id.z + id.x* CHUNK_SIZE_Z
|
||||||
|
|
||||||
|
#define X_AXIS 0
|
||||||
|
#define Y_AXIS 1
|
||||||
|
#define Z_AXIS 2
|
||||||
|
|
||||||
|
// TODO: Change this to be a inline function
|
||||||
|
#define NORMAL_DIR(axis, normal) normalDirs[axis + normal * 3]
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct Voxel;
|
||||||
|
struct LayerVoxel;
|
||||||
|
|
||||||
|
extern Voxel nullVoxel;
|
||||||
|
extern Voxel emptyVoxel;
|
||||||
|
extern LayerVoxel nullLayerVoxel;
|
||||||
|
extern int normalDirs[3 * 6];
|
||||||
|
|
||||||
|
enum NormalDirection : uint8_t {
|
||||||
|
NORMAL_LEFT = 0,
|
||||||
|
NORMAL_RIGHT = 1,
|
||||||
|
NORMAL_DOWN = 2,
|
||||||
|
NORMAL_UP = 3,
|
||||||
|
NORMAL_BACK = 4,
|
||||||
|
NORMAL_FRONT = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class VoxelInfoType : uint8_t {
|
||||||
|
Air = 0,
|
||||||
|
Voxel = 1,
|
||||||
|
TransparentVoxel = 2,
|
||||||
|
Custom = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defines the general data of a voxel id stored in the array
|
||||||
|
// DataStore::voxelsInfo
|
||||||
|
struct VoxelInfo {
|
||||||
|
std::string name;
|
||||||
|
VoxelInfoType type = VoxelInfoType::Air;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Namespace to load and manage voxel data
|
||||||
|
namespace DataStore {
|
||||||
|
// List of the voxels loaded with loadVoxelsData()
|
||||||
|
extern std::vector<VoxelInfo> voxelsInfo;
|
||||||
|
|
||||||
|
// Loads basic voxel data from folder DEER_VOXEL_DATA_PATH defined in
|
||||||
|
// DataStore.h
|
||||||
|
void loadVoxelsData();
|
||||||
|
void createExampleVoxelData();
|
||||||
|
|
||||||
|
int32_t getVoxelID(const std::string&);
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
// List of the voxels Aspect loaded with loadVoxelsAspect()
|
||||||
|
extern std::vector<VoxelAspect> voxelsAspect;
|
||||||
|
|
||||||
|
// Loads voxel aspect from folder DEER_VOXEL_ASPECT_PATH defined in
|
||||||
|
// DataStore.h
|
||||||
|
void loadVoxelsAspect();
|
||||||
|
void createExampleVoxelAspect();
|
||||||
|
|
||||||
|
// Generates the texture atlas that the voxels demanded from folder
|
||||||
|
// DEER_VOXEL_TEXTURE_PATH defined in DataStore.h Warning : This
|
||||||
|
// function must be called with a render context, otherwise this will
|
||||||
|
// crash
|
||||||
|
void generateTextureAtlas();
|
||||||
|
// Loads the shaders for rendering chunks from folder
|
||||||
|
// DEER_VOXEL_SHADER_PATH defined in DataStore.h
|
||||||
|
void loadVoxelsShaders();
|
||||||
|
|
||||||
|
// Returns with & height of the texture atlas generated
|
||||||
|
// Warning: If you call this before generate Texture Atlas the return
|
||||||
|
// value will be 0
|
||||||
|
int getVoxelTextureAtlasSize();
|
||||||
|
// Texture atlas created with generateTextureAtlas() call
|
||||||
|
// Warning: You must have called generateTextureAtlas() in order to work
|
||||||
|
/// Ref<Texture2D>& getVoxelColorTextureAtlas();
|
||||||
|
// Returns the shader created with loadVoxelsShaders()
|
||||||
|
// Warning: You must have called loadVoxelsShaders() in order to work
|
||||||
|
/// Ref<Shader>& getSolidVoxelShader();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
} // namespace DataStore
|
||||||
|
|
||||||
|
// Structure to define what a voxel inside a world must have
|
||||||
|
struct Voxel {
|
||||||
|
// Reference to the voxel id
|
||||||
|
uint16_t id = 0;
|
||||||
|
|
||||||
|
Voxel() = default;
|
||||||
|
Voxel(uint16_t _id) : id(_id) {}
|
||||||
|
|
||||||
|
inline bool operator==(const Voxel& b) const { return id == b.id; }
|
||||||
|
inline bool isVoxelType() const {
|
||||||
|
return DataStore::voxelsInfo[id].type == VoxelInfoType::Voxel;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure to define the general cordinates of a voxel in the world
|
||||||
|
struct VoxelCordinates {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int32_t x, y, z;
|
||||||
|
};
|
||||||
|
std::array<int32_t, 3> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
VoxelCordinates(int32_t _x = 0, int32_t _y = 0, int32_t _z = 0)
|
||||||
|
: x(_x), y(_y), z(_z) {}
|
||||||
|
|
||||||
|
inline int32_t& operator[](int id) { return data[id]; }
|
||||||
|
inline bool operator==(const VoxelCordinates& b) const {
|
||||||
|
return x == b.x && y == b.y && z == b.z;
|
||||||
|
}
|
||||||
|
inline bool isNull() const { return x < 0 || y < 0 || z < 0; }
|
||||||
|
inline void makeNull() { x = -1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stucture that defines the info of a layer voxel
|
||||||
|
struct LayerVoxel {
|
||||||
|
uint16_t height = 0;
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
uint16_t ambient_light_height = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LayerVoxel() = default;
|
||||||
|
LayerVoxel(uint16_t _height) : height(_height) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returning info of a raycast
|
||||||
|
struct VoxelRayResult {
|
||||||
|
float distance = 0;
|
||||||
|
VoxelCordinates hitPos;
|
||||||
|
uint8_t face = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Coordinates of a chunk
|
||||||
|
struct ChunkID {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
uint16_t z;
|
||||||
|
};
|
||||||
|
std::array<uint16_t, 3> axis;
|
||||||
|
};
|
||||||
|
|
||||||
|
ChunkID(uint16_t _x = 0, uint16_t _y = 0, uint16_t _z = 0)
|
||||||
|
: x(_x), y(_y), z(_z) {}
|
||||||
|
|
||||||
|
inline bool operator==(const ChunkID& b) const {
|
||||||
|
return x == b.x && y == b.y && z == b.z;
|
||||||
|
}
|
||||||
|
inline uint16_t& operator[](size_t i) { return axis[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChunkIDHash {
|
||||||
|
size_t operator()(const ChunkID& chunk) const {
|
||||||
|
size_t h1 = std::hash<uint16_t>{}(chunk.x);
|
||||||
|
size_t h2 = std::hash<uint16_t>{}(chunk.y);
|
||||||
|
size_t h3 = std::hash<uint16_t>{}(chunk.z);
|
||||||
|
|
||||||
|
size_t result = h1;
|
||||||
|
result = result * 31 + h2;
|
||||||
|
result = result * 31 + h3;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cordinates of a Layer
|
||||||
|
struct LayerID {
|
||||||
|
uint16_t x = 0;
|
||||||
|
uint16_t z = 0;
|
||||||
|
|
||||||
|
LayerID() = default;
|
||||||
|
LayerID(uint16_t _x, uint16_t _z) : x(_x), z(_z) {}
|
||||||
|
inline bool operator==(const LayerID& b) const {
|
||||||
|
return x == b.x && z == b.z;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Coordinates of a layer voxel relative to the Layer Chunk
|
||||||
|
struct LayerVoxelID {
|
||||||
|
uint8_t x = 0;
|
||||||
|
uint8_t z = 0;
|
||||||
|
|
||||||
|
LayerVoxelID() = default;
|
||||||
|
LayerVoxelID(uint8_t _x, uint8_t _z = 0) : x(_x), z(_z) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Coordinates of a voxel inside a Chunk
|
||||||
|
struct ChunkVoxelID {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
uint8_t z;
|
||||||
|
};
|
||||||
|
std::array<uint8_t, 3> axis;
|
||||||
|
};
|
||||||
|
|
||||||
|
ChunkVoxelID(uint8_t _x = 0, uint8_t _y = 0, uint8_t _z = 0)
|
||||||
|
: x(_x), y(_y), z(_z) {}
|
||||||
|
inline uint8_t& operator[](size_t i) { return axis[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts the chunk coordinaes and the chunk voxel coordinates from a
|
||||||
|
// world position
|
||||||
|
inline void extractChunkCordinates(uint32_t x, uint32_t y, uint32_t z,
|
||||||
|
ChunkID& _chunkID,
|
||||||
|
ChunkVoxelID& _chunkVoxelID) {
|
||||||
|
uint16_t posX = x;
|
||||||
|
uint16_t posY = y;
|
||||||
|
uint16_t posZ = z;
|
||||||
|
|
||||||
|
_chunkID.x = posX >> 5;
|
||||||
|
_chunkID.y = posY >> 5;
|
||||||
|
_chunkID.z = posZ >> 5;
|
||||||
|
|
||||||
|
_chunkVoxelID.x = posX & 31;
|
||||||
|
_chunkVoxelID.y = posY & 31;
|
||||||
|
_chunkVoxelID.z = posZ & 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the chunk coordinaes and the chunk voxel chunk coordinates from
|
||||||
|
// a world position
|
||||||
|
inline void extractChunkCordinates(VoxelCordinates coords,
|
||||||
|
ChunkID& _chunkID,
|
||||||
|
ChunkVoxelID& _chunkVoxelID) {
|
||||||
|
uint16_t posX = coords.x;
|
||||||
|
uint16_t posY = coords.y;
|
||||||
|
uint16_t posZ = coords.z;
|
||||||
|
|
||||||
|
_chunkID.x = posX >> 5;
|
||||||
|
_chunkID.y = posY >> 5;
|
||||||
|
_chunkID.z = posZ >> 5;
|
||||||
|
|
||||||
|
_chunkVoxelID.x = posX & 31;
|
||||||
|
_chunkVoxelID.y = posY & 31;
|
||||||
|
_chunkVoxelID.z = posZ & 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the layer chunk coordinaes and the layer chunk voxel coordinates
|
||||||
|
// from a world position
|
||||||
|
inline void extractLayerCordinates(uint32_t x, uint32_t z,
|
||||||
|
LayerID& _layerID,
|
||||||
|
LayerVoxelID& _layerVoxelID) {
|
||||||
|
uint16_t posX = x;
|
||||||
|
uint16_t posZ = z;
|
||||||
|
|
||||||
|
_layerID.x = posX >> 5;
|
||||||
|
_layerID.z = posZ >> 5;
|
||||||
|
|
||||||
|
_layerVoxelID.x = posX & 31;
|
||||||
|
_layerVoxelID.z = posZ & 31;
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
209
Deer/Include/Deer/VoxelWorld.h
Executable file
209
Deer/Include/Deer/VoxelWorld.h
Executable file
@ -0,0 +1,209 @@
|
|||||||
|
// copyright Copyright (c) 2025 Deer
|
||||||
|
#pragma once
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Voxel.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Chunk;
|
||||||
|
class Layer;
|
||||||
|
struct SceneCamera;
|
||||||
|
struct VoxelWorldProps;
|
||||||
|
struct VoxelWorldRenderData;
|
||||||
|
|
||||||
|
// Properties of a Voxel World
|
||||||
|
struct VoxelWorldProps {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t chunkSizeX;
|
||||||
|
uint8_t chunkSizeY;
|
||||||
|
uint8_t chunkSizeZ;
|
||||||
|
};
|
||||||
|
std::array<uint8_t, 3> axis;
|
||||||
|
};
|
||||||
|
|
||||||
|
VoxelWorldProps() = default;
|
||||||
|
VoxelWorldProps(uint8_t _chunkSizeX, uint8_t _chunkSizeY,
|
||||||
|
uint8_t _chunkSizeZ)
|
||||||
|
: chunkSizeX(_chunkSizeX),
|
||||||
|
chunkSizeY(_chunkSizeY),
|
||||||
|
chunkSizeZ(_chunkSizeZ) {}
|
||||||
|
|
||||||
|
inline uint8_t& operator[](size_t i) { return axis[i]; }
|
||||||
|
|
||||||
|
// Returns the count of chunks
|
||||||
|
inline int getChunkCount() const {
|
||||||
|
return chunkSizeX * chunkSizeY * chunkSizeZ;
|
||||||
|
}
|
||||||
|
// Returns the count of layers
|
||||||
|
inline int getLayerCount() const { return chunkSizeX * chunkSizeZ; }
|
||||||
|
// Returns the internal id of a chunk relative to a Voxel World Props
|
||||||
|
// from a chunk id
|
||||||
|
inline int getWorldChunkID(ChunkID chunkID) const {
|
||||||
|
return chunkID.z + chunkID.y * chunkSizeZ +
|
||||||
|
chunkID.x * chunkSizeZ * chunkSizeY;
|
||||||
|
}
|
||||||
|
// Returns the internal id of a layer relative to a Voxel World Props
|
||||||
|
// from a Layer id
|
||||||
|
inline int getWorldLayerID(LayerID layerID) const {
|
||||||
|
return layerID.z + layerID.x * chunkSizeZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the LayerID from a internal Layer id relative to Voxel World
|
||||||
|
// Props
|
||||||
|
inline LayerID getLayerID(int id) const {
|
||||||
|
LayerID l_id;
|
||||||
|
|
||||||
|
l_id.x = id / chunkSizeZ;
|
||||||
|
id -= l_id.x * chunkSizeZ;
|
||||||
|
|
||||||
|
l_id.z = id;
|
||||||
|
return l_id;
|
||||||
|
}
|
||||||
|
// Extracts the ChunkID from a internal Chunk id relative to Voxel World
|
||||||
|
// Props
|
||||||
|
inline ChunkID getChunkID(int id) const {
|
||||||
|
ChunkID c_id;
|
||||||
|
|
||||||
|
c_id.x = id / (chunkSizeZ * chunkSizeY);
|
||||||
|
id -= c_id.x * (chunkSizeZ * chunkSizeY);
|
||||||
|
|
||||||
|
c_id.y = id / chunkSizeZ;
|
||||||
|
id -= c_id.y * chunkSizeZ;
|
||||||
|
|
||||||
|
c_id.z = id;
|
||||||
|
return c_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the Chunk id is inside the voxel World bounds
|
||||||
|
inline bool isValid(ChunkID chunkID) const {
|
||||||
|
return chunkID.x >= 0 && chunkID.x < chunkSizeX && chunkID.y >= 0 &&
|
||||||
|
chunkID.y < chunkSizeY && chunkID.z >= 0 &&
|
||||||
|
chunkID.z < chunkSizeZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the Layer id is inside the voxel World bounds
|
||||||
|
inline bool isValid(LayerID layerID) const {
|
||||||
|
return layerID.x >= 0 && layerID.x < chunkSizeX && layerID.z >= 0 &&
|
||||||
|
layerID.z < chunkSizeZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the max amount of voxels in the Voxel World Props
|
||||||
|
inline int getMaxVoxelCount() const {
|
||||||
|
return getChunkCount() * CHUNK_VOXELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamps the coordinates of a Voxel World Coordinates to be inside the
|
||||||
|
// voxel world props
|
||||||
|
inline void clampCordinates(VoxelCordinates& coords) const {
|
||||||
|
if (coords.x < 0)
|
||||||
|
coords.x = 0;
|
||||||
|
else if (coords.x >= chunkSizeX * CHUNK_SIZE_X)
|
||||||
|
coords.x = chunkSizeX * CHUNK_SIZE_X - 1;
|
||||||
|
|
||||||
|
if (coords.y < 0)
|
||||||
|
coords.y = 0;
|
||||||
|
else if (coords.y >= chunkSizeY * CHUNK_SIZE_Y)
|
||||||
|
coords.y = chunkSizeY * CHUNK_SIZE_Y - 1;
|
||||||
|
|
||||||
|
if (coords.z < 0)
|
||||||
|
coords.z = 0;
|
||||||
|
else if (coords.z >= chunkSizeZ * CHUNK_SIZE_Z)
|
||||||
|
coords.z = chunkSizeZ * CHUNK_SIZE_Z - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes 2 Voxel coordinates and outputs them in the same variables
|
||||||
|
// being the min with the min values and the max with the max This is
|
||||||
|
// useful for loops
|
||||||
|
inline void clampAndSetMinMax(VoxelCordinates& min,
|
||||||
|
VoxelCordinates& max) const {
|
||||||
|
VoxelCordinates a_cache = min;
|
||||||
|
VoxelCordinates b_cache = max;
|
||||||
|
|
||||||
|
for (int x = 0; x < 3; x++) {
|
||||||
|
if (a_cache[x] > b_cache[x]) {
|
||||||
|
max[x] = a_cache[x];
|
||||||
|
min[x] = b_cache[x];
|
||||||
|
} else {
|
||||||
|
min[x] = a_cache[x];
|
||||||
|
max[x] = b_cache[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clampCordinates(min);
|
||||||
|
clampCordinates(max);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class to manage the voxels
|
||||||
|
namespace VoxelWorld {
|
||||||
|
void initialize(const VoxelWorldProps&);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Returns the voxel in a voxel coordinates
|
||||||
|
Voxel readVoxel(VoxelCordinates);
|
||||||
|
// Sets the voxel in the coordinates to the value
|
||||||
|
void setVoxel(VoxelCordinates, Voxel value);
|
||||||
|
|
||||||
|
// Fills a space with the voxel value inside the 2 coordinates
|
||||||
|
// Note that you don't have to give then ordeered by min and max
|
||||||
|
void fillVoxels(VoxelCordinates, VoxelCordinates, Voxel value);
|
||||||
|
// Remplaces the ref voxel with the value of a space inside the 2 coordinates
|
||||||
|
// Note that you don't have to give then ordeered by min and max
|
||||||
|
void remplaceVoxels(VoxelCordinates, VoxelCordinates, Voxel ref, Voxel value);
|
||||||
|
|
||||||
|
// Returns the layer data of a woorld coordinates
|
||||||
|
// Note out of bounds will return a default Layer Voxel
|
||||||
|
LayerVoxel readLayerVoxel(int x, int z);
|
||||||
|
// Calculates the max height of a layer in a space
|
||||||
|
// Note out of bounds will return a 0 of height
|
||||||
|
// Tip: this will calculate, you should use the cached height in a layer voxel
|
||||||
|
uint16_t calculateLayerVoxelHeight(int x, int z);
|
||||||
|
|
||||||
|
// Raycast a ray from a source and dir
|
||||||
|
VoxelRayResult rayCast(glm::vec3 position, glm::vec3 dir,
|
||||||
|
float maxDistance = 10.0f);
|
||||||
|
// Raycast a ray from a source and dir ignoring if the ray stats inside a voxel
|
||||||
|
VoxelRayResult rayCast_editor(glm::vec3 position, glm::vec3 dir,
|
||||||
|
float maxDistance = 10.0f);
|
||||||
|
|
||||||
|
bool isInitialized();
|
||||||
|
|
||||||
|
// Returns the voxel world props used in the voxel world
|
||||||
|
// Note that you can't change the world size unless you create a new Voxel World
|
||||||
|
const VoxelWorldProps& getWorldProps();
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
// Renders the current voxel world with a specified scene camera
|
||||||
|
void render(const SceneCamera&);
|
||||||
|
// Generates the next chunk mesh
|
||||||
|
void bakeNextChunk();
|
||||||
|
|
||||||
|
// Light data
|
||||||
|
VoxelLight readLight(VoxelCordinates);
|
||||||
|
VoxelLight& modLight(VoxelCordinates);
|
||||||
|
|
||||||
|
// Chunk vertex creation
|
||||||
|
void genSolidVoxel(ChunkID chunkID, ChunkVoxelID chunkVoxelID);
|
||||||
|
|
||||||
|
// --- Light propagation ---
|
||||||
|
// Warning: This function is private and needs to have min and max
|
||||||
|
// clamped and in order
|
||||||
|
void bakeVoxelLight(VoxelCordinates min, VoxelCordinates max);
|
||||||
|
void bakeVoxelLightFromPoint(VoxelCordinates);
|
||||||
|
void bakeAmbientLight(int minX, int maxX, int minZ, int maxZ);
|
||||||
|
void bakeAmbientLightFromPoint(int x, int z);
|
||||||
|
|
||||||
|
void resolveNextAmbientLightPropagation();
|
||||||
|
void resolveNextVoxelLightPropagation();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LayerVoxel& modLayerVoxel(int x, int z);
|
||||||
|
} // namespace VoxelWorld
|
||||||
|
} // namespace Deer
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
using Function = void (*)();
|
|
||||||
|
|
||||||
namespace Engine {
|
|
||||||
void init();
|
|
||||||
void shutdown();
|
|
||||||
|
|
||||||
void setUpdateCallback(Function);
|
|
||||||
} // namespace Engine
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Tools/Memory.h"
|
|
||||||
#include "DeerCore/Tools/TypeDefs.h"
|
|
||||||
|
|
||||||
typedef struct _ENetPeer ENetPeer;
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Network {
|
|
||||||
struct ServerSettings;
|
|
||||||
struct DeerClient;
|
|
||||||
|
|
||||||
void initServer(const ServerSettings&);
|
|
||||||
void shutdownServer();
|
|
||||||
|
|
||||||
void flushServerEvents();
|
|
||||||
|
|
||||||
enum class DeerClientState : int {
|
|
||||||
NotConnected = 0,
|
|
||||||
Connected = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DeerClient {
|
|
||||||
DeerClientState clientState = DeerClientState::NotConnected;
|
|
||||||
ENetPeer* internalPeer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ServerSettings {
|
|
||||||
uint32_t port = 500;
|
|
||||||
uint32_t maxClients = 32;
|
|
||||||
uint32_t maxOutgoingBand = 0;
|
|
||||||
uint32_t maxIncomingBand = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Network
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Tools/Memory.h"
|
|
||||||
#include "DeerCore/Tools/Path.h"
|
|
||||||
#include "DeerCore/Tools/TypeDefs.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class asIScriptEngine;
|
|
||||||
class asIScriptObject;
|
|
||||||
class asIScriptFunction;
|
|
||||||
class asITypeInfo;
|
|
||||||
class asIScriptContext;
|
|
||||||
class asIScriptModule;
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class ScriptEnvironment;
|
|
||||||
class ScriptSystem;
|
|
||||||
class ScriptEnvironmentContextData;
|
|
||||||
class World;
|
|
||||||
|
|
||||||
namespace Scripting {
|
|
||||||
// The event type is necessary to know wich parameters to put
|
|
||||||
enum class EventType {
|
|
||||||
void_event // Defines a event with void as return and no parameter
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SystemEvent {
|
|
||||||
EventType eventType;
|
|
||||||
std::string eventName;
|
|
||||||
SystemEvent(const std::string _name, EventType _type) : eventName(_name), eventType(_type) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SystemDescription {
|
|
||||||
std::string baseTypeName;
|
|
||||||
std::string moduleName;
|
|
||||||
std::vector<SystemEvent> events;
|
|
||||||
SystemDescription(const std::string& _baseTypeName = "", const std::string& _moduleName = "", const std::vector<SystemEvent>& _events = {}) : baseTypeName(_baseTypeName), moduleName(_moduleName), events(_events) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Functions called by Engine
|
|
||||||
void init();
|
|
||||||
void shutdown();
|
|
||||||
|
|
||||||
void registerInterface(const char* name);
|
|
||||||
void registerInterfaceFunction(const char* name, const char* funcName, EventType funcType);
|
|
||||||
|
|
||||||
asIScriptEngine* getScriptEngine();
|
|
||||||
void compileFiles(const Path&, const char* moduleName);
|
|
||||||
|
|
||||||
Scope<ScriptEnvironment> createScriptEnvironment(const SystemDescription& systemDescription);
|
|
||||||
} // namespace Scripting
|
|
||||||
|
|
||||||
struct ScriptObjectGroup {
|
|
||||||
public:
|
|
||||||
// returns false if the object already existed
|
|
||||||
bool createScriptObject(size_t systemIndex);
|
|
||||||
|
|
||||||
void executeOnGroup_voidEvent(size_t eventIndex);
|
|
||||||
void executeOnObject_voidEvent(size_t systemIndex, size_t eventIndex);
|
|
||||||
void executeOnObject_voidEvent(ScriptSystem* system, size_t eventIndex);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScriptObjectGroup(ScriptEnvironment* env);
|
|
||||||
|
|
||||||
Scope<asIScriptObject*[]> systemInstances;
|
|
||||||
ScriptEnvironment* environment;
|
|
||||||
friend ScriptSystem;
|
|
||||||
friend ScriptEnvironment;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScriptSystem {
|
|
||||||
public:
|
|
||||||
const char* getSystemName();
|
|
||||||
bool hasFunction(size_t index);
|
|
||||||
size_t getSystemIndex();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScriptSystem(const Scripting::SystemDescription& desc, asITypeInfo* type, size_t _systemIndex);
|
|
||||||
|
|
||||||
asITypeInfo* systemType;
|
|
||||||
Scope<asIScriptFunction*[]> environmentFunctions;
|
|
||||||
size_t systemIndex;
|
|
||||||
|
|
||||||
friend ScriptEnvironment;
|
|
||||||
friend ScriptObjectGroup;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Script Environment is based of one angelscript interface, the clas analizes all the classes that derives from that
|
|
||||||
// interface and calls them systems, I extract the functions as defined from system description and then the user can tell me to create a
|
|
||||||
// system group, a system group can have each system created or not
|
|
||||||
class ScriptEnvironment {
|
|
||||||
public:
|
|
||||||
~ScriptEnvironment();
|
|
||||||
|
|
||||||
ScriptObjectGroup* createGroupWithAllSystems();
|
|
||||||
ScriptObjectGroup* createEmptyGroup();
|
|
||||||
|
|
||||||
size_t getSystemCount();
|
|
||||||
ScriptSystem* getSystemByIndex(size_t index);
|
|
||||||
|
|
||||||
void tieWorld(World* world);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Scripting::SystemDescription systemDescription;
|
|
||||||
asIScriptContext* context;
|
|
||||||
asIScriptModule* module;
|
|
||||||
asITypeInfo* baseType;
|
|
||||||
|
|
||||||
std::vector<Scope<ScriptSystem>> systems;
|
|
||||||
std::vector<Scope<ScriptObjectGroup>> systemGroups;
|
|
||||||
Scope<ScriptEnvironmentContextData> environmentContext;
|
|
||||||
|
|
||||||
ScriptEnvironment(const Scripting::SystemDescription&);
|
|
||||||
friend Scope<ScriptEnvironment> Scripting::createScriptEnvironment(const Scripting::SystemDescription& systemDescription);
|
|
||||||
friend ScriptObjectGroup;
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "cereal/cereal.hpp"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Mesh.h"
|
|
||||||
#include "DeerRender/Resource.h"
|
|
||||||
#include "DeerRender/Shader.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Tools/Memory.h"
|
|
||||||
#include <functional>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
struct WorldSerializationSettings {
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
bool includeServer = false;
|
|
||||||
bool includeClient = true;
|
|
||||||
|
|
||||||
std::function<Resource<GPUMesh>(ResourceId)> meshLoadingFunction = nullptr;
|
|
||||||
std::function<Resource<Shader>(ResourceId)> shaderLoadingFunction = nullptr;
|
|
||||||
#else
|
|
||||||
bool includeServer = true;
|
|
||||||
bool includeClient = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive& archive) {
|
|
||||||
archive(CEREAL_NVP(includeServer));
|
|
||||||
archive(CEREAL_NVP(includeClient));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Serialization/WorldSettings.h"
|
|
||||||
#include "DeerCore/Tools/Path.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class World;
|
|
||||||
class WorldSettings;
|
|
||||||
|
|
||||||
namespace Universe {
|
|
||||||
World* createWorld(const WorldSettings&);
|
|
||||||
|
|
||||||
World* loadWorldFromJson(const WorldSettings&, WorldSerializationSettings&, const Path&);
|
|
||||||
void saveWorldInJson(World*, WorldSerializationSettings& serializationSettings, const Path& path);
|
|
||||||
|
|
||||||
void destroyAllWorlds();
|
|
||||||
void flushDestroyedWorlds();
|
|
||||||
} // namespace Universe
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Tools/Memory.h"
|
|
||||||
#include "DeerCore/Tools/TypeDefs.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#define CLUSTER_SIZE 16
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Resource.h"
|
|
||||||
namespace Deer {
|
|
||||||
class VoxelBuilder;
|
|
||||||
class GPUMesh;
|
|
||||||
} // namespace Deer
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class VoxelWorldData;
|
|
||||||
|
|
||||||
struct VoxelType {
|
|
||||||
std::string id;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VoxelEnvironment {
|
|
||||||
public:
|
|
||||||
VoxelEnvironment();
|
|
||||||
~VoxelEnvironment();
|
|
||||||
|
|
||||||
void modifyVoxel(uint32_t voxelId, int x, int y, int z);
|
|
||||||
uint32_t getVoxel(int x, int y, int z);
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
public:
|
|
||||||
Resource<GPUMesh> buildCluster(int x, int y, int z);
|
|
||||||
Scope<VoxelBuilder> voxelBuilder;
|
|
||||||
#endif
|
|
||||||
private:
|
|
||||||
Scope<VoxelWorldData> voxelWorldData;
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Tools/Memory.h"
|
|
||||||
#include "DeerCore/Tools/TypeDefs.h"
|
|
||||||
#include "DeerCore/Universe.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class EntityEnvironment;
|
|
||||||
class GizmoRenderer;
|
|
||||||
class World;
|
|
||||||
|
|
||||||
struct WorldCamera;
|
|
||||||
using WorldCallback = std::function<void(World&)>;
|
|
||||||
|
|
||||||
struct WorldSettings {
|
|
||||||
WorldCallback updateCallback;
|
|
||||||
u_int32_t updateFrequency;
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
WorldCallback renderCallback;
|
|
||||||
u_int32_t renderFrequency;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class WorldState {
|
|
||||||
Created,
|
|
||||||
Executing,
|
|
||||||
StopRequested,
|
|
||||||
Stopped,
|
|
||||||
DestroyQueued,
|
|
||||||
ReadyToDestroy
|
|
||||||
};
|
|
||||||
|
|
||||||
class World {
|
|
||||||
public:
|
|
||||||
~World();
|
|
||||||
|
|
||||||
void execute();
|
|
||||||
void stopExecution();
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
WorldState getExecutionState();
|
|
||||||
Scope<EntityEnvironment> entityEnvironment;
|
|
||||||
const WorldSettings& getWorldSettings() { return worldSettings; }
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
inline float getRenderDeltaTime() { return renderDeltaTime; }
|
|
||||||
void setRenderFrequency(int);
|
|
||||||
#endif
|
|
||||||
private:
|
|
||||||
World(const WorldSettings&);
|
|
||||||
|
|
||||||
std::atomic<WorldState> executingState;
|
|
||||||
WorldSettings worldSettings;
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
float renderDeltaTime;
|
|
||||||
#endif
|
|
||||||
friend World* Universe::createWorld(const WorldSettings& worldSettings);
|
|
||||||
}; // namespace World
|
|
||||||
} // namespace Deer
|
|
||||||
21
Deer/Include/DeerRender/Application.h
Normal file
21
Deer/Include/DeerRender/Application.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "Deer/Application.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Events/ApplicationEvent.h"
|
||||||
|
#include "DeerRender/Events/Event.h"
|
||||||
|
#include "DeerRender/Window.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Application {
|
||||||
|
using EventFunction = void(*)(Event&);
|
||||||
|
|
||||||
|
void initWindow();
|
||||||
|
void shutdownWindow();
|
||||||
|
|
||||||
|
void setRenderCallback(Function);
|
||||||
|
void setEventCallback(EventFunction);
|
||||||
|
|
||||||
|
Window& getWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Components.h"
|
#include "Deer/Components.h"
|
||||||
|
|
||||||
#include "DeerRender/Mesh.h"
|
#include "DeerRender/Mesh.h"
|
||||||
#include "DeerRender/Shader.h"
|
#include "DeerRender/Shader.h"
|
||||||
@ -18,15 +18,21 @@ namespace Deer {
|
|||||||
MeshComponent(const MeshComponent&) = default;
|
MeshComponent(const MeshComponent&) = default;
|
||||||
|
|
||||||
Resource<GPUMesh> mesh;
|
Resource<GPUMesh> mesh;
|
||||||
Resource<Shader> shader;
|
|
||||||
Resource<Texture> texture;
|
|
||||||
|
|
||||||
bool active = true;
|
bool active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShaderComponent {
|
||||||
|
ShaderComponent() = default;
|
||||||
|
ShaderComponent(Resource<Shader> _shader) : shader(_shader) {}
|
||||||
|
ShaderComponent(const ShaderComponent&) = default;
|
||||||
|
|
||||||
|
Resource<Shader> shader;
|
||||||
|
Resource<Texture> texture;
|
||||||
|
};
|
||||||
|
|
||||||
struct CameraComponent {
|
struct CameraComponent {
|
||||||
CameraComponent() {}
|
CameraComponent() = default;
|
||||||
CameraComponent(const CameraComponent&) {}
|
CameraComponent(const CameraComponent&) = default;
|
||||||
|
|
||||||
float fov = glm::radians(50.0f);
|
float fov = glm::radians(50.0f);
|
||||||
float aspect = 16 / 9;
|
float aspect = 16 / 9;
|
||||||
@ -35,4 +41,11 @@ namespace Deer {
|
|||||||
|
|
||||||
inline glm::mat4 getMatrix() const { return glm::perspective(fov, aspect, nearZ, farZ); }
|
inline glm::mat4 getMatrix() const { return glm::perspective(fov, aspect, nearZ, farZ); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextureComponent {
|
||||||
|
TextureComponent() = default;
|
||||||
|
TextureComponent(const TextureComponent&) = default;
|
||||||
|
|
||||||
|
Resource<Texture> texture;
|
||||||
|
};
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
2
Deer/Include/DeerRender/DataManager.h
Normal file
2
Deer/Include/DeerRender/DataManager.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/DataManager.h"
|
||||||
2
Deer/Include/DeerRender/DataManagment.h
Normal file
2
Deer/Include/DeerRender/DataManagment.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/DataManagment.h"
|
||||||
2
Deer/Include/DeerRender/DataStore.h
Normal file
2
Deer/Include/DeerRender/DataStore.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/DataStore.h"
|
||||||
@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Engine.h"
|
|
||||||
#include "DeerRender/Events/Event.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
using EventFunction = void (*)(Event&);
|
|
||||||
class World;
|
|
||||||
class Window;
|
|
||||||
|
|
||||||
namespace Engine {
|
|
||||||
void setRenderCallback(Function);
|
|
||||||
void setEventCallback(EventFunction);
|
|
||||||
|
|
||||||
void beginRender();
|
|
||||||
void endRender();
|
|
||||||
|
|
||||||
World& getMainWorld();
|
|
||||||
Window& getWindow();
|
|
||||||
} // namespace Engine
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/EntityEnviroment.h"
|
|
||||||
2
Deer/Include/DeerRender/Enviroment.h
Normal file
2
Deer/Include/DeerRender/Enviroment.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Enviroment.h"
|
||||||
@ -1,30 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerRender/Render/FrameBuffer.h"
|
#include "DeerRender/Render/FrameBuffer.h"
|
||||||
#include "DeerRender/Resource.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
struct FrameBufferData {
|
// TODO: Add safety
|
||||||
enum class FrameBufferType : int {
|
namespace FrameBufferManager {
|
||||||
RGBA8 = 1,
|
uint16_t createRGBA8FrameBuffer(std::string& name, int, int);
|
||||||
GBuffer = 2,
|
void resizeFrameBuffer(uint16_t frameBufferId, int, int);
|
||||||
};
|
|
||||||
|
|
||||||
FrameBufferType frameBufferType;
|
int getFrameBufferWidth(uint16_t frameBufferId);
|
||||||
int sizeX, sizeY;
|
int getFrameBufferHeight(uint16_t frameBufferId);
|
||||||
int samples;
|
|
||||||
|
|
||||||
FrameBufferData(int _sizeX = 100, int _sizeY = 100, int _samples = 4, FrameBufferType type = FrameBufferType::RGBA8)
|
const std::string& getFrameBufferName(uint16_t);
|
||||||
: sizeX(_sizeX), sizeY(_sizeY), samples(_samples), frameBufferType(type) { }
|
uint16_t getFrameBufferId(std::string& name);
|
||||||
};
|
FrameBuffer& getFrameBuffer(uint16_t);
|
||||||
|
|
||||||
template <>
|
|
||||||
class ResourceBuilder<FrameBuffer> {
|
|
||||||
public:
|
|
||||||
using BaseDataType = FrameBufferData;
|
|
||||||
static Scope<FrameBuffer> buildResource(const BaseDataType& baseData);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
void unloadAllFrameBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
33
Deer/Include/DeerRender/GizmoRenderer.h
Executable file
33
Deer/Include/DeerRender/GizmoRenderer.h
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#define GIZMO_DEPTH 8
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct SceneCamera;
|
||||||
|
struct GizmoFace {
|
||||||
|
glm::vec3 positions[4];
|
||||||
|
uint16_t textureID;
|
||||||
|
uint8_t face;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GizmoRenderer {
|
||||||
|
public:
|
||||||
|
void drawLine(glm::vec3 a, glm::vec3 b, glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
void drawVoxelLine(int x, int y, int z, glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
void drawVoxelLineFace(int x, int y, int z, uint8_t face, glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
void drawVoxelFace(int x, int y, int z, uint16_t voxelID, uint8_t face, uint8_t priority = 0);
|
||||||
|
void drawVoxelFaceInverted(int x, int y, int z, uint16_t voxelID, uint8_t face, uint8_t priority = 0);
|
||||||
|
|
||||||
|
void render(const SceneCamera& camera);
|
||||||
|
void refresh();
|
||||||
|
private:
|
||||||
|
std::vector<std::array<glm::vec3, 3>> m_lines;
|
||||||
|
std::array<std::vector<GizmoFace>, GIZMO_DEPTH> m_faces;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Deer/Application.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Log.h"
|
#include "Deer/Log.h"
|
||||||
@ -24,6 +24,8 @@ namespace Deer {
|
|||||||
VertexUV(float _u, float _v) : u(_u), v(_v) {}
|
VertexUV(float _u, float _v) : u(_u), v(_v) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Vertex normal is represented with a number fromn [-64,64], and then its
|
||||||
|
// divided by 64 to know the decimal number
|
||||||
struct VertexNormal {
|
struct VertexNormal {
|
||||||
int8_t x = 0;
|
int8_t x = 0;
|
||||||
int8_t y = 0;
|
int8_t y = 0;
|
||||||
@ -33,15 +35,6 @@ namespace Deer {
|
|||||||
VertexNormal(int8_t _x, int8_t _y, int8_t _z) : x(_x), y(_y), z(_z) {}
|
VertexNormal(int8_t _x, int8_t _y, int8_t _z) : x(_x), y(_y), z(_z) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexColor {
|
|
||||||
uint8_t r = 0;
|
|
||||||
uint8_t g = 0;
|
|
||||||
uint8_t b = 0;
|
|
||||||
|
|
||||||
VertexColor() = default;
|
|
||||||
VertexColor(uint8_t _r, uint8_t _g, uint8_t _b) : r(_r), g(_g), b(_b) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MeshData {
|
struct MeshData {
|
||||||
public:
|
public:
|
||||||
void createVertices(uint32_t count) {
|
void createVertices(uint32_t count) {
|
||||||
@ -49,20 +42,15 @@ namespace Deer {
|
|||||||
vertexNormalData = MakeScope<VertexNormal[]>(count);
|
vertexNormalData = MakeScope<VertexNormal[]>(count);
|
||||||
vertexCount = count;
|
vertexCount = count;
|
||||||
}
|
}
|
||||||
|
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
||||||
void createIndices(uint32_t count) {
|
void createIndices(uint32_t count) {
|
||||||
indexData = MakeScope<uint32_t[]>(count);
|
indexData = MakeScope<uint32_t[]>(count);
|
||||||
indexCount = count;
|
indexCount = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
|
||||||
void createColorData() { vertexColorData = MakeScope<VertexColor[]>(vertexCount); }
|
|
||||||
void createAuxData() { vertexAuxData = MakeScope<uint8_t[]>(vertexCount); }
|
|
||||||
|
|
||||||
inline VertexPosition* getVertexPosition() const { return vertexPositionsData.get(); }
|
inline VertexPosition* getVertexPosition() const { return vertexPositionsData.get(); }
|
||||||
inline VertexNormal* getVertexNormal() const { return vertexNormalData.get(); }
|
inline VertexNormal* getVertexNormal() const { return vertexNormalData.get(); }
|
||||||
inline VertexUV* getVertexUV() const { return vertexUVData.get(); }
|
inline VertexUV* getVertexUV() const { return vertexUVData.get(); }
|
||||||
inline VertexColor* getVertexColor() const { return vertexColorData.get(); }
|
|
||||||
inline uint8_t* getVertexAuxData() const { return vertexAuxData.get(); }
|
|
||||||
inline uint32_t* getIndexData() const { return indexData.get(); }
|
inline uint32_t* getIndexData() const { return indexData.get(); }
|
||||||
|
|
||||||
inline uint32_t getVertexCount() const { return vertexCount; }
|
inline uint32_t getVertexCount() const { return vertexCount; }
|
||||||
@ -73,8 +61,6 @@ namespace Deer {
|
|||||||
Scope<VertexPosition[]> vertexPositionsData;
|
Scope<VertexPosition[]> vertexPositionsData;
|
||||||
Scope<VertexNormal[]> vertexNormalData;
|
Scope<VertexNormal[]> vertexNormalData;
|
||||||
Scope<VertexUV[]> vertexUVData;
|
Scope<VertexUV[]> vertexUVData;
|
||||||
Scope<VertexColor[]> vertexColorData;
|
|
||||||
Scope<uint8_t[]> vertexAuxData;
|
|
||||||
|
|
||||||
uint32_t indexCount = 0;
|
uint32_t indexCount = 0;
|
||||||
Scope<uint32_t[]> indexData;
|
Scope<uint32_t[]> indexData;
|
||||||
@ -91,8 +77,21 @@ namespace Deer {
|
|||||||
static Scope<GPUMesh> buildResource(const BaseDataType& baseData);
|
static Scope<GPUMesh> buildResource(const BaseDataType& baseData);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Builtin {
|
namespace MeshManager {
|
||||||
Resource<GPUMesh> cube();
|
uint16_t loadModel(const Path&);
|
||||||
Resource<GPUMesh> sphere();
|
uint16_t loadModel(const MeshData&, const Path&);
|
||||||
} // namespace Builtin
|
VertexArray& getModel(uint16_t model_id);
|
||||||
|
const Path& getModelName(uint16_t model_id);
|
||||||
|
|
||||||
|
void unloadAllModels();
|
||||||
|
} // namespace MeshManager
|
||||||
|
|
||||||
|
namespace DataStore {
|
||||||
|
void saveModel(const MeshData&, const Path& name);
|
||||||
|
void loadModel(MeshData&, const Path& name);
|
||||||
|
|
||||||
|
void saveBinModel(const MeshData&, const Path& name);
|
||||||
|
|
||||||
|
void createExampleMeshData();
|
||||||
|
} // namespace DataStore
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Log.h"
|
|
||||||
#include "DeerRender/Resource.h"
|
|
||||||
|
|
||||||
#include <initializer_list>
|
#include "Deer/Log.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
enum class TextureBufferType {
|
enum class TextureBufferType {
|
||||||
RGBA8,
|
RGBA8,
|
||||||
RED_INTEGER,
|
RED_INTEGER
|
||||||
GBuffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FrameBufferSpecification {
|
struct FrameBufferSpecification {
|
||||||
@ -41,4 +40,5 @@ namespace Deer {
|
|||||||
|
|
||||||
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
||||||
};
|
};
|
||||||
} // namespace Deer
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
22
Deer/Include/DeerRender/RenderPiperline.h
Normal file
22
Deer/Include/DeerRender/RenderPiperline.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DeerRender/Render/FrameBuffer.h"
|
||||||
|
#include "DeerRender/Tools/Memory.h"
|
||||||
|
#include "DeerRender/Enviroment.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class RenderPiperline {
|
||||||
|
public:
|
||||||
|
RenderPiperline(RenderPiperline&) = delete;
|
||||||
|
RenderPiperline(PiperlineOptions);
|
||||||
|
|
||||||
|
void render(const Environment&);
|
||||||
|
private:
|
||||||
|
Scope<FrameBuffer> resultImage;
|
||||||
|
PiperlineOptions options;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PiperlineOptions {
|
||||||
|
int width = 100;
|
||||||
|
int height = 100;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "DeerRender/DataManagment.h"
|
||||||
#include "DeerRender/Log.h"
|
#include "DeerRender/Log.h"
|
||||||
#include "DeerRender/Tools/Memory.h"
|
#include "DeerRender/Tools/Memory.h"
|
||||||
#include "DeerRender/Tools/Path.h"
|
#include "DeerRender/Tools/Path.h"
|
||||||
@ -11,36 +12,27 @@
|
|||||||
namespace Deer {
|
namespace Deer {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ResourceManager;
|
class ResourceManager;
|
||||||
typedef uint32_t ResourceId;
|
|
||||||
|
|
||||||
ResourceId generatePhyisicalResourceId();
|
|
||||||
ResourceId generateRuntimeResourceId();
|
|
||||||
|
|
||||||
template <typename DataSource>
|
|
||||||
class StorageBackend {
|
|
||||||
public:
|
|
||||||
template <typename T>
|
|
||||||
static Scope<T> load(ResourceId storageId);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Resource {
|
class Resource {
|
||||||
public:
|
public:
|
||||||
int32_t getResourceIndex() const { return resourceId; }
|
int32_t getResourceId() const { return resourceId; }
|
||||||
ResourceId getResourceId() const { return ResourceManager<T>::getResourceId(*this); }
|
|
||||||
|
|
||||||
bool isValid() const { return ResourceManager<T>::isValid(*this); }
|
bool isValid() const { return ResourceManager<T>::isValid(*this); }
|
||||||
T& getData() { return ResourceManager<T>::getResourceData(*this); }
|
T& getData() { return ResourceManager<T>::getResourceData(*this); }
|
||||||
|
|
||||||
|
const std::string& getStorageId() const { return ResourceManager<T>::getStorageId(); }
|
||||||
|
|
||||||
|
inline explicit operator bool() const { return resourceId >= 0; }
|
||||||
|
|
||||||
static Resource<T> unsafeFromId(int32_t id) {
|
static Resource<T> unsafeFromId(int32_t id) {
|
||||||
Resource<T> res;
|
Resource<T> res;
|
||||||
res.resourceId = id;
|
res.resourceId = id;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline explicit operator bool() const { return resourceId >= 0; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// -1 = no resource loaded
|
||||||
int32_t resourceId = -1;
|
int32_t resourceId = -1;
|
||||||
friend ResourceManager<T>;
|
friend ResourceManager<T>;
|
||||||
};
|
};
|
||||||
@ -60,56 +52,41 @@ namespace Deer {
|
|||||||
private:
|
private:
|
||||||
struct ResourceData {
|
struct ResourceData {
|
||||||
public:
|
public:
|
||||||
Scope<T> data = nullptr;
|
ResourceData(const std::string& _resourceId, Scope<T>&& _data)
|
||||||
ResourceId storageId = 0;
|
: storageId(_resourceId), data(std::move(_data)) {}
|
||||||
|
|
||||||
|
Scope<T> data;
|
||||||
|
const std::string storageId;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<ResourceData> resources;
|
static std::vector<ResourceData> resources;
|
||||||
static std::unordered_map<ResourceId, Resource<T>> resourceCache;
|
static std::unordered_map<std::string, Resource<T>> resourceCache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename DataSource>
|
template <typename DataSource>
|
||||||
static Resource<T> loadResource(ResourceId storageId) {
|
static Resource<T> loadResource(const std::string& storageId) {
|
||||||
if (resourceCache.contains(storageId))
|
if (resourceCache.contains(storageId))
|
||||||
return resourceCache[storageId];
|
return resourceCache[storageId];
|
||||||
|
|
||||||
using ResourceBaseType = typename ResourceBuilder<T>::BaseDataType;
|
using ResourceBuilderBaseDataType = typename ResourceBuilder<T>::BaseDataType;
|
||||||
Scope<T> data;
|
Scope<T> data;
|
||||||
|
|
||||||
Scope<ResourceBaseType> baseData = StorageBackend<DataSource>::template load<ResourceBaseType>(storageId);
|
if constexpr (!std::is_void_v<ResourceBuilderBaseDataType>) {
|
||||||
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
Scope<ResourceBuilderBaseDataType> baseData = DataManager<DataSource>::template load<ResourceBuilderBaseDataType>(storageId);
|
||||||
|
if (!baseData) {
|
||||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
const char* baseDataType = abi::__cxa_demangle(typeid(ResourceBuilderBaseDataType).name(), 0, 0, nullptr);
|
||||||
resources.push_back({});
|
const char* dataType = abi::__cxa_demangle(typeid(T).name(), 0, 0, nullptr);
|
||||||
|
DEER_CORE_ERROR("Error loading base resource {} for resource {} with id {}", baseDataType, dataType, storageId.c_str());
|
||||||
ResourceData& rd = resources.back();
|
|
||||||
rd.data = std::move(data);
|
|
||||||
rd.storageId = storageId;
|
|
||||||
|
|
||||||
resourceCache[storageId] = resource;
|
|
||||||
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Resource<T> getResource(ResourceId storageId) {
|
|
||||||
if (resourceCache.contains(storageId))
|
|
||||||
return resourceCache[storageId];
|
|
||||||
|
|
||||||
return Resource<T>();
|
return Resource<T>();
|
||||||
}
|
}
|
||||||
|
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
||||||
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, ResourceId storageId) {
|
} else {
|
||||||
if (resourceCache.contains(storageId))
|
data = ResourceBuilder<T>::buildResource(); // No base data
|
||||||
return resourceCache[storageId];
|
}
|
||||||
|
|
||||||
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
|
||||||
|
|
||||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||||
resources.push_back({});
|
resources.push_back({storageId, std::move(data)});
|
||||||
|
resourceCache[storageId] = resource;
|
||||||
ResourceData& rd = resources.back();
|
|
||||||
rd.data = std::move(data);
|
|
||||||
rd.storageId = storageId;
|
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
@ -123,9 +100,10 @@ namespace Deer {
|
|||||||
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ResourceId getResourceId(Resource<T> res) {
|
static inline const std::string& getStorageId(Resource<T> res) {
|
||||||
|
const static std::string invalid("NULL");
|
||||||
if (!isValid(res))
|
if (!isValid(res))
|
||||||
return 0;
|
return invalid;
|
||||||
|
|
||||||
return resources[res.resourceId].storageId;
|
return resources[res.resourceId].storageId;
|
||||||
}
|
}
|
||||||
@ -138,11 +116,5 @@ namespace Deer {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unordered_map<ResourceId, Resource<T>> ResourceManager<T>::resourceCache;
|
std::unordered_map<std::string, Resource<T>> ResourceManager<T>::resourceCache;
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
|
|
||||||
// BUILTIN RESOURCE IDS
|
|
||||||
|
|
||||||
#define RESOURCE_CUBE_ID 0x1
|
|
||||||
#define RESOURCE_SPHERE_ID 0x2
|
|
||||||
#define RESOURCE_BASIC_SHADER_ID 0x3
|
|
||||||
@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/World.h"
|
#include "Deer/Scene.h"
|
||||||
#include "DeerRender/Components.h"
|
#include "DeerRender/Components.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
struct WorldCamera {
|
struct SceneCamera {
|
||||||
TransformComponent transform;
|
TransformComponent transform;
|
||||||
CameraComponent camera;
|
CameraComponent camera;
|
||||||
|
|
||||||
WorldCamera() {}
|
SceneCamera() {}
|
||||||
WorldCamera(TransformComponent _transform, CameraComponent _camera) : transform(_transform), camera(_camera) {}
|
SceneCamera(TransformComponent _transform, CameraComponent _camera) : transform(_transform), camera(_camera) {}
|
||||||
};
|
};
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Scripting.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
#include "DeerRender/Render/Shader.h"
|
#include "DeerRender/Render/Shader.h"
|
||||||
#include "DeerRender/Resource.h"
|
#include "DeerRender/Resource.h"
|
||||||
|
|
||||||
@ -22,11 +22,6 @@ namespace Deer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace RenderUtils {
|
|
||||||
void initializeRenderUtils();
|
|
||||||
void deinitializeRenderUtils();
|
|
||||||
} // namespace RenderUtils
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class ResourceBuilder<Shader> {
|
class ResourceBuilder<Shader> {
|
||||||
public:
|
public:
|
||||||
@ -37,9 +32,4 @@ namespace Deer {
|
|||||||
namespace DataStore {
|
namespace DataStore {
|
||||||
void loadShader(ShaderData& data, const Path& name);
|
void loadShader(ShaderData& data, const Path& name);
|
||||||
} // namespace DataStore
|
} // namespace DataStore
|
||||||
|
|
||||||
namespace Builtin {
|
|
||||||
Resource<Shader> simpleShader();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Memory.h"
|
#include "Deer/Tools/Memory.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/SmallVector.h"
|
#include "Deer/Tools/SmallVector.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/TypeDefs.h"
|
#include "Deer/Tools/TypeDefs.h"
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Universe.h"
|
|
||||||
94
Deer/Include/DeerRender/Voxel.h
Normal file → Executable file
94
Deer/Include/DeerRender/Voxel.h
Normal file → Executable file
@ -1,81 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Voxel.h"
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
#include "DeerRender/Mesh.h"
|
#define LIGHT_PROPAGATION_COMPLEX_DIRS 18
|
||||||
#include "glm/glm.hpp"
|
#define LIGHT_PROPAGATION_COMPLEX_DIR(id, dir) lightPropagationComplexDir[id + dir * 2]
|
||||||
|
#define LIGHT_PROPAGATION_SIMPLE_FALL 16
|
||||||
|
#define LIGHT_PROPAGATION_COMPLEX_FALL 23
|
||||||
|
|
||||||
#include <array>
|
#define NORMAL_VERTEX_POS(axis, id, normal) normalFacePositions[axis + id * 3 + normal * 3 * 4]
|
||||||
#include <vector>
|
#define VERTEX_UV(axis, id) uvFace[axis + id * 2]
|
||||||
|
#define AMBIENT_OCCLUSION_VERTEX(axis, id, vertex, normal) ambientOcclusionVertex[axis + id * 3 + vertex * 3 * 2 + normal * 3 * 2 * 4]
|
||||||
|
#define LAYER_CHECK_DIRS(axis, id) layerCheckDirections[axis + id * 2]
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
struct VoxelVertex {
|
struct VoxelLight;
|
||||||
VoxelVertex() = default;
|
extern VoxelLight lightVoxel;
|
||||||
VoxelVertex(glm::vec3 _position) : position(_position) {}
|
|
||||||
|
|
||||||
glm::vec3 position;
|
extern int lightPropagationComplexDir[12 * 2];
|
||||||
};
|
extern int normalFacePositions[3 * 4 * 6];
|
||||||
|
extern int uvFace[2 * 4];
|
||||||
|
// 6 Dirs * 4 vertices * 2 checks * 3 dirs
|
||||||
|
extern int ambientOcclusionVertex[6 * 4 * 2 * 3];
|
||||||
|
extern int layerCheckDirections[2 * 8];
|
||||||
|
|
||||||
struct VoxelFaceData {
|
struct VoxelLight {
|
||||||
// Basic construction
|
uint8_t r_light;
|
||||||
std::vector<VoxelVertex> vertices;
|
uint8_t g_light;
|
||||||
std::vector<uint32_t> triangles;
|
uint8_t b_light;
|
||||||
|
uint8_t ambient_light;
|
||||||
|
|
||||||
std::array<std::vector<uint32_t>, 4> connections;
|
VoxelLight(uint8_t _ambient_light = 0) : r_light(0), g_light(0), b_light(0), ambient_light(_ambient_light) {}
|
||||||
std::array<uint32_t, 4> edges;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VoxelBuilder {
|
|
||||||
public:
|
|
||||||
Resource<GPUMesh> buildCluster(int x, int y, int z);
|
|
||||||
|
|
||||||
VoxelBuilder(VoxelEnvironment* env) : environment(env) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct VoxelData {
|
|
||||||
int16_t vertexIndexFace[6] = {-1, -1, -1, -1, -1, -1};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexData {
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec3 tangent;
|
|
||||||
glm::vec2 uv;
|
|
||||||
float AO;
|
|
||||||
float extrussion;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addFace(VoxelFaceData& data, glm::vec3 origin, glm::vec3 up, glm::vec3 right);
|
|
||||||
void calculateNormals();
|
|
||||||
|
|
||||||
void buildVertices();
|
|
||||||
void buildFaceVertices(int x, int y, int z, int face);
|
|
||||||
|
|
||||||
void buildConnections();
|
|
||||||
void buildAxisConnections(int x, int y, int z);
|
|
||||||
void connectVertices(VoxelFaceData& face1, int edgeIndex1, int face1VertexOffset, VoxelFaceData& face2, int edgeIndex2, int face2VertexOffset);
|
|
||||||
|
|
||||||
void buildMarchingCubesCorners();
|
|
||||||
void buildMarchingVoxel(int x, int y, int z, uint8_t marchingCubeId);
|
|
||||||
int getVertexIdCorner(int x, int y, int z, int edge);
|
|
||||||
|
|
||||||
float getAmbientOclusion(int x, int y, int z);
|
|
||||||
|
|
||||||
VoxelData& getVoxelData(int x, int y, int z);
|
|
||||||
void clearVoxelData();
|
|
||||||
|
|
||||||
bool hasBlock(int x, int y, int z);
|
|
||||||
|
|
||||||
std::vector<VertexData> vertices;
|
|
||||||
std::vector<u_int32_t> indices;
|
|
||||||
|
|
||||||
int voxelXOffset;
|
|
||||||
int voxelYOffset;
|
|
||||||
int voxelZOffset;
|
|
||||||
|
|
||||||
VoxelEnvironment* environment;
|
|
||||||
VoxelData voxelData[CLUSTER_SIZE + 2][CLUSTER_SIZE + 2][CLUSTER_SIZE + 2];
|
|
||||||
|
|
||||||
friend VoxelEnvironment;
|
|
||||||
};
|
};
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
54
Deer/Include/DeerRender/VoxelAspect.h
Normal file
54
Deer/Include/DeerRender/VoxelAspect.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* @file VoxelAspect.h
|
||||||
|
* @author chewico@frostdeer.com
|
||||||
|
* @brief File to save the voxel aspect data
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
|
// TEMP
|
||||||
|
#define VOXEL_TEXTURE_SIZE_X 128
|
||||||
|
#define VOXEL_TEXTURE_SIZE_Y 128
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct VoxelTextureFaceDefinition {
|
||||||
|
std::string textureFaces[6];
|
||||||
|
|
||||||
|
inline std::string& operator[](size_t index) {
|
||||||
|
return textureFaces[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelColorEmission {
|
||||||
|
uint8_t r_value = 0;
|
||||||
|
uint8_t g_value = 0;
|
||||||
|
uint8_t b_value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelAspectDefinition {
|
||||||
|
std::string voxelName;
|
||||||
|
VoxelTextureFaceDefinition textureFaces;
|
||||||
|
VoxelColorEmission colorEmission;
|
||||||
|
|
||||||
|
VoxelAspectDefinition() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelAspect {
|
||||||
|
VoxelAspectDefinition definition;
|
||||||
|
uint16_t textureFacesIDs[6]{};
|
||||||
|
|
||||||
|
inline bool isLightSource() {
|
||||||
|
return definition.colorEmission.r_value || definition.colorEmission.g_value || definition.colorEmission.b_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the texture id for the voxel face
|
||||||
|
*
|
||||||
|
* @param face face of the texture defined in the enum NormalDirection of Voxel.h
|
||||||
|
* @return uint16_t texture id in the texture atlas
|
||||||
|
*/
|
||||||
|
inline uint16_t getTextureID(uint8_t face) { return textureFacesIDs[face]; }
|
||||||
|
};
|
||||||
|
}
|
||||||
2
Deer/Include/DeerRender/VoxelWorld.h
Normal file
2
Deer/Include/DeerRender/VoxelWorld.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
#include "DeerRender/Events/Event.h"
|
#include "DeerRender/Events/Event.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -12,7 +12,7 @@ namespace Deer {
|
|||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
|
||||||
WindowProps(const std::string& _title = "Deer Engine",
|
WindowProps(const std::string& _title = "Deer Engine",
|
||||||
unsigned int _width = 900,
|
unsigned int _width = 1280,
|
||||||
unsigned int _height = 720)
|
unsigned int _height = 720)
|
||||||
: title(_title), width(_width), height(_height) {
|
: title(_title), width(_width), height(_height) {
|
||||||
}
|
}
|
||||||
|
|||||||
61
Deer/src/Deer/Core/Application.cpp
Normal file
61
Deer/src/Deer/Core/Application.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "Deer/Application.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Application {
|
||||||
|
// Implemented in DeerRender/Application
|
||||||
|
void runRender(float deltaTime);
|
||||||
|
void resolveEvents();
|
||||||
|
|
||||||
|
Function tickCallback;
|
||||||
|
bool running;
|
||||||
|
|
||||||
|
const double targetUpdateTime = 1.0 / 60.0; // Fixed 60 FPS update
|
||||||
|
double targetRenderTime = 1.0 / 160.0; // User-defined render FPS
|
||||||
|
|
||||||
|
void setTickCallback(Function _tick) {
|
||||||
|
tickCallback = _tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
auto previousTime = std::chrono::high_resolution_clock::now();
|
||||||
|
double accumulatedUpdateTime = 0.0;
|
||||||
|
double accumulatedRenderTime = 0.0;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
// Time handling
|
||||||
|
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||||
|
std::chrono::duration<double> deltaTime = currentTime - previousTime;
|
||||||
|
previousTime = currentTime;
|
||||||
|
|
||||||
|
accumulatedUpdateTime += deltaTime.count();
|
||||||
|
accumulatedRenderTime += deltaTime.count();
|
||||||
|
|
||||||
|
// Fixed Update loop (60 FPS)
|
||||||
|
while (accumulatedUpdateTime >= targetUpdateTime) {
|
||||||
|
Timestep timestep = (float)targetUpdateTime;
|
||||||
|
accumulatedUpdateTime -= targetUpdateTime;
|
||||||
|
|
||||||
|
if (tickCallback)
|
||||||
|
tickCallback();
|
||||||
|
|
||||||
|
}
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
if (accumulatedRenderTime >= targetRenderTime) {
|
||||||
|
runRender((float)targetRenderTime);
|
||||||
|
accumulatedRenderTime -= targetRenderTime;
|
||||||
|
}
|
||||||
|
resolveEvents();
|
||||||
|
#endif
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown() {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Deer/src/Deer/Core/Log.cpp
Executable file
37
Deer/src/Deer/Core/Log.cpp
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#include "Deer/Log.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
std::shared_ptr<spdlog::logger> Log::coreLogger;
|
||||||
|
std::shared_ptr<spdlog::logger> Log::clientLogger;
|
||||||
|
std::shared_ptr<spdlog::logger> Log::scriptLogger;
|
||||||
|
std::shared_ptr<spdlog::logger> Log::EditorEngineLogger;
|
||||||
|
|
||||||
|
void Log::init()
|
||||||
|
{
|
||||||
|
spdlog::set_pattern("%^[%T] %n: %v%$");
|
||||||
|
|
||||||
|
coreLogger = spdlog::stdout_color_mt("Core");
|
||||||
|
clientLogger = spdlog::stdout_color_mt("Client");
|
||||||
|
scriptLogger = spdlog::stdout_color_mt("Script");
|
||||||
|
EditorEngineLogger = spdlog::stdout_color_mt("UI Engine");
|
||||||
|
|
||||||
|
coreLogger->set_level(spdlog::level::level_enum::trace);
|
||||||
|
clientLogger->set_level(spdlog::level::level_enum::trace);
|
||||||
|
scriptLogger->set_level(spdlog::level::level_enum::trace);
|
||||||
|
EditorEngineLogger->set_level(spdlog::level::level_enum::trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::shutdown() {
|
||||||
|
coreLogger.reset();
|
||||||
|
clientLogger.reset();
|
||||||
|
scriptLogger.reset();
|
||||||
|
EditorEngineLogger.reset();
|
||||||
|
|
||||||
|
spdlog::drop_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::coreTrace(const char* msg)
|
||||||
|
{
|
||||||
|
//coreLogger->trace(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
210
Deer/src/Deer/DataStore/DataStore.cpp
Executable file
210
Deer/src/Deer/DataStore/DataStore.cpp
Executable file
@ -0,0 +1,210 @@
|
|||||||
|
#include "Deer/DataStore.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/Tools/Path.h"
|
||||||
|
|
||||||
|
#include "cereal/archives/portable_binary.hpp"
|
||||||
|
#include "cereal/cereal.hpp"
|
||||||
|
#include "cereal/types/unordered_map.hpp"
|
||||||
|
|
||||||
|
#include "Deer/DataStore/DataStructure.h"
|
||||||
|
#include "Deer/DataStore/DataStructureSerialization.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace DataStore {
|
||||||
|
Path rootPath = "./";
|
||||||
|
std::unordered_map<std::string, DirectoryData> dirData_cache;
|
||||||
|
} // namespace DataStore
|
||||||
|
|
||||||
|
const DirectoryData& DataStore::getDirData(const Path& id,
|
||||||
|
const Path& subDir,
|
||||||
|
const char* extension) {
|
||||||
|
std::string dirId = std::string(id) + "&" + std::string(subDir) + "&" +
|
||||||
|
std::string(extension);
|
||||||
|
if (dirData_cache.contains(dirId)) {
|
||||||
|
return dirData_cache[dirId];
|
||||||
|
}
|
||||||
|
|
||||||
|
Path idPath = rootPath / id;
|
||||||
|
|
||||||
|
Path searchPath = idPath / subDir;
|
||||||
|
|
||||||
|
DirectoryData& dirData = dirData_cache[dirId];
|
||||||
|
for (const auto& entry :
|
||||||
|
std::filesystem::directory_iterator(searchPath)) {
|
||||||
|
if (entry.is_directory())
|
||||||
|
dirData.dirs.push_back(entry.path().lexically_relative(idPath));
|
||||||
|
else if (entry.path().extension() == extension) {
|
||||||
|
Path ent = entry.path().lexically_relative(idPath);
|
||||||
|
dirData.elements.push_back(ent.parent_path() / ent.stem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataStore::loadFileData(const Path& id, const Path& name,
|
||||||
|
uint8_t** data, uint32_t* size) {
|
||||||
|
Path filePath = rootPath / id / name;
|
||||||
|
std::ifstream file(filePath, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
*size = (size_t)file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
*data = new uint8_t[*size];
|
||||||
|
|
||||||
|
if (!file.read(reinterpret_cast<char*>(*data), *size)) {
|
||||||
|
DEER_CORE_ERROR("Failed to read file: {0}",
|
||||||
|
filePath.generic_string().c_str());
|
||||||
|
delete[] *data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataStore::loadGlobalFileData(const Path& id, const Path& name,
|
||||||
|
uint8_t** data, uint32_t* size) {
|
||||||
|
Path filePath = rootPath / id;
|
||||||
|
for (auto& f :
|
||||||
|
std::filesystem::recursive_directory_iterator(filePath)) {
|
||||||
|
if (f.path().stem() == name) {
|
||||||
|
std::ifstream file(f.path(), std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
*size = (size_t)file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
*data = new uint8_t[*size];
|
||||||
|
|
||||||
|
if (!file.read(reinterpret_cast<char*>(*data), *size)) {
|
||||||
|
DEER_CORE_ERROR("Failed to read file: {0}",
|
||||||
|
filePath.generic_string().c_str());
|
||||||
|
delete[] *data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEER_CORE_ERROR("File {0} not found", filePath.string().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::freeFileData(uint8_t* data) { delete[] data; }
|
||||||
|
|
||||||
|
void DataStore::deleteFile(const Path& path) {
|
||||||
|
Path filePath = rootPath / toLowerCasePath(path);
|
||||||
|
std::filesystem::remove(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* DataStore::readFile(const Path& path, uint32_t* size) {
|
||||||
|
Path filePath = rootPath / path;
|
||||||
|
std::ifstream file(filePath, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
file.close();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
*size = (size_t)file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
uint8_t* buffer = new uint8_t[*size];
|
||||||
|
|
||||||
|
if (!file.read(reinterpret_cast<char*>(buffer), *size)) {
|
||||||
|
DEER_CORE_ERROR("Failed to read file: {0}",
|
||||||
|
filePath.generic_string().c_str());
|
||||||
|
delete[] buffer;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::saveFile(const Path& path, uint8_t* data, uint32_t size) {
|
||||||
|
Path filePath = rootPath / toLowerCasePath(path);
|
||||||
|
std::filesystem::create_directories(filePath.parent_path());
|
||||||
|
|
||||||
|
std::ofstream file(filePath, std::ios::out | std::ios::binary);
|
||||||
|
|
||||||
|
DEER_CORE_ASSERT(file, "Error when writing file {0}",
|
||||||
|
filePath.generic_string().c_str());
|
||||||
|
|
||||||
|
file.write(reinterpret_cast<const char*>(data), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::compressFiles(std::vector<Path> files, const Path& path) {
|
||||||
|
std::unordered_map<Path, DataStructure> dataStructure;
|
||||||
|
std::vector<uint8_t> combinedData;
|
||||||
|
|
||||||
|
for (const Path& inputPath : files) {
|
||||||
|
uint32_t fileSize = 0;
|
||||||
|
uint8_t* fileData = readFile(inputPath, &fileSize);
|
||||||
|
|
||||||
|
uint32_t start = combinedData.size();
|
||||||
|
|
||||||
|
combinedData.insert(combinedData.end(), fileData,
|
||||||
|
fileData + fileSize);
|
||||||
|
dataStructure[inputPath] = DataStructure{.dataPath = inputPath,
|
||||||
|
.dataStart = start,
|
||||||
|
.dataSize = fileSize};
|
||||||
|
|
||||||
|
delete[] fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path compressedPath = path;
|
||||||
|
compressedPath += ".deer";
|
||||||
|
Path metaPath = path;
|
||||||
|
metaPath += ".deer.meta";
|
||||||
|
|
||||||
|
std::stringstream buffer;
|
||||||
|
{
|
||||||
|
cereal::PortableBinaryOutputArchive archive(buffer);
|
||||||
|
archive(dataStructure);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFile(compressedPath, combinedData.data(), combinedData.size());
|
||||||
|
saveFile(metaPath, (uint8_t*)buffer.str().c_str(), buffer.str().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Path> DataStore::getFiles(const Path& path, const std::string& extension) {
|
||||||
|
std::vector<Path> files;
|
||||||
|
Path lookPath = rootPath / path;
|
||||||
|
|
||||||
|
for (const auto& entry :
|
||||||
|
std::filesystem::recursive_directory_iterator(lookPath)) {
|
||||||
|
if (std::filesystem::is_regular_file(entry) &&
|
||||||
|
entry.path().extension() == extension) {
|
||||||
|
files.push_back(entry.path().lexically_relative(rootPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::createFolder(const Path& path) {
|
||||||
|
std::filesystem::create_directories(path);
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
struct DataStructure {
|
struct DataStructure {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DeerCore/DataStore/DataStructure.h"
|
#include "Deer/DataStore/DataStructure.h"
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
|
|
||||||
#include "cereal/cereal.hpp"
|
#include "cereal/cereal.hpp"
|
||||||
#include "cereal/types/string.hpp"
|
#include "cereal/types/string.hpp"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "DeerCore/Tools/Path.h"
|
#include "Deer/Tools/Path.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
||||||
14
Deer/src/Deer/Scene/Components.cpp
Executable file
14
Deer/src/Deer/Scene/Components.cpp
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#include "Deer/Components.h"
|
||||||
|
#include "glm/gtc/matrix_transform.hpp"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
glm::mat4 TransformComponent::getMatrix() const{
|
||||||
|
glm::mat4 scaleMat = glm::scale(glm::mat4(1.0f), scale);
|
||||||
|
glm::mat4 roatationMat = glm::mat4(rotation);
|
||||||
|
glm::mat4 positionMat = glm::translate(glm::mat4(1.0f), position);
|
||||||
|
|
||||||
|
return positionMat * roatationMat * scaleMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
#include "DeerCore/Components.h"
|
#include "Deer/Components.h"
|
||||||
#include "DeerCore/EntityEnviroment.h"
|
#include "Deer/Enviroment.h"
|
||||||
#include "DeerCore/Log.h"
|
#include "Deer/Log.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
Entity::Entity(entt::entity handle, EntityEnvironment* scene, uint32_t entityID)
|
Entity::Entity(entt::entity handle, Environment* scene, uint16_t entityID)
|
||||||
: entHandle(handle),
|
: entHandle(handle),
|
||||||
environment(scene),
|
environment(scene),
|
||||||
entId(entityID) {}
|
entId(entityID) {}
|
||||||
@ -63,37 +63,6 @@ namespace Deer {
|
|||||||
parentId = parent.getId();
|
parentId = parent.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityNetworkBehaviour Entity::getForcedNetworkBehaviour() {
|
|
||||||
if (entId == 0)
|
|
||||||
return EntityNetworkBehaviour::PARENT;
|
|
||||||
|
|
||||||
TagComponent& tag = getComponent<TagComponent>();
|
|
||||||
|
|
||||||
if (tag.networkBehaviour == EntityNetworkBehaviour::CLIENT)
|
|
||||||
return EntityNetworkBehaviour::CLIENT;
|
|
||||||
else if (tag.networkBehaviour == EntityNetworkBehaviour::SERVER)
|
|
||||||
return EntityNetworkBehaviour::SERVER;
|
|
||||||
|
|
||||||
return getParent().getForcedNetworkBehaviour();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Entity::isValidNetworkBehaviour(EntityNetworkBehaviour networkBehaviour) {
|
|
||||||
if (entId == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
TagComponent& tag = getComponent<TagComponent>();
|
|
||||||
if (tag.networkBehaviour == EntityNetworkBehaviour::PARENT)
|
|
||||||
return getParent().isValidNetworkBehaviour(networkBehaviour);
|
|
||||||
|
|
||||||
if (tag.networkBehaviour == networkBehaviour)
|
|
||||||
return getParent().isValidNetworkBehaviour(networkBehaviour);
|
|
||||||
|
|
||||||
if (networkBehaviour == EntityNetworkBehaviour::PARENT)
|
|
||||||
return getParent().isValidNetworkBehaviour(tag.networkBehaviour);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Entity::isDescendantOf(Entity& parent) const {
|
bool Entity::isDescendantOf(Entity& parent) const {
|
||||||
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
|
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
|
||||||
if (getId() == parent.getId())
|
if (getId() == parent.getId())
|
||||||
@ -1,19 +1,21 @@
|
|||||||
#include "DeerCore/EntityEnviroment.h"
|
#include "Deer/Enviroment.h"
|
||||||
|
|
||||||
#include "DeerCore/Components.h"
|
#include "Deer/Application.h"
|
||||||
#include "DeerCore/Log.h"
|
#include "Deer/Components.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
#include "DeerRender/Render/Render.h"
|
#include "DeerRender/Render/Render.h"
|
||||||
|
#include "DeerRender/Render/RenderUtils.h"
|
||||||
#include "DeerRender/Render/Texture.h"
|
#include "DeerRender/Render/Texture.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
EntityEnvironment::EntityEnvironment() {
|
Environment::Environment() {
|
||||||
m_registry = MakeScope<entt::registry>();
|
m_registry = MakeScope<entt::registry>();
|
||||||
createEntityWithId(0, "root");
|
createEntityWithId(0, "root");
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityEnvironment::~EntityEnvironment() {}
|
Environment::~Environment() {}
|
||||||
|
|
||||||
void EntityEnvironment::clear() {
|
void Environment::clear() {
|
||||||
// Clear all existing entities and map
|
// Clear all existing entities and map
|
||||||
m_registry->clear();
|
m_registry->clear();
|
||||||
|
|
||||||
@ -25,23 +27,23 @@ namespace Deer {
|
|||||||
createEntityWithId(0, "root");
|
createEntityWithId(0, "root");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EntityEnvironment::getEntityCount() const {
|
uint16_t Environment::getEntityCount() const {
|
||||||
return entities.size() - unused_entities_spaces.size();
|
return entities.size() - unused_entities_spaces.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity& EntityEnvironment::getEntity(uint32_t id) {
|
Entity& Environment::getEntity(uint16_t id) {
|
||||||
DEER_CORE_ASSERT(entityExists(id), "Entity id {0} does not exist", id);
|
DEER_CORE_ASSERT(entityExists(id), "Entity id {0} does not exist", id);
|
||||||
return entities[id];
|
return entities[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityEnvironment::entityExists(uint32_t id) const {
|
bool Environment::entityExists(uint16_t id) const {
|
||||||
if (id >= entities.size())
|
if (id >= entities.size())
|
||||||
return false;
|
return false;
|
||||||
const Entity& refEntity = entities[id];
|
const Entity& refEntity = entities[id];
|
||||||
return refEntity.isValid();
|
return refEntity.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity& EntityEnvironment::createEntity(const std::string& name) {
|
Entity& Environment::createEntity(const std::string& name) {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
|
|
||||||
entt::entity entityID = m_registry->create();
|
entt::entity entityID = m_registry->create();
|
||||||
@ -66,7 +68,7 @@ namespace Deer {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity& EntityEnvironment::createEntityWithId(uint32_t id, const std::string& name) {
|
Entity& Environment::createEntityWithId(uint16_t id, const std::string& name) {
|
||||||
entt::entity entityID = m_registry->create();
|
entt::entity entityID = m_registry->create();
|
||||||
|
|
||||||
// We allocate all the memory until that id
|
// We allocate all the memory until that id
|
||||||
@ -81,7 +83,7 @@ namespace Deer {
|
|||||||
|
|
||||||
entities.push_back({});
|
entities.push_back({});
|
||||||
} else {
|
} else {
|
||||||
static std::stack<uint32_t> unused_entities_spaces_cache;
|
static std::stack<uint16_t> unused_entities_spaces_cache;
|
||||||
|
|
||||||
// This code its to remove a specific element from a stack
|
// This code its to remove a specific element from a stack
|
||||||
// We pop the stack until we find the id or we empty it to
|
// We pop the stack until we find the id or we empty it to
|
||||||
@ -117,7 +119,7 @@ namespace Deer {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityEnvironment::destroyEntity(uint32_t entityID) {
|
void Environment::destroyEntity(uint16_t entityID) {
|
||||||
DEER_CORE_ASSERT(entityExists(entityID), "Entity id {0} does not exist", entityID);
|
DEER_CORE_ASSERT(entityExists(entityID), "Entity id {0} does not exist", entityID);
|
||||||
DEER_CORE_ASSERT(entityID != 0, "Cannot destroy root");
|
DEER_CORE_ASSERT(entityID != 0, "Cannot destroy root");
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ namespace Deer {
|
|||||||
RelationshipComponent& relationship = entity.getComponent<RelationshipComponent>();
|
RelationshipComponent& relationship = entity.getComponent<RelationshipComponent>();
|
||||||
// We want to delete all childrens
|
// We want to delete all childrens
|
||||||
for (int i = 0; i < relationship.getChildCount(); i++) {
|
for (int i = 0; i < relationship.getChildCount(); i++) {
|
||||||
uint32_t childID = relationship.getChildId(i);
|
uint16_t childID = relationship.getChildId(i);
|
||||||
destroyEntity(childID);
|
destroyEntity(childID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +142,9 @@ namespace Deer {
|
|||||||
unused_entities_spaces.push(entityID);
|
unused_entities_spaces.push(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t EntityEnvironment::tryGetMainCamera() const { return m_mainCamera; }
|
uint16_t Environment::tryGetMainCamera() const { return m_mainCamera; }
|
||||||
|
|
||||||
void EntityEnvironment::setMainCamera(Entity& entity) {
|
void Environment::setMainCamera(Entity& entity) {
|
||||||
if (!entity.isValid())
|
if (!entity.isValid())
|
||||||
m_mainCamera = 0;
|
m_mainCamera = 0;
|
||||||
|
|
||||||
51
Deer/src/Deer/Scene/Scene.cpp
Executable file
51
Deer/src/Deer/Scene/Scene.cpp
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#include "Deer/Scene.h"
|
||||||
|
|
||||||
|
#include "Deer/Components.h"
|
||||||
|
#include "Deer/Enviroment.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
|
#include "Deer/Voxels/Chunk.h"
|
||||||
|
#include "Deer/Voxels/Layer.h"
|
||||||
|
#include "Deer/Voxels/VoxelWorldData.h"
|
||||||
|
|
||||||
|
#include "Deer/Enviroment.h"
|
||||||
|
#include "Deer/Scene/SceneData.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/FrameBuffer.h"
|
||||||
|
#include "DeerRender/Mesh.h"
|
||||||
|
#include "DeerRender/Shader.h"
|
||||||
|
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
void Scene::clear() {
|
||||||
|
environment.clear();
|
||||||
|
VoxelWorld::clear();
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
ResourceManager<Shader>::unloadResources();
|
||||||
|
ResourceManager<GPUMesh>::unloadResources();
|
||||||
|
FrameBufferManager::unloadAllFrameBuffer();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scene::getExecutingState() {
|
||||||
|
return isExecuting;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::initExecution() {
|
||||||
|
DEER_CORE_ASSERT(!isExecuting, "Deer scene is already executing");
|
||||||
|
isExecuting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::tickExecution() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::endExecution() {
|
||||||
|
DEER_CORE_ASSERT(isExecuting, "Deer scene is not executing");
|
||||||
|
isExecuting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
18
Deer/src/Deer/Scene/SceneData.cpp
Normal file
18
Deer/src/Deer/Scene/SceneData.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "Deer/Enviroment.h"
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/GizmoRenderer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Scene {
|
||||||
|
Environment environment;
|
||||||
|
bool isExecuting = false;
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
GizmoRenderer gizmoRenderer;
|
||||||
|
#endif
|
||||||
|
} // namespace Scene
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
20
Deer/src/Deer/Scene/SceneData.h
Normal file
20
Deer/src/Deer/Scene/SceneData.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/GizmoRenderer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Environment;
|
||||||
|
|
||||||
|
namespace Scene {
|
||||||
|
extern Environment environment;
|
||||||
|
extern bool isExecuting;
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
extern GizmoRenderer gizmoRenderer;
|
||||||
|
#endif
|
||||||
|
} // namespace Scene
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Components.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
// RELATIONSHIP COMPONENT
|
||||||
|
template <class Archive>
|
||||||
|
void serialize(Archive& archive, RelationshipComponent& relationship) {
|
||||||
|
archive(cereal::make_nvp("parentId", relationship.parent_id));
|
||||||
|
|
||||||
|
archive(cereal::make_size_tag(
|
||||||
|
static_cast<cereal::size_type>(relationship.getChildCount())));
|
||||||
|
for (int i = 0; i < relationship.getChildCount(); i++)
|
||||||
|
archive(relationship.getChildId(i));
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Components.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
|
||||||
|
// TRANSFORM COMPONENT
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& archive,
|
||||||
|
TransformComponent& transform) {
|
||||||
|
|
||||||
|
archive(cereal::make_nvp("position", transform.position));
|
||||||
|
archive(cereal::make_nvp("scale", transform.scale));
|
||||||
|
archive(cereal::make_nvp("rotation", transform.rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
72
Deer/src/Deer/Scene/Serialization/EntitySerialization.h
Executable file
72
Deer/src/Deer/Scene/Serialization/EntitySerialization.h
Executable file
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Deer/Components.h"
|
||||||
|
#include "Deer/Enviroment.h"
|
||||||
|
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
||||||
|
#include "EntitySerializationStruct.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
template <class Archive, typename T>
|
||||||
|
void saveComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
|
||||||
|
bool hasComponent = m_entity.hasComponent<T>();
|
||||||
|
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
|
||||||
|
if (hasComponent) {
|
||||||
|
const T& component = m_entity.getComponent<T>();
|
||||||
|
archive(cereal::make_nvp(componentName.c_str(), component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive, typename T>
|
||||||
|
void loadComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
|
||||||
|
bool hasComponent;
|
||||||
|
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
|
||||||
|
if (hasComponent) {
|
||||||
|
T& component = m_entity.addComponent<T>();
|
||||||
|
archive(cereal::make_nvp(componentName.c_str(), component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ENTITY
|
||||||
|
template <class Archive>
|
||||||
|
void save(Archive& archive, EntitySerializationStruct const& m_entity) {
|
||||||
|
const Entity& entity = m_entity.env->getEntity(m_entity.entityID);
|
||||||
|
|
||||||
|
const TagComponent& name = entity.getComponent<TagComponent>();
|
||||||
|
archive(cereal::make_nvp("id", m_entity.entityID));
|
||||||
|
archive(cereal::make_nvp("name", name.tag));
|
||||||
|
|
||||||
|
const TransformComponent& transform = entity.getComponent<TransformComponent>();
|
||||||
|
archive(cereal::make_nvp("transform", transform));
|
||||||
|
|
||||||
|
const RelationshipComponent& relation = entity.getComponent<RelationshipComponent>();
|
||||||
|
archive(cereal::make_nvp("relationship", relation));
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
if (!is_server_serialization) {
|
||||||
|
saveComponent<Archive, MeshComponent>(archive, "meshRenderComponent", entity);
|
||||||
|
saveComponent<Archive, CameraComponent>(archive, "cameraComponent", entity);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void load(Archive& archive, EntitySerializationStruct& m_entity) {
|
||||||
|
uint16_t id;
|
||||||
|
std::string name;
|
||||||
|
archive(cereal::make_nvp("id", id));
|
||||||
|
archive(cereal::make_nvp("name", name));
|
||||||
|
|
||||||
|
Entity& entity = m_entity.env->createEntityWithId(id);
|
||||||
|
archive(cereal::make_nvp("transform", entity.getComponent<TransformComponent>()));
|
||||||
|
|
||||||
|
RelationshipComponent& rc = entity.getComponent<RelationshipComponent>();
|
||||||
|
archive(cereal::make_nvp("relationship", rc));
|
||||||
|
entity.setParent(m_entity.env->getEntity(rc.parent_id));
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
if (!is_server_serialization) {
|
||||||
|
loadComponent<Archive, MeshComponent>(archive, "meshRenderComponent", entity);
|
||||||
|
loadComponent<Archive, CameraComponent>(archive, "cameraComponent", entity);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Environment;
|
||||||
|
struct EntitySerializationStruct {
|
||||||
|
uint16_t entityID;
|
||||||
|
Environment* env;
|
||||||
|
};
|
||||||
|
} // namespace Deer
|
||||||
57
Deer/src/Deer/Scene/Serialization/EnvironmentSerialization.h
Executable file
57
Deer/src/Deer/Scene/Serialization/EnvironmentSerialization.h
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Deer/Enviroment.h"
|
||||||
|
#include "EntitySerializationStruct.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct EnvironmentEntity {
|
||||||
|
Environment& environment;
|
||||||
|
EnvironmentEntity(Environment& env) : environment(env) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void save(Archive& archive, const Deer::Environment& environment) {
|
||||||
|
EnvironmentEntity envEnt(const_cast<Deer::Environment&>(environment));
|
||||||
|
archive(cereal::make_nvp("entities", envEnt));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void load(Archive& archive, Deer::Environment& environment) {
|
||||||
|
EnvironmentEntity envEnt(environment);
|
||||||
|
archive(cereal::make_nvp("entities", envEnt));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void save(Archive& archive, EnvironmentEntity const& m_entities) {
|
||||||
|
archive(cereal::make_size_tag(static_cast<cereal::size_type>(
|
||||||
|
m_entities.environment.getEntityCount())));
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < m_entities.environment.getEntityCount(); i++) {
|
||||||
|
while (!m_entities.environment.entityExists(i)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntitySerializationStruct serializationStruct;
|
||||||
|
serializationStruct.env =
|
||||||
|
const_cast<Environment*>(&m_entities.environment);
|
||||||
|
serializationStruct.entityID = i;
|
||||||
|
|
||||||
|
archive(serializationStruct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void load(Archive& archive, EnvironmentEntity& m_entities) {
|
||||||
|
cereal::size_type size;
|
||||||
|
archive(cereal::make_size_tag(size));
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
EntitySerializationStruct serializationStruct;
|
||||||
|
serializationStruct.env = &m_entities.environment;
|
||||||
|
|
||||||
|
archive(serializationStruct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
4
Deer/src/Deer/Scene/Serialization/Serialization.cpp
Executable file
4
Deer/src/Deer/Scene/Serialization/Serialization.cpp
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
bool is_server_serialization = false;
|
||||||
|
}
|
||||||
27
Deer/src/Deer/Scene/Serialization/Serialization.h
Executable file
27
Deer/src/Deer/Scene/Serialization/Serialization.h
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cereal/cereal.hpp"
|
||||||
|
#include "cereal/types/string.hpp"
|
||||||
|
#include "cereal/types/vector.hpp"
|
||||||
|
|
||||||
|
// Serialization Vars
|
||||||
|
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
||||||
|
|
||||||
|
// GENERICS
|
||||||
|
#include "Deer/Scene/Serialization/QuatSerialization.h"
|
||||||
|
#include "Deer/Scene/Serialization/Vec3Serialization.h"
|
||||||
|
|
||||||
|
// SCENE SPECIFIC
|
||||||
|
#include "Deer/Scene/Serialization/EntitySerialization.h"
|
||||||
|
#include "Deer/Scene/Serialization/EnvironmentSerialization.h"
|
||||||
|
|
||||||
|
// COMPONENTS SPECIFIC
|
||||||
|
#include "Deer/Scene/Serialization/Components/RelationshipComponentSerialization.h"
|
||||||
|
#include "Deer/Scene/Serialization/Components/TransformComponentSerialization.h"
|
||||||
|
|
||||||
|
// RENDER SPECIFIC
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Scene/Serialization/Components/CameraSerializationComponent.h"
|
||||||
|
#include "DeerRender/Scene/Serialization/Components/MeshRenderComponentSerialization.h"
|
||||||
|
#include "DeerRender/Scene/Serialization/Components/TextureBindingSerializationComponent.h"
|
||||||
|
#endif
|
||||||
7
Deer/src/Deer/Scene/Serialization/SerializationGlobalVars.cpp
Executable file
7
Deer/src/Deer/Scene/Serialization/SerializationGlobalVars.cpp
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#include "SerializationGlobalVars.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
|
||||||
|
bool is_server_serialization = false;
|
||||||
|
|
||||||
|
}
|
||||||
5
Deer/src/Deer/Scene/Serialization/SerializationGlobalVars.h
Executable file
5
Deer/src/Deer/Scene/Serialization/SerializationGlobalVars.h
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
extern bool is_server_serialization;
|
||||||
|
}
|
||||||
21
Deer/src/Deer/Voxels/Chunk.cpp
Executable file
21
Deer/src/Deer/Voxels/Chunk.cpp
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#include "Chunk.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
Chunk::~Chunk() {
|
||||||
|
if (m_voxels) {
|
||||||
|
delete[] m_voxels;
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
delete[] m_lightInfo;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::loadVoxels() {
|
||||||
|
if (!m_voxels) {
|
||||||
|
m_voxels = new Voxel[CHUNK_VOXELS]();
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
m_lightInfo = new VoxelLight[CHUNK_VOXELS]();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
143
Deer/src/Deer/Voxels/Chunk.h
Executable file
143
Deer/src/Deer/Voxels/Chunk.h
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "DeerRender/Voxel.h"
|
||||||
|
#include "DeerRender/VoxelAspect.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Chunk {
|
||||||
|
public:
|
||||||
|
Chunk() = default;
|
||||||
|
~Chunk();
|
||||||
|
|
||||||
|
inline Voxel readVoxel(ChunkVoxelID id) {
|
||||||
|
if (m_voxels)
|
||||||
|
return m_voxels[VOXEL_POSITION(id)];
|
||||||
|
return emptyVoxel;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Voxel& modVoxel(ChunkVoxelID id) {
|
||||||
|
if (!m_voxels)
|
||||||
|
loadVoxels();
|
||||||
|
return m_voxels[VOXEL_POSITION(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fillVoxels(ChunkVoxelID min, ChunkVoxelID max, Voxel info) {
|
||||||
|
if (!m_voxels)
|
||||||
|
loadVoxels();
|
||||||
|
|
||||||
|
ChunkVoxelID voxelID;
|
||||||
|
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
||||||
|
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
||||||
|
for (voxelID.z = min.z; voxelID.z <= max.x; voxelID.z++) {
|
||||||
|
m_voxels[VOXEL_POSITION(voxelID)] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void remplaceVoxels(ChunkVoxelID min, ChunkVoxelID max,
|
||||||
|
Voxel ref, Voxel value) {
|
||||||
|
if (!m_voxels)
|
||||||
|
loadVoxels();
|
||||||
|
|
||||||
|
ChunkVoxelID voxelID;
|
||||||
|
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
||||||
|
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
||||||
|
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
||||||
|
Voxel& currentVoxel = m_voxels[VOXEL_POSITION(voxelID)];
|
||||||
|
|
||||||
|
if (currentVoxel.id == ref.id)
|
||||||
|
currentVoxel = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t calculateLayerVoxelHeight(LayerVoxelID layerVoxelID) {
|
||||||
|
if (!m_voxels)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ChunkVoxelID voxelID(layerVoxelID.x, CHUNK_SIZE_Y - 1,
|
||||||
|
layerVoxelID.z);
|
||||||
|
for (int y = CHUNK_SIZE_Y - 1; y >= 0; y--) {
|
||||||
|
voxelID.y = y;
|
||||||
|
|
||||||
|
if (m_voxels[VOXEL_POSITION(voxelID)].id != 0)
|
||||||
|
return voxelID.y + 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Voxel* m_voxels = nullptr;
|
||||||
|
|
||||||
|
void loadVoxels();
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
public:
|
||||||
|
inline VoxelLight readLight(ChunkVoxelID id) {
|
||||||
|
if (m_voxels)
|
||||||
|
return m_lightInfo[VOXEL_POSITION(id)];
|
||||||
|
return VoxelLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VoxelLight& modLight(ChunkVoxelID id) {
|
||||||
|
if (!m_voxels)
|
||||||
|
loadVoxels();
|
||||||
|
return m_lightInfo[VOXEL_POSITION(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void clearVoxelLight(ChunkVoxelID min, ChunkVoxelID max) {
|
||||||
|
ChunkVoxelID voxelID;
|
||||||
|
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
||||||
|
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
||||||
|
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].b_light = 0;
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].r_light = 0;
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].g_light = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is the same as clear Voxel Light but it also checks if
|
||||||
|
// there is a source of light
|
||||||
|
inline void clearVoxelLightAndSaveSources(
|
||||||
|
ChunkVoxelID min, ChunkVoxelID max, ChunkID chunkID,
|
||||||
|
std::vector<VoxelCordinates>& sources) {
|
||||||
|
if (!m_voxels)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChunkVoxelID voxelID;
|
||||||
|
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
||||||
|
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
||||||
|
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
||||||
|
Voxel voxel = m_voxels[VOXEL_POSITION(voxelID)];
|
||||||
|
VoxelAspect& voxelAspect =
|
||||||
|
DataStore::voxelsAspect[voxel.id];
|
||||||
|
if (voxelAspect.isLightSource()) {
|
||||||
|
sources.push_back(VoxelCordinates(
|
||||||
|
voxelID.x + chunkID.x * CHUNK_SIZE_X,
|
||||||
|
voxelID.y + chunkID.y * CHUNK_SIZE_Y,
|
||||||
|
voxelID.z + chunkID.z * CHUNK_SIZE_Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].b_light = 0;
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].r_light = 0;
|
||||||
|
m_lightInfo[VOXEL_POSITION(voxelID)].g_light = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VoxelLight* m_lightInfo = nullptr;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
} // namespace Deer
|
||||||
12
Deer/src/Deer/Voxels/Layer.cpp
Executable file
12
Deer/src/Deer/Voxels/Layer.cpp
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
Layer::~Layer() {
|
||||||
|
if (m_layerInfo)
|
||||||
|
delete[] m_layerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::loadData() {
|
||||||
|
m_layerInfo = new LayerVoxel[LAYER_VOXELS]();
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Deer/src/Deer/Voxels/Layer.h
Executable file
40
Deer/src/Deer/Voxels/Layer.h
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
class Layer {
|
||||||
|
public:
|
||||||
|
Layer() = default;
|
||||||
|
~Layer();
|
||||||
|
|
||||||
|
inline LayerVoxel readLayerVoxel(LayerVoxelID id) {
|
||||||
|
if (!m_layerInfo)
|
||||||
|
return LayerVoxel();
|
||||||
|
return m_layerInfo[LAYER_VOXEL_POSITION(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LayerVoxel& modLayerVoxel(LayerVoxelID id) {
|
||||||
|
if (!m_layerInfo)
|
||||||
|
loadData();
|
||||||
|
return m_layerInfo[LAYER_VOXEL_POSITION(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fillVoxelLayerMaxHeight(LayerVoxelID min, LayerVoxelID max, uint8_t maxHeight) {
|
||||||
|
if (!m_layerInfo)
|
||||||
|
loadData();
|
||||||
|
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
for (layerVoxelID.x = min.x; layerVoxelID.x <= max.x; layerVoxelID.x++) {
|
||||||
|
for (layerVoxelID.z = min.x; layerVoxelID.z <= max.z; layerVoxelID.z++) {
|
||||||
|
int id = LAYER_VOXEL_POSITION(layerVoxelID);
|
||||||
|
if (m_layerInfo[id].height <= maxHeight)
|
||||||
|
m_layerInfo[id].height = maxHeight + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void loadData();
|
||||||
|
|
||||||
|
LayerVoxel* m_layerInfo = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
56
Deer/src/Deer/Voxels/Serialization/VoxelInfoSerialization.h
Normal file
56
Deer/src/Deer/Voxels/Serialization/VoxelInfoSerialization.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
|
||||||
|
#include "cereal/cereal.hpp"
|
||||||
|
#include "cereal/types/string.hpp"
|
||||||
|
|
||||||
|
namespace Deer{
|
||||||
|
template<class Archive>
|
||||||
|
void save(Archive & archive, VoxelInfo const & block) {
|
||||||
|
archive(cereal::make_nvp("name", block.name));
|
||||||
|
|
||||||
|
// To avoid breaking things we set it up to Air
|
||||||
|
const char* blockTypeChar = VOXEL_INFO_TYPE_AIR;
|
||||||
|
switch (block.type)
|
||||||
|
{
|
||||||
|
case VoxelInfoType::Air :
|
||||||
|
blockTypeChar = VOXEL_INFO_TYPE_AIR;
|
||||||
|
break;
|
||||||
|
case VoxelInfoType::Voxel :
|
||||||
|
blockTypeChar = VOXEL_INFO_TYPE_VOXEL;
|
||||||
|
break;
|
||||||
|
case VoxelInfoType::TransparentVoxel :
|
||||||
|
blockTypeChar = VOXEL_INFO_TYPE_TRANSPARENT_VOXEL;
|
||||||
|
break;
|
||||||
|
case VoxelInfoType::Custom :
|
||||||
|
blockTypeChar = VOXEL_INFO_TYPE_CUSTOM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string blockTypeString(blockTypeChar);
|
||||||
|
archive(cereal::make_nvp("type", blockTypeString));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void load(Archive & archive, VoxelInfo & block) {archive(cereal::make_nvp("name", block.name));
|
||||||
|
std::string blockTypeString;
|
||||||
|
|
||||||
|
archive(cereal::make_nvp("name", block.name));
|
||||||
|
archive(cereal::make_nvp("type", blockTypeString));
|
||||||
|
|
||||||
|
if (blockTypeString == VOXEL_INFO_TYPE_AIR)
|
||||||
|
block.type = VoxelInfoType::Air;
|
||||||
|
else if (blockTypeString == VOXEL_INFO_TYPE_VOXEL)
|
||||||
|
block.type = VoxelInfoType::Voxel;
|
||||||
|
else if (blockTypeString == VOXEL_INFO_TYPE_TRANSPARENT_VOXEL)
|
||||||
|
block.type = VoxelInfoType::TransparentVoxel;
|
||||||
|
else if (blockTypeString == VOXEL_INFO_TYPE_CUSTOM)
|
||||||
|
block.type = VoxelInfoType::Custom;
|
||||||
|
else {
|
||||||
|
block.type = VoxelInfoType::Air;
|
||||||
|
DEER_CORE_ERROR("Failed to resolve voxel type for {0}, unknown type : {1}",
|
||||||
|
block.name.c_str(), blockTypeString.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Deer/src/Deer/Voxels/Voxel.cpp
Executable file
19
Deer/src/Deer/Voxels/Voxel.cpp
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#include "Deer/Voxel.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
// This means the voxel is null
|
||||||
|
Voxel nullVoxel(65535);
|
||||||
|
Voxel emptyVoxel;
|
||||||
|
|
||||||
|
LayerVoxel nullLayerVoxel(65535);
|
||||||
|
|
||||||
|
int normalDirs[3 * 6] = {
|
||||||
|
-1, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, -1,
|
||||||
|
0, 0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
89
Deer/src/Deer/Voxels/VoxelData.cpp
Normal file
89
Deer/src/Deer/Voxels/VoxelData.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Deer/DataStore.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/Voxel.h"
|
||||||
|
#include "Deer/Voxels/Serialization/VoxelInfoSerialization.h"
|
||||||
|
#include "cereal/archives/json.hpp"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace DataStore {
|
||||||
|
std::vector<VoxelInfo> voxelsInfo;
|
||||||
|
std::unordered_map<std::string, uint32_t> blockIDMap;
|
||||||
|
} // namespace DataStore
|
||||||
|
|
||||||
|
int32_t DataStore::getVoxelID(const std::string& name) {
|
||||||
|
if (blockIDMap.contains(name))
|
||||||
|
return blockIDMap[name];
|
||||||
|
DEER_CORE_WARN("Voxel Info {0} Not Found!", name.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::loadVoxelsData() {
|
||||||
|
voxelsInfo.clear();
|
||||||
|
blockIDMap.clear();
|
||||||
|
|
||||||
|
VoxelInfo airVoxelInfo;
|
||||||
|
airVoxelInfo.name = VOXEL_INFO_TYPE_AIR;
|
||||||
|
|
||||||
|
voxelsInfo.push_back(airVoxelInfo);
|
||||||
|
blockIDMap[VOXEL_INFO_TYPE_AIR] = 0;
|
||||||
|
|
||||||
|
std::vector<Path> voxelsData;
|
||||||
|
voxelsData = DataStore::getFiles(DEER_VOXEL_DATA_PATH, ".voxel");
|
||||||
|
|
||||||
|
DEER_CORE_TRACE("Loading voxels");
|
||||||
|
for (Path& voxel : voxelsData) {
|
||||||
|
VoxelInfo voxelData;
|
||||||
|
|
||||||
|
uint32_t dataSize;
|
||||||
|
uint8_t* data = DataStore::readFile(voxel, &dataSize);
|
||||||
|
|
||||||
|
std::string dataString((char*)data, dataSize);
|
||||||
|
std::istringstream dataInputStream(dataString);
|
||||||
|
{
|
||||||
|
cereal::JSONInputArchive archive(dataInputStream);
|
||||||
|
archive(cereal::make_nvp("voxel", voxelData));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (voxelData.name.empty()) {
|
||||||
|
DEER_CORE_ERROR("{0} has an empty name",
|
||||||
|
voxel.generic_string().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockIDMap.contains(voxelData.name)) {
|
||||||
|
DEER_CORE_ERROR("{0} with name {1} has dupplicated name id",
|
||||||
|
voxel.generic_string().c_str(),
|
||||||
|
voxelData.name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// DEER_CORE_TRACE(" {0} - {1}",
|
||||||
|
// voxel.filename().generic_string().c_str(),
|
||||||
|
// voxelData.name);
|
||||||
|
|
||||||
|
uint32_t id = voxelsInfo.size();
|
||||||
|
|
||||||
|
voxelsInfo.push_back(voxelData);
|
||||||
|
blockIDMap[voxelData.name] = id;
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::createExampleVoxelData() {
|
||||||
|
VoxelInfo block;
|
||||||
|
|
||||||
|
std::stringstream data;
|
||||||
|
{
|
||||||
|
cereal::JSONOutputArchive archive(data);
|
||||||
|
archive(cereal::make_nvp("voxel", block));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataStore::saveFile(Path(DEER_VOXEL_PATH) / "voxel.example",
|
||||||
|
(uint8_t*)(data.str().c_str()), data.str().size());
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
68
Deer/src/Deer/Voxels/VoxelWorld.cpp
Executable file
68
Deer/src/Deer/Voxels/VoxelWorld.cpp
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
|
#include "Deer/Voxels/VoxelWorldData.h"
|
||||||
|
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/Voxels/Chunk.h"
|
||||||
|
#include "Deer/Voxels/Layer.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
void VoxelWorld::initialize(const VoxelWorldProps& props) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
worldProps = props;
|
||||||
|
|
||||||
|
chunks = MakeScope<Chunk[]>(worldProps.getChunkCount());
|
||||||
|
layers = MakeScope<Layer[]>(worldProps.getLayerCount());
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
initializeRenderVars(props);
|
||||||
|
#endif
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelWorld::clear() {
|
||||||
|
chunks.reset();
|
||||||
|
layers.reset();
|
||||||
|
|
||||||
|
initialized = false;
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
clearRenderVars();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const VoxelWorldProps& VoxelWorld::getWorldProps() {
|
||||||
|
return worldProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t VoxelWorld::calculateLayerVoxelHeight(int x, int z) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
LayerID layerID;
|
||||||
|
|
||||||
|
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
||||||
|
ChunkID chunkID(layerID.x, 0, layerID.z);
|
||||||
|
|
||||||
|
for (int y = worldProps.chunkSizeY - 1; y >= 0; y--) {
|
||||||
|
chunkID.y = y;
|
||||||
|
|
||||||
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
||||||
|
uint8_t chunkVoxelHeight =
|
||||||
|
chunk.calculateLayerVoxelHeight(layerVoxelID);
|
||||||
|
|
||||||
|
if (chunkVoxelHeight != 0) {
|
||||||
|
return chunkVoxelHeight + chunkID.y * CHUNK_SIZE_Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
18
Deer/src/Deer/Voxels/VoxelWorldData.cpp
Normal file
18
Deer/src/Deer/Voxels/VoxelWorldData.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "Deer/Voxels/VoxelWorldData.h"
|
||||||
|
#include "Deer/Voxels/Chunk.h"
|
||||||
|
#include "Deer/Voxels/Layer.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace VoxelWorld {
|
||||||
|
VoxelWorldProps worldProps;
|
||||||
|
|
||||||
|
Scope<Chunk[]> chunks;
|
||||||
|
Scope<Layer[]> layers;
|
||||||
|
|
||||||
|
bool initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelWorld::isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Deer/src/Deer/Voxels/VoxelWorldData.h
Normal file
13
Deer/src/Deer/Voxels/VoxelWorldData.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Deer/Tools/Memory.h"
|
||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace VoxelWorld {
|
||||||
|
extern VoxelWorldProps worldProps;
|
||||||
|
|
||||||
|
extern Scope<Chunk[]> chunks;
|
||||||
|
extern Scope<Layer[]> layers;
|
||||||
|
extern bool initialized;
|
||||||
|
} // namespace VoxelWorld
|
||||||
|
} // namespace Deer
|
||||||
159
Deer/src/Deer/Voxels/VoxelWorld_Raycast.cpp
Normal file
159
Deer/src/Deer/Voxels/VoxelWorld_Raycast.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/Voxels/Chunk.h"
|
||||||
|
#include "Deer/Voxels/Layer.h"
|
||||||
|
#include "Deer/Voxels/VoxelWorldData.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
VoxelRayResult VoxelWorld::rayCast(glm::vec3 position, glm::vec3 dir, float maxDistance) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
VoxelRayResult result;
|
||||||
|
|
||||||
|
result.hitPos.x = (int32_t)std::floor(position.x);
|
||||||
|
result.hitPos.y = (int32_t)std::floor(position.y);
|
||||||
|
result.hitPos.z = (int32_t)std::floor(position.z);
|
||||||
|
|
||||||
|
result.distance = 0;
|
||||||
|
|
||||||
|
if (dir.x == 0 && dir.y == 0 && dir.z == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = glm::normalize(dir);
|
||||||
|
|
||||||
|
glm::vec3 stepAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
||||||
|
glm::vec3 distanceAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
||||||
|
|
||||||
|
int8_t directionAxis[3] = { 1, 1, 1 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (dir[i] < 0) {
|
||||||
|
stepAxis[i] = -1.0f / dir[i];
|
||||||
|
directionAxis[i] = -1;
|
||||||
|
distanceAxis[i] = stepAxis[i] * ((float)position[i] - (float)(&result.hitPos.x)[i]);
|
||||||
|
}
|
||||||
|
else if (dir[i] > 0) {
|
||||||
|
stepAxis[i] = 1.0f / dir[i];
|
||||||
|
distanceAxis[i] = stepAxis[i] * (1 - (float)position[i] + (float)(&result.hitPos.x)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result.distance < maxDistance) {
|
||||||
|
float minDistance = distanceAxis[0];
|
||||||
|
for (int i = 1; i < 3; i++) {
|
||||||
|
if (distanceAxis[i] < minDistance)
|
||||||
|
minDistance = distanceAxis[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.distance = minDistance;
|
||||||
|
if (result.distance > maxDistance)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (minDistance == distanceAxis[i]) {
|
||||||
|
result.hitPos[i] += directionAxis[i];
|
||||||
|
distanceAxis[i] = minDistance + stepAxis[i];
|
||||||
|
|
||||||
|
Voxel hitVoxel = readVoxel(result.hitPos);
|
||||||
|
|
||||||
|
if (hitVoxel == nullVoxel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (hitVoxel != 0) {
|
||||||
|
result.face = i * 2;
|
||||||
|
|
||||||
|
if (directionAxis[i] == -1)
|
||||||
|
result.face++;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.distance = maxDistance;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelRayResult VoxelWorld::rayCast_editor(glm::vec3 position, glm::vec3 dir, float maxDistance) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
VoxelRayResult result;
|
||||||
|
|
||||||
|
result.hitPos.x = (int32_t)std::floor(position.x);
|
||||||
|
result.hitPos.y = (int32_t)std::floor(position.y);
|
||||||
|
result.hitPos.z = (int32_t)std::floor(position.z);
|
||||||
|
|
||||||
|
result.distance = 0;
|
||||||
|
|
||||||
|
if (dir.x == 0 && dir.y == 0 && dir.z == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = glm::normalize(dir);
|
||||||
|
|
||||||
|
glm::vec3 stepAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
||||||
|
glm::vec3 distanceAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
||||||
|
|
||||||
|
int8_t directionAxis[3] = { 1, 1, 1 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (dir[i] < 0) {
|
||||||
|
stepAxis[i] = -1.0f / dir[i];
|
||||||
|
directionAxis[i] = -1;
|
||||||
|
distanceAxis[i] = stepAxis[i] * ((float)position[i] - (float)result.hitPos[i]);
|
||||||
|
}
|
||||||
|
else if (dir[i] > 0) {
|
||||||
|
stepAxis[i] = 1.0f / dir[i];
|
||||||
|
distanceAxis[i] = stepAxis[i] * (1 - (float)position[i] + (float)result.hitPos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Voxel hitVoxel = readVoxel(result.hitPos);
|
||||||
|
bool has_exit_inner_walls = hitVoxel.id == 0;
|
||||||
|
while (result.distance < maxDistance) {
|
||||||
|
float minDistance = distanceAxis[0];
|
||||||
|
for (int i = 1; i < 3; i++) {
|
||||||
|
if (distanceAxis[i] < minDistance)
|
||||||
|
minDistance = distanceAxis[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.distance = minDistance;
|
||||||
|
if (result.distance > maxDistance)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (minDistance == distanceAxis[i]) {
|
||||||
|
result.hitPos[i] += directionAxis[i];
|
||||||
|
distanceAxis[i] = minDistance + stepAxis[i];
|
||||||
|
|
||||||
|
Voxel hitVoxel = readVoxel(result.hitPos);
|
||||||
|
|
||||||
|
if (hitVoxel.id == 0) {
|
||||||
|
if (has_exit_inner_walls && result.hitPos.y == -1 && directionAxis[1] == -1 && i == 1) {
|
||||||
|
result.face = NORMAL_UP;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_exit_inner_walls = true;
|
||||||
|
} else if (hitVoxel.id != 0 && has_exit_inner_walls) {
|
||||||
|
result.face = i * 2;
|
||||||
|
|
||||||
|
if (directionAxis[i] == -1)
|
||||||
|
result.face++;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.distance = maxDistance;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
255
Deer/src/Deer/Voxels/VoxelWorld_VoxelManipultation.cpp
Normal file
255
Deer/src/Deer/Voxels/VoxelWorld_VoxelManipultation.cpp
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
#include "Deer/Log.h"
|
||||||
|
#include "Deer/VoxelWorld.h"
|
||||||
|
#include "Deer/Voxels/Chunk.h"
|
||||||
|
#include "Deer/Voxels/Layer.h"
|
||||||
|
|
||||||
|
#include "Deer/Voxels/VoxelWorldData.h"
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
Voxel VoxelWorld::readVoxel(VoxelCordinates coords) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
ChunkID chunkID;
|
||||||
|
ChunkVoxelID chunkVoxelID;
|
||||||
|
|
||||||
|
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
||||||
|
if (!worldProps.isValid(chunkID)) return emptyVoxel;
|
||||||
|
|
||||||
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
||||||
|
return chunk.readVoxel(chunkVoxelID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelWorld::setVoxel(VoxelCordinates coords, Voxel info) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
ChunkID chunkID;
|
||||||
|
ChunkVoxelID chunkVoxelID;
|
||||||
|
|
||||||
|
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
||||||
|
if (!worldProps.isValid(chunkID)) return;
|
||||||
|
|
||||||
|
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
||||||
|
chunk.modVoxel(chunkVoxelID) = info;
|
||||||
|
|
||||||
|
LayerID layerID;
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
|
||||||
|
extractLayerCordinates(coords.x, coords.z, layerID, layerVoxelID);
|
||||||
|
|
||||||
|
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
||||||
|
LayerVoxel& layerVoxel = layer.modLayerVoxel(layerVoxelID);
|
||||||
|
|
||||||
|
if (!info.isVoxelType())
|
||||||
|
layerVoxel.height = calculateLayerVoxelHeight(coords.x, coords.z);
|
||||||
|
else if (coords.y >= layerVoxel.height)
|
||||||
|
layerVoxel.height = coords.y + 1;
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
chunkQueue.addChunk(chunkID);
|
||||||
|
// For every axis, X & Y & Z
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (chunkVoxelID[i] == 0 && chunkID[i] != 0) {
|
||||||
|
ChunkID nextChunk = chunkID;
|
||||||
|
nextChunk[i]--;
|
||||||
|
chunkQueue.addChunk(nextChunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunkVoxelID[i] == CHUNK_SIZE(i) &&
|
||||||
|
chunkID[i] != worldProps[i] - 1) {
|
||||||
|
ChunkID nextChunk = chunkID;
|
||||||
|
nextChunk[i]++;
|
||||||
|
chunkQueue.addChunk(nextChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we should update the lighting
|
||||||
|
bakeAmbientLightFromPoint(coords.x, coords.z);
|
||||||
|
bakeVoxelLightFromPoint(coords);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelWorld::fillVoxels(VoxelCordinates min, VoxelCordinates max, Voxel info) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
ChunkID minChunkID;
|
||||||
|
ChunkID maxChunkID;
|
||||||
|
ChunkVoxelID minChunkVoxelID;
|
||||||
|
ChunkVoxelID maxChunkVoxelID;
|
||||||
|
|
||||||
|
worldProps.clampAndSetMinMax(min, max);
|
||||||
|
|
||||||
|
extractChunkCordinates(min, minChunkID, minChunkVoxelID);
|
||||||
|
extractChunkCordinates(max, maxChunkID, maxChunkVoxelID);
|
||||||
|
for (int chunkX = minChunkID.x; chunkX <= maxChunkID.x; chunkX++) {
|
||||||
|
for (int chunkY = minChunkID.y; chunkY <= maxChunkID.y; chunkY++) {
|
||||||
|
for (int chunkZ = minChunkID.z; chunkZ <= maxChunkID.z;
|
||||||
|
chunkZ++) {
|
||||||
|
ChunkID workingChunkID(chunkX, chunkY, chunkZ);
|
||||||
|
LayerID workingLayerID(chunkX, chunkZ);
|
||||||
|
Chunk& workingChunk =
|
||||||
|
chunks[worldProps.getWorldChunkID(workingChunkID)];
|
||||||
|
Layer& workingLayer =
|
||||||
|
layers[worldProps.getWorldLayerID(workingLayerID)];
|
||||||
|
|
||||||
|
ChunkVoxelID workingMin(0, 0, 0);
|
||||||
|
ChunkVoxelID workingMax(CHUNK_SIZE_X - 1, CHUNK_SIZE_Y - 1,
|
||||||
|
CHUNK_SIZE_Z - 1);
|
||||||
|
|
||||||
|
if (chunkX == minChunkID.x)
|
||||||
|
workingMin.x = minChunkVoxelID.x;
|
||||||
|
if (chunkY == minChunkID.y)
|
||||||
|
workingMin.y = minChunkVoxelID.y;
|
||||||
|
if (chunkZ == minChunkID.z)
|
||||||
|
workingMin.z = minChunkVoxelID.z;
|
||||||
|
|
||||||
|
if (chunkX == maxChunkID.x)
|
||||||
|
workingMax.x = maxChunkVoxelID.x;
|
||||||
|
if (chunkY == maxChunkID.y)
|
||||||
|
workingMax.y = maxChunkVoxelID.y;
|
||||||
|
if (chunkZ == maxChunkID.z)
|
||||||
|
workingMax.z = maxChunkVoxelID.z;
|
||||||
|
|
||||||
|
LayerVoxelID workingMinLayer(workingMin.x, workingMin.z);
|
||||||
|
LayerVoxelID workingMaxLayer(workingMax.x, workingMax.z);
|
||||||
|
|
||||||
|
workingChunk.fillVoxels(workingMin, workingMax, info);
|
||||||
|
workingLayer.fillVoxelLayerMaxHeight(
|
||||||
|
workingMinLayer, workingMaxLayer, max.y);
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
chunkQueue.addChunk(workingChunkID);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
VoxelCordinates minLightModification = min;
|
||||||
|
VoxelCordinates maxLightModification = max;
|
||||||
|
// We want to add a 16 layer border
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
minLightModification[i] -= 16;
|
||||||
|
maxLightModification[i] += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
worldProps.clampCordinates(minLightModification);
|
||||||
|
worldProps.clampCordinates(maxLightModification);
|
||||||
|
|
||||||
|
bakeAmbientLight(minLightModification.x, maxLightModification.x,
|
||||||
|
minLightModification.z, maxLightModification.z);
|
||||||
|
bakeVoxelLight(minLightModification, maxLightModification);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelWorld::remplaceVoxels(VoxelCordinates min, VoxelCordinates max,
|
||||||
|
Voxel ref, Voxel value) {
|
||||||
|
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
||||||
|
|
||||||
|
ChunkID minChunkID;
|
||||||
|
ChunkID maxChunkID;
|
||||||
|
ChunkVoxelID minChunkVoxelID;
|
||||||
|
ChunkVoxelID maxChunkVoxelID;
|
||||||
|
|
||||||
|
worldProps.clampAndSetMinMax(min, max);
|
||||||
|
|
||||||
|
extractChunkCordinates(min, minChunkID, minChunkVoxelID);
|
||||||
|
extractChunkCordinates(max, maxChunkID, maxChunkVoxelID);
|
||||||
|
for (int chunkX = minChunkID.x; chunkX <= maxChunkID.x; chunkX++) {
|
||||||
|
for (int chunkY = minChunkID.y; chunkY <= maxChunkID.y; chunkY++) {
|
||||||
|
for (int chunkZ = minChunkID.z; chunkZ <= maxChunkID.z;
|
||||||
|
chunkZ++) {
|
||||||
|
ChunkID workingChunkID(chunkX, chunkY, chunkZ);
|
||||||
|
Chunk& workingChunk =
|
||||||
|
chunks[worldProps.getWorldChunkID(workingChunkID)];
|
||||||
|
|
||||||
|
ChunkVoxelID workingMin(0, 0, 0);
|
||||||
|
ChunkVoxelID workingMax(CHUNK_SIZE_X - 1, CHUNK_SIZE_Y - 1,
|
||||||
|
CHUNK_SIZE_Z - 1);
|
||||||
|
|
||||||
|
if (chunkX == minChunkID.x)
|
||||||
|
workingMin.x = minChunkVoxelID.x;
|
||||||
|
if (chunkY == minChunkID.y)
|
||||||
|
workingMin.y = minChunkVoxelID.y;
|
||||||
|
if (chunkZ == minChunkID.z)
|
||||||
|
workingMin.z = minChunkVoxelID.z;
|
||||||
|
|
||||||
|
if (chunkX == maxChunkID.x)
|
||||||
|
workingMax.x = maxChunkVoxelID.x;
|
||||||
|
if (chunkY == maxChunkID.y)
|
||||||
|
workingMax.y = maxChunkVoxelID.y;
|
||||||
|
if (chunkZ == maxChunkID.z)
|
||||||
|
workingMax.z = maxChunkVoxelID.z;
|
||||||
|
|
||||||
|
workingChunk.remplaceVoxels(workingMin, workingMax, ref,
|
||||||
|
value);
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
chunkQueue.addChunk(workingChunkID);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int xPos = min.x; xPos <= max.x; xPos++) {
|
||||||
|
for (int zPos = min.z; zPos <= max.z; zPos++) {
|
||||||
|
LayerID layerID;
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
|
||||||
|
extractLayerCordinates(xPos, zPos, layerID, layerVoxelID);
|
||||||
|
int worldLayerID = worldProps.getWorldLayerID(layerID);
|
||||||
|
|
||||||
|
layers[worldLayerID].modLayerVoxel(layerVoxelID).height =
|
||||||
|
calculateLayerVoxelHeight(xPos, zPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
VoxelCordinates minLightModification = min;
|
||||||
|
VoxelCordinates maxLightModification = max;
|
||||||
|
// We want to add a 16 layer border
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
minLightModification[i] -= 16;
|
||||||
|
maxLightModification[i] += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
worldProps.clampCordinates(minLightModification);
|
||||||
|
worldProps.clampCordinates(maxLightModification);
|
||||||
|
|
||||||
|
bakeAmbientLight(minLightModification.x, maxLightModification.x,
|
||||||
|
minLightModification.z, maxLightModification.z);
|
||||||
|
bakeVoxelLight(minLightModification, maxLightModification);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerVoxel VoxelWorld::readLayerVoxel(int x, int z) {
|
||||||
|
LayerID layerID;
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
|
||||||
|
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
||||||
|
if (!worldProps.isValid(layerID)) return LayerVoxel();
|
||||||
|
|
||||||
|
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
||||||
|
return layer.readLayerVoxel(layerVoxelID);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerVoxel& VoxelWorld::modLayerVoxel(int x, int z) {
|
||||||
|
LayerID layerID;
|
||||||
|
LayerVoxelID layerVoxelID;
|
||||||
|
|
||||||
|
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
||||||
|
if (!worldProps.isValid(layerID)) return nullLayerVoxel;
|
||||||
|
|
||||||
|
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
||||||
|
return layer.modLayerVoxel(layerVoxelID);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#ifndef DEER_RENDER
|
|
||||||
#include "DeerCore/Engine.h"
|
|
||||||
#include "DeerCore/Log.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Engine {
|
|
||||||
Function renderCallback = nullptr;
|
|
||||||
Function updateCallback = nullptr;
|
|
||||||
} // namespace Engine
|
|
||||||
|
|
||||||
void Engine::setUpdateCallback(Function _update) {
|
|
||||||
updateCallback = _update;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::init() {
|
|
||||||
Log::init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::shutdown() {
|
|
||||||
Log::shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::execute() {
|
|
||||||
bool running = true;
|
|
||||||
|
|
||||||
auto previousTime = std::chrono::high_resolution_clock::now();
|
|
||||||
double accumulatedUpdateTime = 0.0;
|
|
||||||
double accumulatedRenderTime = 0.0;
|
|
||||||
|
|
||||||
double targetUpdateTime = 1.0f / 50.0f;
|
|
||||||
double targetRenderTime = 1.0f / 144.0f;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
|
||||||
std::chrono::duration<double> deltaTime = currentTime - previousTime;
|
|
||||||
previousTime = currentTime;
|
|
||||||
|
|
||||||
accumulatedUpdateTime += deltaTime.count();
|
|
||||||
accumulatedRenderTime += deltaTime.count();
|
|
||||||
|
|
||||||
while (accumulatedUpdateTime >= targetUpdateTime) {
|
|
||||||
float timestep = targetUpdateTime;
|
|
||||||
accumulatedUpdateTime -= targetUpdateTime;
|
|
||||||
|
|
||||||
updateCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
#endif
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
#include "DeerCore/Log.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Log {
|
|
||||||
std::shared_ptr<spdlog::logger> coreLogger;
|
|
||||||
std::shared_ptr<spdlog::logger> clientLogger;
|
|
||||||
std::shared_ptr<spdlog::logger> scriptLogger;
|
|
||||||
std::shared_ptr<spdlog::logger> EditorEngineLogger;
|
|
||||||
} // namespace Log
|
|
||||||
|
|
||||||
void Log::init() {
|
|
||||||
// spdlog::set_pattern("%^[%T] %n: %v%$");
|
|
||||||
spdlog::set_pattern("%v%$");
|
|
||||||
|
|
||||||
coreLogger = spdlog::stdout_color_mt("Core");
|
|
||||||
clientLogger = spdlog::stdout_color_mt("Client");
|
|
||||||
scriptLogger = spdlog::stdout_color_mt("Script");
|
|
||||||
EditorEngineLogger = spdlog::stdout_color_mt("UI Engine");
|
|
||||||
|
|
||||||
coreLogger->set_level(spdlog::level::level_enum::trace);
|
|
||||||
clientLogger->set_level(spdlog::level::level_enum::trace);
|
|
||||||
scriptLogger->set_level(spdlog::level::level_enum::trace);
|
|
||||||
EditorEngineLogger->set_level(spdlog::level::level_enum::trace);
|
|
||||||
}
|
|
||||||
spdlog::logger* Log::getCoreLogger() {
|
|
||||||
return coreLogger.get();
|
|
||||||
}
|
|
||||||
spdlog::logger* Log::getClientLogger() {
|
|
||||||
return clientLogger.get();
|
|
||||||
}
|
|
||||||
spdlog::logger* Log::getScriptLogger() {
|
|
||||||
return scriptLogger.get();
|
|
||||||
}
|
|
||||||
spdlog::logger* Log::getEditorEngineLogger() {
|
|
||||||
return EditorEngineLogger.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Log::shutdown() {
|
|
||||||
coreLogger.reset();
|
|
||||||
clientLogger.reset();
|
|
||||||
scriptLogger.reset();
|
|
||||||
EditorEngineLogger.reset();
|
|
||||||
|
|
||||||
spdlog::drop_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Log::coreTrace(const char* msg) {
|
|
||||||
// coreLogger->trace(msg);
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
#include "DeerCore/Log.h"
|
|
||||||
#include "DeerCore/Network.h"
|
|
||||||
|
|
||||||
#include "enet/enet.h"
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Network {
|
|
||||||
ServerSettings serverSettings;
|
|
||||||
ENetHost* enetServer;
|
|
||||||
|
|
||||||
void clientConnect(ENetPeer* refPeer);
|
|
||||||
void clientDisconnect(ENetPeer* refPeer);
|
|
||||||
void clientData(ENetPeer* peer, ENetPacket* packet);
|
|
||||||
|
|
||||||
// Fixed array of clients, defined by max player count
|
|
||||||
Scope<DeerClient[]> clients;
|
|
||||||
} // namespace Network
|
|
||||||
|
|
||||||
void Network::initServer(const ServerSettings& config) {
|
|
||||||
serverSettings = config;
|
|
||||||
if (enet_initialize() != 0) {
|
|
||||||
DEER_CORE_ERROR("An error ocurred while initing enet");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ENetAddress serverAddress;
|
|
||||||
|
|
||||||
serverAddress.host = ENET_HOST_ANY;
|
|
||||||
serverAddress.port = config.port;
|
|
||||||
|
|
||||||
enetServer = enet_host_create(&serverAddress, config.maxClients, 2, config.maxOutgoingBand, config.maxIncomingBand);
|
|
||||||
if (!enetServer) {
|
|
||||||
DEER_CORE_ERROR("An error ocurred while initing server");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clients = MakeScope<DeerClient[]>(serverSettings.maxClients);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::shutdownServer() {
|
|
||||||
enet_deinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::flushServerEvents() {
|
|
||||||
ENetEvent event;
|
|
||||||
while (enet_host_service(enetServer, &event, 0) > 0) {
|
|
||||||
switch (event.type) {
|
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
|
||||||
clientConnect(event.peer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
|
||||||
clientData(event.peer, event.packet);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
clientDisconnect(event.peer);
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::clientConnect(ENetPeer* peer) {
|
|
||||||
DeerClient* client = nullptr;
|
|
||||||
int clientId = -1;
|
|
||||||
for (int i = 0; i < serverSettings.maxClients; i++) {
|
|
||||||
if (clients[i].clientState == DeerClientState::NotConnected) {
|
|
||||||
client = &client[i];
|
|
||||||
clientId = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!client) {
|
|
||||||
DEER_CORE_ERROR("Server full, critical error");
|
|
||||||
enet_peer_disconnect(peer, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client->clientState = DeerClientState::Connected;
|
|
||||||
client->internalPeer = peer;
|
|
||||||
peer->data = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::clientDisconnect(ENetPeer* peer) {
|
|
||||||
DeerClient& client = *(DeerClient*)peer->data;
|
|
||||||
client.clientState = DeerClientState::NotConnected;
|
|
||||||
client.internalPeer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::clientData(ENetPeer* peer, ENetPacket* packetData) {
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,265 +0,0 @@
|
|||||||
#include "DeerCore/Scripting/InternalAPI/Entity.h"
|
|
||||||
#include "DeerCore/Scripting/ScriptEnvironmentContextData.h"
|
|
||||||
|
|
||||||
#include "DeerCore/EntityEnviroment.h"
|
|
||||||
#include "angelscript.h"
|
|
||||||
#include "scriptarray.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Mesh.h"
|
|
||||||
#include "DeerRender/Shader.h"
|
|
||||||
#include "DeerRender/Texture.h"
|
|
||||||
#include "DeerRender/World.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
extern asIScriptEngine* scriptEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity& Scripting::getContextEntity(EntityHandle handle) {
|
|
||||||
asIScriptContext* context = asGetActiveContext();
|
|
||||||
ScriptEnvironmentContextData* environmentData = (ScriptEnvironmentContextData*)context->GetUserData();
|
|
||||||
|
|
||||||
return environmentData->world->entityEnvironment->getEntity(handle.entityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityEnvironment& Scripting::getContextEntityEnvironment(EntityHandle handle) {
|
|
||||||
asIScriptContext* context = asGetActiveContext();
|
|
||||||
ScriptEnvironmentContextData* environmentData = (ScriptEnvironmentContextData*)context->GetUserData();
|
|
||||||
|
|
||||||
return *environmentData->world->entityEnvironment.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& Scripting::getContextEntityComponent(EntityHandle handle) {
|
|
||||||
asIScriptContext* context = asGetActiveContext();
|
|
||||||
ScriptEnvironmentContextData* environmentData = (ScriptEnvironmentContextData*)context->GetUserData();
|
|
||||||
|
|
||||||
return environmentData->world->entityEnvironment->getEntity(handle.entityId).getComponent<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityHandle Scripting::entity_getSelf(EntityHandle& handle) {
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Scripting::entity_getName(EntityHandle& handle) {
|
|
||||||
return getContextEntity(handle).getComponent<TagComponent>().tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scripting::entity_getId(EntityHandle& handle) {
|
|
||||||
return handle.entityId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_setName(std::string& name, EntityHandle& handle) {
|
|
||||||
getContextEntity(handle).getComponent<TagComponent>().tag = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scripting::entity_exists(EntityHandle& handle) {
|
|
||||||
return getContextEntityEnvironment(handle).entityExists(handle.entityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scripting::entity_isRoot(EntityHandle& handle) {
|
|
||||||
return handle.entityId == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_destroy(EntityHandle& handle) {
|
|
||||||
getContextEntity(handle).destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 Scripting::entity_getWorldMatrix(EntityHandle& handle) {
|
|
||||||
Entity& entity = getContextEntity(handle);
|
|
||||||
return entity.getWorldMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scripting::entity_getNetworkBehaviour(EntityHandle& handle) {
|
|
||||||
return (int)getContextEntityComponent<TagComponent>(handle).networkBehaviour;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_setNetworkBehaviour(int value, EntityHandle& handle) {
|
|
||||||
getContextEntityComponent<TagComponent>(handle).networkBehaviour = (EntityNetworkBehaviour)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scripting::entity_getForcedNetworkBehaviour(EntityHandle& handle) {
|
|
||||||
return (int)getContextEntity(handle).getForcedNetworkBehaviour();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scripting::entity_isValidNetworkBehaviour(EntityHandle& handle) {
|
|
||||||
return getContextEntity(handle).isValidNetworkBehaviour();
|
|
||||||
}
|
|
||||||
|
|
||||||
CScriptArray* Scripting::entity_getChildrens(EntityHandle& handle) {
|
|
||||||
Entity& entity = getContextEntity(handle);
|
|
||||||
|
|
||||||
asITypeInfo* arrayStringType = scriptEngine->GetTypeInfoByDecl("array<Entity>");
|
|
||||||
CScriptArray* array = CScriptArray::Create(arrayStringType);
|
|
||||||
|
|
||||||
RelationshipComponent& relationship = entity.getComponent<RelationshipComponent>();
|
|
||||||
size_t childCount = relationship.getChildCount();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < childCount; i++) {
|
|
||||||
EntityHandle entity(relationship.getChildId(i));
|
|
||||||
|
|
||||||
array->Resize(array->GetSize() + 1);
|
|
||||||
array->SetValue(array->GetSize() - 1, &entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityHandle Scripting::entity_createChild(std::string& childName, EntityHandle& handle) {
|
|
||||||
Entity& child = getContextEntityEnvironment(handle).createEntity();
|
|
||||||
Entity& self = getContextEntity(handle);
|
|
||||||
|
|
||||||
child.setParent(self);
|
|
||||||
child.getComponent<TagComponent>().tag = childName;
|
|
||||||
return EntityHandle(child.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_setParent(EntityHandle other_handle, EntityHandle& self_handle) {
|
|
||||||
Entity& child = getContextEntity(other_handle);
|
|
||||||
Entity& self = getContextEntity(self_handle);
|
|
||||||
|
|
||||||
self.setParent(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityHandle Scripting::entity_getParent(EntityHandle& handle) {
|
|
||||||
return EntityHandle(getContextEntity(handle).getParentId());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scripting::entity_isDescendantOf(EntityHandle other_handle, EntityHandle& self_handle) {
|
|
||||||
Entity& child = getContextEntity(other_handle);
|
|
||||||
Entity& self = getContextEntity(self_handle);
|
|
||||||
|
|
||||||
return self.isDescendantOf(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scripting::entity_opEquals(EntityHandle& other, EntityHandle& self_handle) {
|
|
||||||
return other.entityId == self_handle.entityId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_addGenericComponent(asIScriptGeneric* generic) {
|
|
||||||
asITypeInfo* componentType = generic->GetFunction()->GetSubType();
|
|
||||||
std::string componentName = componentType->GetName();
|
|
||||||
|
|
||||||
EntityHandle handle = *(EntityHandle*)generic->GetObject();
|
|
||||||
Entity& self_entity = getContextEntity(handle);
|
|
||||||
|
|
||||||
EntityHandle* return_handle = (EntityHandle*)generic->GetAddressOfReturnLocation();
|
|
||||||
*return_handle = handle;
|
|
||||||
|
|
||||||
if (componentName == "TransformComponent") {
|
|
||||||
self_entity.addComponent<TransformComponent>();
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
} else if (componentName == "MeshComponent") {
|
|
||||||
self_entity.addComponent<MeshComponent>();
|
|
||||||
} else if (componentName == "CameraComponent") {
|
|
||||||
self_entity.addComponent<CameraComponent>();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
DEER_SCRIPT_ERROR("Type {} not suported for {}", componentType->GetName(), generic->GetFunction()->GetDeclaration());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_removeGenericComponent(asIScriptGeneric* generic) {
|
|
||||||
asITypeInfo* componentType = generic->GetFunction()->GetSubType();
|
|
||||||
std::string componentName = componentType->GetName();
|
|
||||||
|
|
||||||
EntityHandle handle = *(EntityHandle*)generic->GetObject();
|
|
||||||
Entity& self_entity = getContextEntity(handle);
|
|
||||||
|
|
||||||
if (componentName == "TransformComponent") {
|
|
||||||
self_entity.removeComponent<TransformComponent>();
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
} else if (componentName == "MeshComponent") {
|
|
||||||
self_entity.removeComponent<MeshComponent>();
|
|
||||||
} else if (componentName == "CameraComponent") {
|
|
||||||
self_entity.removeComponent<CameraComponent>();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
DEER_SCRIPT_ERROR("Type {} not suported for {}", componentType->GetName(), generic->GetFunction()->GetDeclaration());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_getGenericComponent(asIScriptGeneric* generic) {
|
|
||||||
asITypeInfo* componentType = generic->GetFunction()->GetSubType();
|
|
||||||
std::string componentName = componentType->GetName();
|
|
||||||
|
|
||||||
EntityHandle handle = *(EntityHandle*)generic->GetObject();
|
|
||||||
Entity& self_entity = getContextEntity(handle);
|
|
||||||
|
|
||||||
EntityHandle* return_handle = (EntityHandle*)generic->GetAddressOfReturnLocation();
|
|
||||||
*return_handle = handle;
|
|
||||||
|
|
||||||
if (componentName == "TransformComponent") {
|
|
||||||
// Some checks
|
|
||||||
} else if (componentName == "MeshComponent") {
|
|
||||||
// Some checks
|
|
||||||
} else if (componentName == "CameraComponent") {
|
|
||||||
// Some checks
|
|
||||||
} else {
|
|
||||||
DEER_SCRIPT_ERROR("Type {} not suported for {}", componentType->GetName(), generic->GetFunction()->GetDeclaration());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::entity_hasGenericComponent(asIScriptGeneric* generic) {
|
|
||||||
asITypeInfo* componentType = generic->GetFunction()->GetSubType();
|
|
||||||
std::string componentName = componentType->GetName();
|
|
||||||
|
|
||||||
EntityHandle handle = *(EntityHandle*)generic->GetObject();
|
|
||||||
Entity& self_entity = getContextEntity(handle);
|
|
||||||
|
|
||||||
if (componentName == "TransformComponent") {
|
|
||||||
generic->SetReturnByte(self_entity.hasComponent<TransformComponent>());
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
} else if (componentName == "MeshComponent") {
|
|
||||||
generic->SetReturnByte(self_entity.hasComponent<MeshComponent>());
|
|
||||||
} else if (componentName == "CameraComponent") {
|
|
||||||
generic->SetReturnByte(self_entity.hasComponent<CameraComponent>());
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
DEER_SCRIPT_ERROR("Type {} not suported for {}", componentType->GetName(), generic->GetFunction()->GetDeclaration());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SPECIFIC TRANSFORM SECTION
|
|
||||||
glm::vec3 Scripting::transform_getPosition(EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
return transformComponent.position;
|
|
||||||
}
|
|
||||||
glm::vec3 Scripting::transform_getScale(EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
return transformComponent.scale;
|
|
||||||
}
|
|
||||||
glm::quat Scripting::transform_getRotation(EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
return transformComponent.rotation;
|
|
||||||
}
|
|
||||||
glm::vec3 Scripting::transform_getEuler(EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
return transformComponent.getEulerAngles();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::transform_setPosition(glm::vec3 position, EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
transformComponent.position = position;
|
|
||||||
}
|
|
||||||
void Scripting::transform_setScale(glm::vec3 scale, EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
transformComponent.scale = scale;
|
|
||||||
}
|
|
||||||
void Scripting::transform_setRotation(glm::quat rotation, EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
transformComponent.rotation = rotation;
|
|
||||||
}
|
|
||||||
void Scripting::transform_setEuler(glm::vec3 rotation, EntityHandle& handle) {
|
|
||||||
TransformComponent& transformComponent = getContextEntityComponent<TransformComponent>(handle);
|
|
||||||
transformComponent.setEulerAngles(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::constructEntityStruct(void* memory) {
|
|
||||||
new (memory) EntityHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::destructEntityStruct(void* memory) {}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class asIScriptGeneric;
|
|
||||||
class CScriptArray;
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class Entity;
|
|
||||||
class EntityEnvironment;
|
|
||||||
|
|
||||||
struct EntityHandle {
|
|
||||||
uint32_t entityId;
|
|
||||||
EntityHandle(uint32_t _id = 0) : entityId(_id) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Scripting {
|
|
||||||
// SPECIFIC ENTITY SECTION
|
|
||||||
Entity& getContextEntity(EntityHandle);
|
|
||||||
EntityEnvironment& getContextEntityEnvironment(EntityHandle);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& getContextEntityComponent(EntityHandle handle);
|
|
||||||
|
|
||||||
EntityHandle entity_getSelf(EntityHandle&);
|
|
||||||
std::string entity_getName(EntityHandle&);
|
|
||||||
int entity_getId(EntityHandle&);
|
|
||||||
void entity_setName(std::string&, EntityHandle&);
|
|
||||||
bool entity_exists(EntityHandle&);
|
|
||||||
bool entity_isRoot(EntityHandle&);
|
|
||||||
void entity_destroy(EntityHandle&);
|
|
||||||
CScriptArray* entity_getChildrens(EntityHandle&);
|
|
||||||
|
|
||||||
glm::mat4 entity_getWorldMatrix(EntityHandle&);
|
|
||||||
|
|
||||||
int entity_getNetworkBehaviour(EntityHandle&);
|
|
||||||
void entity_setNetworkBehaviour(int, EntityHandle&);
|
|
||||||
int entity_getForcedNetworkBehaviour(EntityHandle&);
|
|
||||||
bool entity_isValidNetworkBehaviour(EntityHandle&);
|
|
||||||
|
|
||||||
EntityHandle entity_createChild(std::string&, EntityHandle&);
|
|
||||||
void entity_setParent(EntityHandle, EntityHandle&);
|
|
||||||
EntityHandle entity_getParent(EntityHandle&);
|
|
||||||
|
|
||||||
bool entity_isDescendantOf(EntityHandle, EntityHandle&);
|
|
||||||
bool entity_opEquals(EntityHandle& other, EntityHandle&);
|
|
||||||
|
|
||||||
void entity_addGenericComponent(asIScriptGeneric* generic);
|
|
||||||
void entity_removeGenericComponent(asIScriptGeneric* generic);
|
|
||||||
void entity_getGenericComponent(asIScriptGeneric* generic);
|
|
||||||
void entity_hasGenericComponent(asIScriptGeneric* generic);
|
|
||||||
|
|
||||||
// SPECIFIC TRANSFORM SECTION
|
|
||||||
glm::vec3 transform_getPosition(EntityHandle&);
|
|
||||||
glm::vec3 transform_getScale(EntityHandle&);
|
|
||||||
glm::quat transform_getRotation(EntityHandle&);
|
|
||||||
glm::vec3 transform_getEuler(EntityHandle&);
|
|
||||||
void transform_setPosition(glm::vec3, EntityHandle&);
|
|
||||||
void transform_setScale(glm::vec3, EntityHandle&);
|
|
||||||
void transform_setRotation(glm::quat, EntityHandle&);
|
|
||||||
void transform_setEuler(glm::vec3, EntityHandle&);
|
|
||||||
|
|
||||||
void constructEntityStruct(void* memory);
|
|
||||||
void destructEntityStruct(void* memory);
|
|
||||||
} // namespace Scripting
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
#include "DeerCore/Scripting/InternalAPI/InternalFunctions.h"
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "angelscript.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void Scripting::errorCallback_angelscript(const asSMessageInfo* msg, void* param) {
|
|
||||||
if (msg->type == asMSGTYPE_WARNING) {
|
|
||||||
DEER_EDITOR_ENGINE_WARN("{0}:{1}:{2} : {3}", msg->section, msg->row, msg->col, msg->message);
|
|
||||||
} else if (msg->type == asMSGTYPE_INFORMATION) {
|
|
||||||
DEER_EDITOR_ENGINE_INFO("{0}:{1}:{2} : {3}", msg->section, msg->row, msg->col, msg->message);
|
|
||||||
} else if (msg->type == asMSGTYPE_ERROR) {
|
|
||||||
DEER_EDITOR_ENGINE_ERROR("{0}:{1}:{2} : {3}", msg->section, msg->row, msg->col, msg->message);
|
|
||||||
} else {
|
|
||||||
DEER_EDITOR_ENGINE_INFO("{0}:{1}:{2} : {3}", msg->section, msg->row, msg->col, msg->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scripting::print(std::string& msg) {
|
|
||||||
DEER_EDITOR_ENGINE_INFO("{0}", msg.c_str());
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
#include "DeerCore/Scripting/InternalAPI/Math.h"
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
void vec3_constructor(void* mem) {
|
|
||||||
new (mem) glm::vec3();
|
|
||||||
}
|
|
||||||
|
|
||||||
void mat4_constructor(void* mem) {
|
|
||||||
new (mem) glm::mat4(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 mat4_getRelativeMatrix(glm::mat4& other, glm::mat4& self) {
|
|
||||||
return glm::inverse(other) * self;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 mat4_getPosition(glm::mat4& matrix) {
|
|
||||||
return glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat mat4_getRotation(glm::mat4& m) {
|
|
||||||
glm::vec3 scale = mat4_getScale(m);
|
|
||||||
|
|
||||||
// Avoid division by zero
|
|
||||||
glm::mat3 rotationMatrix;
|
|
||||||
rotationMatrix[0] = glm::vec3(m[0]) / scale.x;
|
|
||||||
rotationMatrix[1] = glm::vec3(m[1]) / scale.y;
|
|
||||||
rotationMatrix[2] = glm::vec3(m[2]) / scale.z;
|
|
||||||
|
|
||||||
return glm::quat_cast(rotationMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 mat4_getScale(glm::mat4& m) {
|
|
||||||
glm::vec3 scale;
|
|
||||||
|
|
||||||
scale.x = glm::length(glm::vec3(m[0]));
|
|
||||||
scale.y = glm::length(glm::vec3(m[1]));
|
|
||||||
scale.z = glm::length(glm::vec3(m[2]));
|
|
||||||
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vec3_constructor_params(float x, float y, float z, void* mem) {
|
|
||||||
new (mem) glm::vec3(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 vec3_add(glm::vec3& value, glm::vec3& self) {
|
|
||||||
return self + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 vec3_sub(const glm::vec3& value, glm::vec3& self) {
|
|
||||||
return self - value;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 vec3_neg(glm::vec3& self) {
|
|
||||||
return -self;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 vec3_mult(float value, glm::vec3& self) {
|
|
||||||
return self * value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void quat_construct(glm::quat* mem) {
|
|
||||||
new (mem) glm::quat();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quat_copyConstruct(glm::quat* data, glm::quat* mem) {
|
|
||||||
new (mem) glm::quat(*data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void quat_constructFromValue(float x, float y, float z, float w, glm::quat* mem) {
|
|
||||||
new (mem) glm::quat(x, y, z, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 quat_getEuler(glm::quat* mem) {
|
|
||||||
return glm::degrees(glm::eulerAngles(*mem));
|
|
||||||
}
|
|
||||||
|
|
||||||
void quat_setEuler(glm::vec3 euler, glm::quat* mem) {
|
|
||||||
new (mem) glm::quat(glm::radians(euler));
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat quat_multiply(glm::quat* data, glm::quat* mem) {
|
|
||||||
return *mem * *data;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 transform_relative(glm::vec3 pos, TransformComponent* transform) {
|
|
||||||
return transform->getMatrix() * glm::vec4(pos, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void transform_construct(TransformComponent* mem) {
|
|
||||||
new (mem) TransformComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void camera_construct(CameraComponent* mem) {
|
|
||||||
new (mem) CameraComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneCamera_Construct(WorldCamera* mem) {
|
|
||||||
new (mem) WorldCamera();
|
|
||||||
}
|
|
||||||
} // namespace Scripting
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#include "DeerCore/Scripting/InternalAPI/World.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
EntityHandle Scripting::getRoot() {
|
|
||||||
return EntityHandle();
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerCore/Scripting/InternalAPI/Entity.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
EntityHandle getRoot();
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,304 +0,0 @@
|
|||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "angelscript.h"
|
|
||||||
|
|
||||||
#include <iso646.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
#include "DeerRender/Tools/Path.h"
|
|
||||||
|
|
||||||
#include <angelscript.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
extern asIScriptEngine* scriptEngine;
|
|
||||||
|
|
||||||
static std::stringstream stream;
|
|
||||||
static std::string str;
|
|
||||||
|
|
||||||
void printFuncList(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetFuncdefCount(); ++i) {
|
|
||||||
asITypeInfo* t = engine.GetFuncdefByIndex(i);
|
|
||||||
if (!t)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
asIScriptFunction* func = t->GetFuncdefSignature();
|
|
||||||
if (!func || func->GetSubType())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string decl = func->GetDeclaration(true, true, true);
|
|
||||||
|
|
||||||
// Detect class-scoped funcdefs by presence of "::" in the declaration
|
|
||||||
size_t scopePos = decl.find("::");
|
|
||||||
if (scopePos != std::string::npos)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
stream << "funcdef " << decl << ";\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printEnumList(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetEnumCount(); ++i) {
|
|
||||||
const auto e = engine.GetEnumByIndex(i);
|
|
||||||
if (!e)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string_view ns = e->GetNamespace();
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "namespace " << ns << " {\n";
|
|
||||||
|
|
||||||
stream << "enum " << e->GetName() << " {\n";
|
|
||||||
for (int j = 0; j < e->GetEnumValueCount(); ++j) {
|
|
||||||
int value;
|
|
||||||
stream << "\t" << e->GetEnumValueByIndex(j, &value) << " = "
|
|
||||||
<< value;
|
|
||||||
if (j < e->GetEnumValueCount() - 1)
|
|
||||||
stream << ",";
|
|
||||||
stream << "\n";
|
|
||||||
}
|
|
||||||
stream << "}\n";
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "}\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeParameters(asIScriptFunction* function) {
|
|
||||||
for (int n = 0; n < function->GetParamCount(); n++) {
|
|
||||||
int typeId;
|
|
||||||
asDWORD flags;
|
|
||||||
const char* name;
|
|
||||||
const char* defaultArgument;
|
|
||||||
|
|
||||||
function->GetParam(n, &typeId, &flags, &name, &defaultArgument);
|
|
||||||
|
|
||||||
if (typeId == -1) {
|
|
||||||
stream << "?";
|
|
||||||
} else {
|
|
||||||
asITypeInfo* ti = function->GetEngine()->GetTypeInfoById(typeId);
|
|
||||||
if (ti && (ti->GetFlags() & asOBJ_FUNCDEF)) {
|
|
||||||
stream << ti->GetName();
|
|
||||||
} else {
|
|
||||||
const char* typeName = function->GetEngine()->GetTypeDeclaration(typeId, false);
|
|
||||||
stream << typeName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & asTM_INREF)
|
|
||||||
stream << " &in ";
|
|
||||||
else if (flags & asTM_OUTREF)
|
|
||||||
stream << " &out ";
|
|
||||||
else if (flags & asTM_INOUTREF)
|
|
||||||
stream << " &inout ";
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
stream << " " << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n != function->GetParamCount() - 1)
|
|
||||||
stream << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printClassTypeList(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetObjectTypeCount(); ++i) {
|
|
||||||
asITypeInfo* t = engine.GetObjectTypeByIndex(i);
|
|
||||||
if (!t)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string_view ns = t->GetNamespace();
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "namespace " << ns << " {\n";
|
|
||||||
|
|
||||||
stream << "class " << t->GetName();
|
|
||||||
if (std::string("any") == t->GetName())
|
|
||||||
stream << " ";
|
|
||||||
if (t->GetSubTypeCount() > 0) {
|
|
||||||
stream << "<";
|
|
||||||
for (int sub = 0; sub < t->GetSubTypeCount(); ++sub) {
|
|
||||||
if (sub > 0)
|
|
||||||
stream << ", ";
|
|
||||||
const auto st = t->GetSubType(sub);
|
|
||||||
stream << st->GetName();
|
|
||||||
}
|
|
||||||
stream << ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << " {\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < t->GetChildFuncdefCount(); ++i) {
|
|
||||||
asITypeInfo* ftype = t->GetChildFuncdef(i);
|
|
||||||
|
|
||||||
asIScriptFunction* func = ftype->GetFuncdefSignature();
|
|
||||||
|
|
||||||
std::string decl = func->GetDeclaration(false, false, true);
|
|
||||||
stream << "\tfuncdef " << decl << ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < t->GetFactoryCount(); ++j) {
|
|
||||||
asIScriptFunction* f = t->GetFactoryByIndex(j);
|
|
||||||
|
|
||||||
stream << "\t" << t->GetName() << "(";
|
|
||||||
writeParameters(f);
|
|
||||||
stream << ");\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < t->GetBehaviourCount(); ++j) {
|
|
||||||
asEBehaviours behaviours;
|
|
||||||
const auto f = t->GetBehaviourByIndex(j, &behaviours);
|
|
||||||
|
|
||||||
if (behaviours == asBEHAVE_CONSTRUCT ||
|
|
||||||
behaviours == asBEHAVE_DESTRUCT ||
|
|
||||||
behaviours == asBEHAVE_FACTORY)
|
|
||||||
stream << "\t" << f->GetDeclaration(false, false, true)
|
|
||||||
<< ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < t->GetMethodCount(); ++j) {
|
|
||||||
const auto m = t->GetMethodByIndex(j);
|
|
||||||
|
|
||||||
stream << "\t";
|
|
||||||
int methodReturnId = m->GetReturnTypeId();
|
|
||||||
if (methodReturnId == -1) {
|
|
||||||
stream << "? ";
|
|
||||||
} else {
|
|
||||||
stream << t->GetEngine()->GetTypeDeclaration(methodReturnId) << " ";
|
|
||||||
}
|
|
||||||
stream << m->GetName();
|
|
||||||
|
|
||||||
if (m->GetSubTypeCount() > 0) {
|
|
||||||
stream << "<";
|
|
||||||
for (int sub = 0; sub < m->GetSubTypeCount(); ++sub) {
|
|
||||||
if (sub > 0)
|
|
||||||
stream << ", ";
|
|
||||||
const auto st = m->GetSubType(sub);
|
|
||||||
stream << st->GetName();
|
|
||||||
}
|
|
||||||
stream << ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << "(";
|
|
||||||
|
|
||||||
writeParameters(m);
|
|
||||||
stream << ")";
|
|
||||||
|
|
||||||
// stream << "\t" << m->GetDeclaration(false, false, true);
|
|
||||||
|
|
||||||
if (m->IsProperty())
|
|
||||||
stream << " property";
|
|
||||||
stream << ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < t->GetPropertyCount(); ++j) {
|
|
||||||
stream << "\t" << t->GetPropertyDeclaration(j, false) << ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < t->GetChildFuncdefCount(); ++j) {
|
|
||||||
stream
|
|
||||||
<< "\tfuncdef "
|
|
||||||
<< t->GetChildFuncdef(j)->GetFuncdefSignature()->GetDeclaration(
|
|
||||||
false)
|
|
||||||
<< ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << "}\n";
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "}\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printGlobalFunctionList(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetGlobalFunctionCount(); ++i) {
|
|
||||||
const auto f = engine.GetGlobalFunctionByIndex(i);
|
|
||||||
|
|
||||||
std::string_view ns = f->GetNamespace();
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "namespace " << ns << " { ";
|
|
||||||
int methodReturnId = f->GetReturnTypeId();
|
|
||||||
if (methodReturnId == -1) {
|
|
||||||
stream << "? ";
|
|
||||||
} else {
|
|
||||||
stream << f->GetEngine()->GetTypeDeclaration(methodReturnId) << " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << f->GetName() << "(";
|
|
||||||
|
|
||||||
writeParameters(f);
|
|
||||||
stream << ")";
|
|
||||||
|
|
||||||
// stream << "\t" << m->GetDeclaration(false, false, true);
|
|
||||||
|
|
||||||
if (f->IsProperty())
|
|
||||||
stream << " property";
|
|
||||||
stream << ";";
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "\t}";
|
|
||||||
stream << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printGlobalPropertyList(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetGlobalPropertyCount(); ++i) {
|
|
||||||
const char* name;
|
|
||||||
const char* ns0;
|
|
||||||
int type;
|
|
||||||
engine.GetGlobalPropertyByIndex(i, &name, &ns0, &type, nullptr, nullptr,
|
|
||||||
nullptr, nullptr);
|
|
||||||
|
|
||||||
std::string t = engine.GetTypeDeclaration(type, true);
|
|
||||||
if (t.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string_view ns = ns0;
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "namespace " << ns << " { ";
|
|
||||||
stream << t << " " << name << ";";
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << " }";
|
|
||||||
stream << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printGlobalTypedef(const asIScriptEngine& engine) {
|
|
||||||
for (int i = 0; i < engine.GetTypedefCount(); ++i) {
|
|
||||||
const auto type = engine.GetTypedefByIndex(i);
|
|
||||||
if (!type)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string_view ns = type->GetNamespace();
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "namespace " << ns << " {\n";
|
|
||||||
stream << "typedef "
|
|
||||||
<< engine.GetTypeDeclaration(type->GetTypedefTypeId()) << " "
|
|
||||||
<< type->GetName() << ";\n";
|
|
||||||
if (!ns.empty())
|
|
||||||
stream << "}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void generatePredefined(const Path& root) {
|
|
||||||
stream.clear();
|
|
||||||
stream.str("");
|
|
||||||
str.clear();
|
|
||||||
stream << "// This file is autogenerated\n";
|
|
||||||
|
|
||||||
printFuncList(*scriptEngine);
|
|
||||||
printEnumList(*scriptEngine);
|
|
||||||
printClassTypeList(*scriptEngine);
|
|
||||||
printGlobalFunctionList(*scriptEngine);
|
|
||||||
printGlobalPropertyList(*scriptEngine);
|
|
||||||
printGlobalTypedef(*scriptEngine);
|
|
||||||
|
|
||||||
Path path = root / "as.predefined";
|
|
||||||
std::ofstream predefinedFile(path);
|
|
||||||
std::string info = stream.str();
|
|
||||||
predefinedFile.write(info.c_str(), info.size());
|
|
||||||
predefinedFile.close();
|
|
||||||
}
|
|
||||||
} // namespace Scripting
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#include "DeerCore/Log.h"
|
|
||||||
#include "DeerCore/Scripting.h"
|
|
||||||
#include "DeerCore/Tools/Memory.h"
|
|
||||||
#include "angelscript.h"
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scripting {
|
|
||||||
extern asIScriptEngine* scriptEngine;
|
|
||||||
|
|
||||||
} // namespace Scripting
|
|
||||||
|
|
||||||
asIScriptEngine* Scripting::getScriptEngine() {
|
|
||||||
return scriptEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Deer
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user