Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c5992db4a | |||
| a4c8f44ae3 | |||
| 0b1dcb5e55 | |||
| 76f2204074 | |||
| b72fb412a7 | |||
| d377e99d31 | |||
| f154eac1e9 | |||
| 7489393d3d | |||
| 1af4547c97 | |||
| 3e222b09be | |||
| 7813d35cad | |||
| efab720485 | |||
| 5d0741635c | |||
| 041853a4a0 | |||
| 946c9e0027 | |||
| 6ee3cc146f | |||
| 398b655f3d | |||
| 818941460f | |||
| 2d15ff8c07 | |||
| 5d3fc40d74 | |||
| 84fa7a450b | |||
| baba8f2e09 | |||
| 9e6ee7b2e2 | |||
| f246d0e227 | |||
| 67b316a70b | |||
| 54f8156b6b | |||
| 47871fa1dc | |||
| ba42be46ba | |||
| 90f5569855 | |||
| a6328299ec | |||
| c9378c630d | |||
| 19c342b921 | |||
| 3817b5a355 | |||
| ded41e7c3e | |||
| 23989d5cf7 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@
|
||||
*.dbscn
|
||||
*.make
|
||||
*.code-workspace
|
||||
as.predefined
|
||||
Makefile
|
||||
|
||||
as.predefined_tmp
|
||||
|
||||
@ -19,9 +19,12 @@ project "DeerService"
|
||||
"vendor/entt/include",
|
||||
"vendor/cereal/include",
|
||||
"vendor/angelScript/include",
|
||||
"vendor/smallVector"
|
||||
"vendor/smallVector",
|
||||
"vendor/enet/include"
|
||||
}
|
||||
|
||||
links {"enet"}
|
||||
|
||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
||||
|
||||
|
||||
@ -6,8 +6,8 @@ project "Deer"
|
||||
staticruntime "off"
|
||||
|
||||
files {
|
||||
"src/Deer/**.h",
|
||||
"src/Deer/**.cpp",
|
||||
"src/DeerCore/**.h",
|
||||
"src/DeerCore/**.cpp",
|
||||
"src/DeerRender/**.h",
|
||||
"src/DeerRender/**.cpp",
|
||||
"src/Plattform/OpenGL/**.h",
|
||||
@ -35,7 +35,8 @@ project "Deer"
|
||||
"vendor/cereal/include",
|
||||
"vendor/objload/include/objload",
|
||||
"vendor/angelScript/include",
|
||||
"vendor/smallVector"
|
||||
"vendor/smallVector",
|
||||
"vendor/enet/include"
|
||||
}
|
||||
|
||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||
@ -81,7 +82,8 @@ project "Deer"
|
||||
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
||||
"gio-2.0", -- GIO library
|
||||
"gobject-2.0", -- GObject library
|
||||
"pthread" -- POSIX threads library
|
||||
"pthread", -- POSIX threads library
|
||||
"enet"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
#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,83 +0,0 @@
|
||||
#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
|
||||
@ -1,62 +0,0 @@
|
||||
#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,51 +0,0 @@
|
||||
#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
|
||||
@ -1,296 +0,0 @@
|
||||
// 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
|
||||
@ -1,209 +0,0 @@
|
||||
// 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,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Tools/SmallVector.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/SmallVector.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <stdint.h>
|
||||
@ -9,7 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/quaternion.hpp"
|
||||
|
||||
@ -18,10 +18,16 @@
|
||||
|
||||
namespace Deer {
|
||||
class ComponentScriptInstance;
|
||||
enum class EntityNetworkBehaviour : uint32_t {
|
||||
PARENT = 0,
|
||||
SERVER = 1 << 0,
|
||||
CLIENT = 1 << 1
|
||||
};
|
||||
|
||||
struct TagComponent {
|
||||
std::string tag;
|
||||
uint32_t entityUID;
|
||||
EntityNetworkBehaviour networkBehaviour = EntityNetworkBehaviour::PARENT;
|
||||
|
||||
TagComponent() = default;
|
||||
TagComponent(const TagComponent&) = default;
|
||||
@ -30,18 +36,18 @@ namespace Deer {
|
||||
};
|
||||
|
||||
struct RelationshipComponent {
|
||||
uint16_t parent_id = 0;
|
||||
u_int32_t parent_id = 0;
|
||||
|
||||
// Use p-ranav's small_vector for children storage
|
||||
// Inline capacity ENTITY_MAX_CHILDREN, fallback to heap if exceeded
|
||||
ankerl::svector<uint16_t, ENTITY_BUFFER_CHILDREN> children;
|
||||
ankerl::svector<u_int32_t, ENTITY_BUFFER_CHILDREN> children;
|
||||
|
||||
inline uint16_t getChildId(size_t i) const {
|
||||
inline u_int32_t getChildId(size_t i) const {
|
||||
DEER_CORE_ASSERT(i < children.size() && children[i] != 0, "Invalid child request {0}", i);
|
||||
return children[i];
|
||||
}
|
||||
|
||||
inline void addChildId(uint16_t childId) {
|
||||
inline void addChildId(u_int32_t childId) {
|
||||
// Prevent duplicates
|
||||
for (auto id : children)
|
||||
if (id == childId)
|
||||
@ -49,7 +55,7 @@ namespace Deer {
|
||||
children.push_back(childId);
|
||||
}
|
||||
|
||||
inline bool removeChild(uint16_t childId) {
|
||||
inline bool removeChild(u_int32_t childId) {
|
||||
for (size_t i = 0; i < children.size(); ++i) {
|
||||
if (children[i] == childId) {
|
||||
// Swap-remove for O(1)
|
||||
@ -67,7 +73,7 @@ namespace Deer {
|
||||
|
||||
RelationshipComponent() = default;
|
||||
RelationshipComponent(const RelationshipComponent&) = default;
|
||||
RelationshipComponent(uint16_t _parent) : parent_id(_parent) {}
|
||||
RelationshipComponent(u_int32_t _parent) : parent_id(_parent) {}
|
||||
};
|
||||
|
||||
struct TransformComponent {
|
||||
@ -75,9 +81,9 @@ namespace Deer {
|
||||
glm::vec3 scale = glm::vec3(1.0f);
|
||||
glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
TransformComponent() = default;
|
||||
TransformComponent() {}
|
||||
TransformComponent(glm::vec3 _position) : position(_position) {}
|
||||
TransformComponent(const TransformComponent&) = default;
|
||||
TransformComponent(const TransformComponent&) {}
|
||||
|
||||
inline const glm::vec3 getEulerAngles() {
|
||||
return glm::degrees(glm::eulerAngles(rotation));
|
||||
12
Deer/Include/DeerCore/Engine.h
Normal file
12
Deer/Include/DeerCore/Engine.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace Deer {
|
||||
using Function = void (*)();
|
||||
|
||||
namespace Engine {
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
void setUpdateCallback(Function);
|
||||
} // namespace Engine
|
||||
} // namespace Deer
|
||||
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include "Deer/Components.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/Render/FrameBuffer.h"
|
||||
#include "DeerRender/Scene.h"
|
||||
#include "DeerRender/World.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
@ -19,37 +19,28 @@
|
||||
namespace Deer {
|
||||
class Entity;
|
||||
|
||||
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 ///////////
|
||||
class EntityEnvironment {
|
||||
public:
|
||||
Environment();
|
||||
~Environment();
|
||||
EntityEnvironment();
|
||||
~EntityEnvironment();
|
||||
// This class can not be copyed
|
||||
Environment(const Environment&) = delete;
|
||||
Environment& operator=(Environment&) = delete;
|
||||
EntityEnvironment(const EntityEnvironment&) = delete;
|
||||
EntityEnvironment& operator=(EntityEnvironment&) = delete;
|
||||
|
||||
// Clears all entities
|
||||
void clear();
|
||||
// Obtains the entity
|
||||
Entity& getEntity(uint16_t id);
|
||||
bool entityExists(uint16_t id) const;
|
||||
uint16_t getEntityCount() const;
|
||||
Entity& getEntity(uint32_t id);
|
||||
bool entityExists(uint32_t id) const;
|
||||
uint32_t getEntityCount() const;
|
||||
|
||||
// Creates a entity child at root
|
||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||
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!
|
||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||
Entity& createEntityWithId(uint16_t id, const std::string& name = "");
|
||||
void destroyEntity(uint16_t id);
|
||||
Entity& createEntityWithId(uint32_t id, const std::string& name = "");
|
||||
void destroyEntity(uint32_t id);
|
||||
|
||||
// Special behaviour
|
||||
// WARNING: This method can change internal pointers and invalidate entitiy references
|
||||
@ -62,20 +53,19 @@ namespace Deer {
|
||||
// Obtains the entity that is on the root of the environment
|
||||
inline Entity& getRoot() { return getEntity(0); }
|
||||
#ifdef DEER_RENDER
|
||||
void render(SceneCamera& camera);
|
||||
void render(const WorldCamera& camera);
|
||||
#endif
|
||||
Scope<entt::registry> m_registry;
|
||||
|
||||
private:
|
||||
uint16_t m_mainCamera = 0;
|
||||
|
||||
std::stack<u_int16_t> unused_entities_spaces;
|
||||
std::stack<u_int32_t> unused_entities_spaces;
|
||||
std::vector<Entity> entities;
|
||||
|
||||
friend class Entity;
|
||||
};
|
||||
|
||||
// Warning: This calss does not initialize for performance
|
||||
class Entity {
|
||||
public:
|
||||
Entity() {}
|
||||
@ -87,15 +77,18 @@ namespace Deer {
|
||||
Entity& duplicate();
|
||||
void destroy();
|
||||
|
||||
uint16_t getId() const { return entId; }
|
||||
uint32_t getId() const { return entId; }
|
||||
Entity& getParent() const;
|
||||
inline uint16_t getParentId() const { return parentId; }
|
||||
inline uint32_t getParentId() const { return parentId; }
|
||||
|
||||
EntityNetworkBehaviour getForcedNetworkBehaviour();
|
||||
bool isValidNetworkBehaviour(EntityNetworkBehaviour nb = EntityNetworkBehaviour::PARENT);
|
||||
|
||||
// TODO, enable transfer entitys from difrent environments
|
||||
void setParent(Entity& parent);
|
||||
bool isDescendantOf(Entity& parent) const;
|
||||
|
||||
Environment* getEnvironment() const { return environment; }
|
||||
EntityEnvironment* getEntityEnvironment() const { return environment; }
|
||||
|
||||
bool isRoot() const { return entId == 0; }
|
||||
glm::mat4 getWorldMatrix() const;
|
||||
@ -107,14 +100,14 @@ namespace Deer {
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
Environment* environment = nullptr;
|
||||
EntityEnvironment* environment = nullptr;
|
||||
entt::entity entHandle = entt::null;
|
||||
uint16_t entId = 0;
|
||||
uint16_t parentId = 0;
|
||||
uint32_t entId = 0;
|
||||
uint32_t parentId = 0;
|
||||
|
||||
Entity(entt::entity handle, Environment* scene, uint16_t entityID);
|
||||
Entity(entt::entity handle, EntityEnvironment* scene, uint32_t entityID);
|
||||
|
||||
friend class Environment;
|
||||
friend class EntityEnvironment;
|
||||
|
||||
public:
|
||||
template <typename T, typename... Args>
|
||||
@ -123,8 +116,7 @@ namespace Deer {
|
||||
!environment->m_registry->all_of<T>(entHandle),
|
||||
"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>
|
||||
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
@ -10,32 +9,17 @@ namespace spdlog {
|
||||
// Simple file to define logs functions optimized depending on the compilation
|
||||
|
||||
namespace Deer {
|
||||
class Log {
|
||||
public:
|
||||
static void init();
|
||||
static void shutdown();
|
||||
namespace Log {
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
static void coreTrace(const char* msg);
|
||||
void coreTrace(const char* msg);
|
||||
|
||||
static inline Ref<spdlog::logger>& getCoreLogger() {
|
||||
return coreLogger;
|
||||
}
|
||||
static inline Ref<spdlog::logger>& getClientLogger() {
|
||||
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;
|
||||
};
|
||||
spdlog::logger* getCoreLogger();
|
||||
spdlog::logger* getClientLogger();
|
||||
spdlog::logger* getScriptLogger();
|
||||
spdlog::logger* getEditorEngineLogger();
|
||||
}; // namespace Log
|
||||
} // namespace Deer
|
||||
|
||||
#define DEER_CORE_TRACE(...) Deer::Log::getCoreLogger()->trace(__VA_ARGS__)
|
||||
35
Deer/Include/DeerCore/Network.h
Normal file
35
Deer/Include/DeerCore/Network.h
Normal file
@ -0,0 +1,35 @@
|
||||
#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
|
||||
118
Deer/Include/DeerCore/Scripting.h
Normal file
118
Deer/Include/DeerCore/Scripting.h
Normal file
@ -0,0 +1,118 @@
|
||||
#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
|
||||
@ -3,30 +3,66 @@
|
||||
#include "angelscript.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace StudioAPI {
|
||||
namespace Scripting {
|
||||
const char* getAngelScriptReturnCodeString(int code);
|
||||
}
|
||||
bool ImplementsInterface(asITypeInfo* type, asITypeInfo* iface);
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
|
||||
#define AS_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r)); \
|
||||
} \
|
||||
#define REGISTER_GLOBAL_FUNC(scriptEngine, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterGlobalFunction( \
|
||||
funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL))
|
||||
|
||||
#define REGISTER_OBJECT_METHOD(scriptEngine, clasdef, funcdef, clas, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asMETHOD(clas, func), asCALL_THISCALL))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_GENERIC_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asFUNCTION(func), asCALL_GENERIC))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_CONSTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_DESTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_DESTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define AS_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
|
||||
} \
|
||||
}
|
||||
#define AS_CHECK_ADDITIONAL_INFO(f, i) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r), i); \
|
||||
} \
|
||||
#define AS_CHECK_ADDITIONAL_INFO(f, i) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r), i); \
|
||||
} \
|
||||
}
|
||||
#define AS_RET_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r)); \
|
||||
return; \
|
||||
} \
|
||||
#define AS_RET_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
32
Deer/Include/DeerCore/Serialization/WorldSettings.h
Normal file
32
Deer/Include/DeerCore/Serialization/WorldSettings.h
Normal file
@ -0,0 +1,32 @@
|
||||
#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
|
||||
18
Deer/Include/DeerCore/Universe.h
Normal file
18
Deer/Include/DeerCore/Universe.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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
|
||||
42
Deer/Include/DeerCore/Voxel.h
Normal file
42
Deer/Include/DeerCore/Voxel.h
Normal file
@ -0,0 +1,42 @@
|
||||
#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
|
||||
62
Deer/Include/DeerCore/World.h
Executable file
62
Deer/Include/DeerCore/World.h
Executable file
@ -0,0 +1,62 @@
|
||||
#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
|
||||
@ -1,21 +0,0 @@
|
||||
#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
|
||||
#include "Deer/Components.h"
|
||||
#include "DeerCore/Components.h"
|
||||
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Shader.h"
|
||||
@ -18,21 +18,15 @@ namespace Deer {
|
||||
MeshComponent(const MeshComponent&) = default;
|
||||
|
||||
Resource<GPUMesh> mesh;
|
||||
Resource<Shader> shader;
|
||||
Resource<Texture> texture;
|
||||
|
||||
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 {
|
||||
CameraComponent() = default;
|
||||
CameraComponent(const CameraComponent&) = default;
|
||||
CameraComponent() {}
|
||||
CameraComponent(const CameraComponent&) {}
|
||||
|
||||
float fov = glm::radians(50.0f);
|
||||
float aspect = 16 / 9;
|
||||
@ -41,11 +35,4 @@ namespace Deer {
|
||||
|
||||
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
|
||||
@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "Deer/DataManager.h"
|
||||
@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "Deer/DataManagment.h"
|
||||
@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "Deer/DataStore.h"
|
||||
20
Deer/Include/DeerRender/Engine.h
Normal file
20
Deer/Include/DeerRender/Engine.h
Normal file
@ -0,0 +1,20 @@
|
||||
#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
|
||||
2
Deer/Include/DeerRender/EntityEnviroment.h
Normal file
2
Deer/Include/DeerRender/EntityEnviroment.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#include "DeerCore/EntityEnviroment.h"
|
||||
@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "Deer/Enviroment.h"
|
||||
@ -1,22 +1,30 @@
|
||||
#pragma once
|
||||
#include "DeerRender/Render/FrameBuffer.h"
|
||||
#include "DeerRender/Resource.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Deer {
|
||||
// TODO: Add safety
|
||||
namespace FrameBufferManager {
|
||||
uint16_t createRGBA8FrameBuffer(std::string& name, int, int);
|
||||
void resizeFrameBuffer(uint16_t frameBufferId, int, int);
|
||||
struct FrameBufferData {
|
||||
enum class FrameBufferType : int {
|
||||
RGBA8 = 1,
|
||||
GBuffer = 2,
|
||||
};
|
||||
|
||||
int getFrameBufferWidth(uint16_t frameBufferId);
|
||||
int getFrameBufferHeight(uint16_t frameBufferId);
|
||||
FrameBufferType frameBufferType;
|
||||
int sizeX, sizeY;
|
||||
int samples;
|
||||
|
||||
const std::string& getFrameBufferName(uint16_t);
|
||||
uint16_t getFrameBufferId(std::string& name);
|
||||
FrameBuffer& getFrameBuffer(uint16_t);
|
||||
FrameBufferData(int _sizeX = 100, int _sizeY = 100, int _samples = 4, FrameBufferType type = FrameBufferType::RGBA8)
|
||||
: sizeX(_sizeX), sizeY(_sizeY), samples(_samples), frameBufferType(type) { }
|
||||
};
|
||||
|
||||
template <>
|
||||
class ResourceBuilder<FrameBuffer> {
|
||||
public:
|
||||
using BaseDataType = FrameBufferData;
|
||||
static Scope<FrameBuffer> buildResource(const BaseDataType& baseData);
|
||||
};
|
||||
|
||||
void unloadAllFrameBuffer();
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
}
|
||||
|
||||
@ -3,20 +3,26 @@
|
||||
#include "DeerRender/Events/KeyEvent.h"
|
||||
#include "DeerRender/Events/MouseEvent.h"
|
||||
|
||||
namespace Deer {
|
||||
class ImGuiLayer {
|
||||
public:
|
||||
~ImGuiLayer() = default;
|
||||
struct ImFont;
|
||||
|
||||
void onAttach();
|
||||
void onDetach();
|
||||
namespace Deer {
|
||||
class Window;
|
||||
|
||||
namespace ImGuiLayer {
|
||||
void init(Window& window);
|
||||
void shutdown();
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
|
||||
void onEvent(Event& event);
|
||||
private:
|
||||
bool onMouseButtonPressedEvent(MouseButtonPressedEvent& e);
|
||||
|
||||
void setTextFont(ImFont*);
|
||||
void setTitleFont(ImFont*);
|
||||
ImFont* getTextFont();
|
||||
ImFont* getTitleFont();
|
||||
|
||||
bool onMouseButtonPressedEvent(MouseButtonPressedEvent& e);
|
||||
bool onMouseButtonReleasedEvent(MouseButtonReleasedEvent& e);
|
||||
bool onMouseMovedEvent(MouseMovedEvent& e);
|
||||
bool onMouseScrollEvent(MouseScrolledEvent& e);
|
||||
@ -24,6 +30,5 @@ namespace Deer {
|
||||
bool onKeyReleasedEvent(KeyReleasedEvent& e);
|
||||
bool onKeyTypedEvent(KeyTypedEvent& e);
|
||||
bool onWindowResizeEvent(WindowResizeEvent& e);
|
||||
};
|
||||
}
|
||||
|
||||
}; // namespace ImGuiLayer
|
||||
} // namespace Deer
|
||||
@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
#include "Deer/Application.h"
|
||||
|
||||
namespace Deer {
|
||||
class Input {
|
||||
public:
|
||||
public:
|
||||
static bool isKeyPressed(unsigned int key);
|
||||
static bool isMouseButtonPressed(int button);
|
||||
static void getMousePos(float& x, float& y);
|
||||
};
|
||||
} // namespace Deer
|
||||
} // namespace Deer
|
||||
|
||||
// From GLFW
|
||||
#define DEER_KEY_SPACE 32
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Log.h"
|
||||
@ -24,8 +24,6 @@ namespace Deer {
|
||||
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 {
|
||||
int8_t x = 0;
|
||||
int8_t y = 0;
|
||||
@ -35,6 +33,15 @@ namespace Deer {
|
||||
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 {
|
||||
public:
|
||||
void createVertices(uint32_t count) {
|
||||
@ -42,15 +49,20 @@ namespace Deer {
|
||||
vertexNormalData = MakeScope<VertexNormal[]>(count);
|
||||
vertexCount = count;
|
||||
}
|
||||
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
||||
void createIndices(uint32_t count) {
|
||||
indexData = MakeScope<uint32_t[]>(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 VertexNormal* getVertexNormal() const { return vertexNormalData.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 getVertexCount() const { return vertexCount; }
|
||||
@ -61,6 +73,8 @@ namespace Deer {
|
||||
Scope<VertexPosition[]> vertexPositionsData;
|
||||
Scope<VertexNormal[]> vertexNormalData;
|
||||
Scope<VertexUV[]> vertexUVData;
|
||||
Scope<VertexColor[]> vertexColorData;
|
||||
Scope<uint8_t[]> vertexAuxData;
|
||||
|
||||
uint32_t indexCount = 0;
|
||||
Scope<uint32_t[]> indexData;
|
||||
@ -77,21 +91,8 @@ namespace Deer {
|
||||
static Scope<GPUMesh> buildResource(const BaseDataType& baseData);
|
||||
};
|
||||
|
||||
namespace MeshManager {
|
||||
uint16_t loadModel(const Path&);
|
||||
uint16_t loadModel(const MeshData&, const Path&);
|
||||
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 Builtin {
|
||||
Resource<GPUMesh> cube();
|
||||
Resource<GPUMesh> sphere();
|
||||
} // namespace Builtin
|
||||
} // namespace Deer
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerRender/Resource.h"
|
||||
|
||||
#include "Deer/Log.h"
|
||||
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
enum class TextureBufferType {
|
||||
RGBA8,
|
||||
RED_INTEGER
|
||||
RED_INTEGER,
|
||||
GBuffer,
|
||||
};
|
||||
|
||||
struct FrameBufferSpecification {
|
||||
@ -18,12 +19,12 @@ namespace Deer {
|
||||
|
||||
bool swapChainTarget = false;
|
||||
FrameBufferSpecification(unsigned int _width, unsigned int _height, std::initializer_list<TextureBufferType> _frameBufferTextures, unsigned int _samples = 1, bool _swapChainTarget = false)
|
||||
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
||||
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
||||
}
|
||||
};
|
||||
|
||||
class FrameBuffer {
|
||||
public:
|
||||
public:
|
||||
virtual ~FrameBuffer() = default;
|
||||
virtual const FrameBufferSpecification& getSpecification() = 0;
|
||||
|
||||
@ -40,5 +41,4 @@ namespace Deer {
|
||||
|
||||
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Deer
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
#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,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "DeerRender/DataManagment.h"
|
||||
#include "DeerRender/Log.h"
|
||||
#include "DeerRender/Tools/Memory.h"
|
||||
#include "DeerRender/Tools/Path.h"
|
||||
@ -12,27 +11,36 @@
|
||||
namespace Deer {
|
||||
template <typename T>
|
||||
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>
|
||||
class Resource {
|
||||
public:
|
||||
int32_t getResourceId() const { return resourceId; }
|
||||
int32_t getResourceIndex() const { return resourceId; }
|
||||
ResourceId getResourceId() const { return ResourceManager<T>::getResourceId(*this); }
|
||||
|
||||
bool isValid() const { return ResourceManager<T>::isValid(*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) {
|
||||
Resource<T> res;
|
||||
res.resourceId = id;
|
||||
return res;
|
||||
}
|
||||
|
||||
inline explicit operator bool() const { return resourceId >= 0; }
|
||||
|
||||
private:
|
||||
// -1 = no resource loaded
|
||||
int32_t resourceId = -1;
|
||||
friend ResourceManager<T>;
|
||||
};
|
||||
@ -52,45 +60,60 @@ namespace Deer {
|
||||
private:
|
||||
struct ResourceData {
|
||||
public:
|
||||
ResourceData(const std::string& _resourceId, Scope<T>&& _data)
|
||||
: storageId(_resourceId), data(std::move(_data)) {}
|
||||
|
||||
Scope<T> data;
|
||||
const std::string storageId;
|
||||
Scope<T> data = nullptr;
|
||||
ResourceId storageId = 0;
|
||||
};
|
||||
|
||||
static std::vector<ResourceData> resources;
|
||||
static std::unordered_map<std::string, Resource<T>> resourceCache;
|
||||
static std::unordered_map<ResourceId, Resource<T>> resourceCache;
|
||||
|
||||
public:
|
||||
template <typename DataSource>
|
||||
static Resource<T> loadResource(const std::string& storageId) {
|
||||
static Resource<T> loadResource(ResourceId storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
using ResourceBuilderBaseDataType = typename ResourceBuilder<T>::BaseDataType;
|
||||
using ResourceBaseType = typename ResourceBuilder<T>::BaseDataType;
|
||||
Scope<T> data;
|
||||
|
||||
if constexpr (!std::is_void_v<ResourceBuilderBaseDataType>) {
|
||||
Scope<ResourceBuilderBaseDataType> baseData = DataManager<DataSource>::template load<ResourceBuilderBaseDataType>(storageId);
|
||||
if (!baseData) {
|
||||
const char* baseDataType = abi::__cxa_demangle(typeid(ResourceBuilderBaseDataType).name(), 0, 0, nullptr);
|
||||
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());
|
||||
return Resource<T>();
|
||||
}
|
||||
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
||||
} else {
|
||||
data = ResourceBuilder<T>::buildResource(); // No base data
|
||||
}
|
||||
Scope<ResourceBaseType> baseData = StorageBackend<DataSource>::template load<ResourceBaseType>(storageId);
|
||||
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({storageId, std::move(data)});
|
||||
resources.push_back({});
|
||||
|
||||
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>();
|
||||
}
|
||||
|
||||
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, ResourceId storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({});
|
||||
|
||||
ResourceData& rd = resources.back();
|
||||
rd.data = std::move(data);
|
||||
rd.storageId = storageId;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static void unloadResources() {
|
||||
resourceCache.clear();
|
||||
resources.clear();
|
||||
@ -100,10 +123,9 @@ namespace Deer {
|
||||
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
||||
}
|
||||
|
||||
static inline const std::string& getStorageId(Resource<T> res) {
|
||||
const static std::string invalid("NULL");
|
||||
static inline ResourceId getResourceId(Resource<T> res) {
|
||||
if (!isValid(res))
|
||||
return invalid;
|
||||
return 0;
|
||||
|
||||
return resources[res.resourceId].storageId;
|
||||
}
|
||||
@ -116,5 +138,11 @@ namespace Deer {
|
||||
template <typename T>
|
||||
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
||||
template <typename T>
|
||||
std::unordered_map<std::string, Resource<T>> ResourceManager<T>::resourceCache;
|
||||
std::unordered_map<ResourceId, Resource<T>> ResourceManager<T>::resourceCache;
|
||||
} // namespace Deer
|
||||
|
||||
// BUILTIN RESOURCE IDS
|
||||
|
||||
#define RESOURCE_CUBE_ID 0x1
|
||||
#define RESOURCE_SPHERE_ID 0x2
|
||||
#define RESOURCE_BASIC_SHADER_ID 0x3
|
||||
7
Deer/Include/DeerRender/Scripting.h
Normal file
7
Deer/Include/DeerRender/Scripting.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Scripting.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace Scripting {
|
||||
}
|
||||
} // namespace Deer
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerRender/Render/Shader.h"
|
||||
#include "DeerRender/Resource.h"
|
||||
|
||||
@ -22,6 +22,11 @@ namespace Deer {
|
||||
}
|
||||
};
|
||||
|
||||
namespace RenderUtils {
|
||||
void initializeRenderUtils();
|
||||
void deinitializeRenderUtils();
|
||||
} // namespace RenderUtils
|
||||
|
||||
template <>
|
||||
class ResourceBuilder<Shader> {
|
||||
public:
|
||||
@ -32,4 +37,9 @@ namespace Deer {
|
||||
namespace DataStore {
|
||||
void loadShader(ShaderData& data, const Path& name);
|
||||
} // namespace DataStore
|
||||
|
||||
namespace Builtin {
|
||||
Resource<Shader> simpleShader();
|
||||
}
|
||||
|
||||
} // namespace Deer
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/SmallVector.h"
|
||||
#include "DeerCore/Tools/SmallVector.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/TypeDefs.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
2
Deer/Include/DeerRender/Universe.h
Normal file
2
Deer/Include/DeerRender/Universe.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Universe.h"
|
||||
94
Deer/Include/DeerRender/Voxel.h
Executable file → Normal file
94
Deer/Include/DeerRender/Voxel.h
Executable file → Normal file
@ -1,33 +1,81 @@
|
||||
#pragma once
|
||||
#include "Deer/Voxel.h"
|
||||
#include "DeerCore/Voxel.h"
|
||||
|
||||
#define LIGHT_PROPAGATION_COMPLEX_DIRS 18
|
||||
#define LIGHT_PROPAGATION_COMPLEX_DIR(id, dir) lightPropagationComplexDir[id + dir * 2]
|
||||
#define LIGHT_PROPAGATION_SIMPLE_FALL 16
|
||||
#define LIGHT_PROPAGATION_COMPLEX_FALL 23
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#define NORMAL_VERTEX_POS(axis, id, normal) normalFacePositions[axis + id * 3 + normal * 3 * 4]
|
||||
#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]
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
struct VoxelLight;
|
||||
extern VoxelLight lightVoxel;
|
||||
struct VoxelVertex {
|
||||
VoxelVertex() = default;
|
||||
VoxelVertex(glm::vec3 _position) : position(_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];
|
||||
glm::vec3 position;
|
||||
};
|
||||
|
||||
struct VoxelLight {
|
||||
uint8_t r_light;
|
||||
uint8_t g_light;
|
||||
uint8_t b_light;
|
||||
uint8_t ambient_light;
|
||||
struct VoxelFaceData {
|
||||
// Basic construction
|
||||
std::vector<VoxelVertex> vertices;
|
||||
std::vector<uint32_t> triangles;
|
||||
|
||||
VoxelLight(uint8_t _ambient_light = 0) : r_light(0), g_light(0), b_light(0), ambient_light(_ambient_light) {}
|
||||
std::array<std::vector<uint32_t>, 4> connections;
|
||||
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
|
||||
@ -1,54 +0,0 @@
|
||||
/**
|
||||
* @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]; }
|
||||
};
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "Deer/VoxelWorld.h"
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerRender/Events/Event.h"
|
||||
|
||||
#include <functional>
|
||||
@ -12,7 +12,7 @@ namespace Deer {
|
||||
unsigned int height;
|
||||
|
||||
WindowProps(const std::string& _title = "Deer Engine",
|
||||
unsigned int _width = 1280,
|
||||
unsigned int _width = 900,
|
||||
unsigned int _height = 720)
|
||||
: title(_title), width(_width), height(_height) {
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include "Deer/Scene.h"
|
||||
#include "DeerCore/World.h"
|
||||
#include "DeerRender/Components.h"
|
||||
|
||||
namespace Deer {
|
||||
struct SceneCamera {
|
||||
struct WorldCamera {
|
||||
TransformComponent transform;
|
||||
CameraComponent camera;
|
||||
|
||||
SceneCamera() {}
|
||||
SceneCamera(TransformComponent _transform, CameraComponent _camera) : transform(_transform), camera(_camera) {}
|
||||
WorldCamera() {}
|
||||
WorldCamera(TransformComponent _transform, CameraComponent _camera) : transform(_transform), camera(_camera) {}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,61 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
@ -1,210 +0,0 @@
|
||||
#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,14 +0,0 @@
|
||||
#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,51 +0,0 @@
|
||||
#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
|
||||
@ -1,18 +0,0 @@
|
||||
#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
|
||||
@ -1,20 +0,0 @@
|
||||
#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
|
||||
@ -1,15 +0,0 @@
|
||||
#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
|
||||
@ -1,16 +0,0 @@
|
||||
#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));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
#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
|
||||
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Deer {
|
||||
class Environment;
|
||||
struct EntitySerializationStruct {
|
||||
uint16_t entityID;
|
||||
Environment* env;
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,57 +0,0 @@
|
||||
#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
|
||||
@ -1,4 +0,0 @@
|
||||
|
||||
namespace Deer {
|
||||
bool is_server_serialization = false;
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
#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
|
||||
@ -1,7 +0,0 @@
|
||||
#include "SerializationGlobalVars.h"
|
||||
|
||||
namespace Deer {
|
||||
|
||||
bool is_server_serialization = false;
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace Deer {
|
||||
extern bool is_server_serialization;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
#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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
#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
|
||||
@ -1,12 +0,0 @@
|
||||
#include "Layer.h"
|
||||
|
||||
namespace Deer {
|
||||
Layer::~Layer() {
|
||||
if (m_layerInfo)
|
||||
delete[] m_layerInfo;
|
||||
}
|
||||
|
||||
void Layer::loadData() {
|
||||
m_layerInfo = new LayerVoxel[LAYER_VOXELS]();
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
#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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
#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
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
#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
|
||||
@ -1,68 +0,0 @@
|
||||
#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
|
||||
@ -1,18 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
#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
|
||||
@ -1,159 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@ -1,255 +0,0 @@
|
||||
#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
|
||||
52
Deer/src/DeerCore/Core/Engine.cpp
Normal file
52
Deer/src/DeerCore/Core/Engine.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#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
|
||||
50
Deer/src/DeerCore/Core/Log.cpp
Executable file
50
Deer/src/DeerCore/Core/Log.cpp
Executable file
@ -0,0 +1,50 @@
|
||||
#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,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
namespace Deer {
|
||||
struct DataStructure {
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Deer/DataStore/DataStructure.h"
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/DataStore/DataStructure.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
@ -1,4 +1,4 @@
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include <algorithm>
|
||||
|
||||
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
||||
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#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,9 +1,8 @@
|
||||
#include "DeerStudio/AngelScriptEngine/ErrorHandle.h"
|
||||
|
||||
#include "DeerCore/Scripting/Helpers.h"
|
||||
#include "angelscript.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace AngelScriptEngine {
|
||||
namespace Scripting {
|
||||
const char* getAngelScriptReturnCodeString(int code) {
|
||||
switch (code) {
|
||||
case asSUCCESS:
|
||||
@ -53,7 +52,7 @@ namespace Deer {
|
||||
}
|
||||
}
|
||||
|
||||
bool AngelScriptEngine::ImplementsInterface(asITypeInfo* type, asITypeInfo* iface) {
|
||||
bool ImplementsInterface(asITypeInfo* type, asITypeInfo* iface) {
|
||||
for (uint32_t i = 0; i < type->GetInterfaceCount(); i++) {
|
||||
if (type->GetInterface(i) == iface)
|
||||
return true;
|
||||
@ -61,5 +60,5 @@ namespace Deer {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace AngelScriptEngine
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
@ -3,31 +3,66 @@
|
||||
#include "angelscript.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace AngelScriptEngine {
|
||||
namespace Scripting {
|
||||
const char* getAngelScriptReturnCodeString(int code);
|
||||
bool ImplementsInterface(asITypeInfo* type, asITypeInfo* iface);
|
||||
}
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
|
||||
#define AS_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::AngelScriptEngine::getAngelScriptReturnCodeString(__r)); \
|
||||
} \
|
||||
#define REGISTER_GLOBAL_FUNC(scriptEngine, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterGlobalFunction( \
|
||||
funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL))
|
||||
|
||||
#define REGISTER_OBJECT_METHOD(scriptEngine, clasdef, funcdef, clas, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asMETHOD(clas, func), asCALL_THISCALL))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_GENERIC_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectMethod( \
|
||||
clasdef, funcdef, \
|
||||
asFUNCTION(func), asCALL_GENERIC))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_CONSTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_DESTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \
|
||||
AS_CHECK(scriptEngine->RegisterObjectBehaviour( \
|
||||
clasdef, asBEHAVE_DESTRUCT, funcdef, \
|
||||
asFUNCTION(func), asCALL_CDECL_OBJLAST))
|
||||
|
||||
#define AS_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
|
||||
} \
|
||||
}
|
||||
#define AS_CHECK_ADDITIONAL_INFO(f, i) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::AngelScriptEngine::getAngelScriptReturnCodeString(__r), i); \
|
||||
} \
|
||||
#define AS_CHECK_ADDITIONAL_INFO(f, i) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r), i); \
|
||||
} \
|
||||
}
|
||||
#define AS_RET_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::AngelScriptEngine::getAngelScriptReturnCodeString(__r)); \
|
||||
return; \
|
||||
} \
|
||||
#define AS_RET_CHECK(f) \
|
||||
{ \
|
||||
int __r = f; \
|
||||
if (__r < 0) { \
|
||||
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
#include "DeerStudio/StudioAPI/Engine.h"
|
||||
#include "DeerCore/Scripting/InternalAPI/Engine.h"
|
||||
#include "DeerRender/Tools/Path.h"
|
||||
#include "DeerStudio/AngelScriptEngine.h"
|
||||
|
||||
#include "angelscript.h"
|
||||
#include "scriptarray.h"
|
||||
@ -9,7 +8,9 @@
|
||||
#include <string>
|
||||
|
||||
namespace Deer {
|
||||
namespace StudioAPI {
|
||||
namespace Scripting {
|
||||
extern asIScriptEngine* scriptEngine;
|
||||
|
||||
std::string getParentPath(std::string& path) {
|
||||
return Path(path).parent_path().string();
|
||||
}
|
||||
@ -23,7 +24,8 @@ namespace Deer {
|
||||
}
|
||||
|
||||
CScriptArray* dividePath_angelscript(std::string& path_s) {
|
||||
CScriptArray* array = CScriptArray::Create(AngelScriptEngine::arrayStringBaseType);
|
||||
asITypeInfo* arrayStringType = scriptEngine->GetTypeInfoByDecl("array<string>");
|
||||
CScriptArray* array = CScriptArray::Create(arrayStringType);
|
||||
|
||||
Path path_p(path_s);
|
||||
for (const auto& part : path_p) {
|
||||
@ -35,5 +37,5 @@ namespace Deer {
|
||||
|
||||
return array;
|
||||
}
|
||||
} // namespace StudioAPI
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
@ -4,11 +4,10 @@
|
||||
class CScriptArray;
|
||||
|
||||
namespace Deer {
|
||||
namespace StudioAPI {
|
||||
// ANGELSCRIPT SPECIFIC
|
||||
namespace Scripting {
|
||||
CScriptArray* dividePath_angelscript(std::string&);
|
||||
std::string getParentPath(std::string&);
|
||||
std::string getParentPathName(std::string&);
|
||||
std::string getPathName(std::string&);
|
||||
} // namespace StudioAPI
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
265
Deer/src/DeerCore/Scripting/InternalAPI/Entity.cpp
Normal file
265
Deer/src/DeerCore/Scripting/InternalAPI/Entity.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
#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
|
||||
67
Deer/src/DeerCore/Scripting/InternalAPI/Entity.h
Normal file
67
Deer/src/DeerCore/Scripting/InternalAPI/Entity.h
Normal file
@ -0,0 +1,67 @@
|
||||
#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
|
||||
@ -0,0 +1,21 @@
|
||||
#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,11 +1,11 @@
|
||||
#pragma once
|
||||
#include "string"
|
||||
struct asSMessageInfo;
|
||||
|
||||
class asSMessageInfo;
|
||||
#include <string>
|
||||
|
||||
namespace Deer {
|
||||
namespace StudioAPI {
|
||||
namespace Scripting {
|
||||
void errorCallback_angelscript(const asSMessageInfo* msg, void* param);
|
||||
void print(std::string& msg);
|
||||
} // namespace StudioAPI
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
104
Deer/src/DeerCore/Scripting/InternalAPI/Math.cpp
Normal file
104
Deer/src/DeerCore/Scripting/InternalAPI/Math.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#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
|
||||
@ -3,13 +3,19 @@
|
||||
#include "glm/gtc/quaternion.hpp"
|
||||
|
||||
#include "DeerRender/Components.h"
|
||||
#include "DeerRender/Scene.h"
|
||||
#include "DeerRender/World.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace StudioAPI {
|
||||
namespace Scripting {
|
||||
void vec3_constructor(void*);
|
||||
void vec3_constructor_params(float, float, float, void*);
|
||||
|
||||
void mat4_constructor(void*);
|
||||
glm::mat4 mat4_getRelativeMatrix(glm::mat4&, glm::mat4&);
|
||||
glm::vec3 mat4_getPosition(glm::mat4&);
|
||||
glm::quat mat4_getRotation(glm::mat4&);
|
||||
glm::vec3 mat4_getScale(glm::mat4&);
|
||||
|
||||
glm::vec3 vec3_add(glm::vec3&, glm::vec3&);
|
||||
glm::vec3 vec3_sub(const glm::vec3&, glm::vec3&);
|
||||
glm::vec3 vec3_neg(glm::vec3&);
|
||||
@ -17,7 +23,6 @@ namespace Deer {
|
||||
|
||||
void quat_construct(glm::quat*);
|
||||
void quat_copyConstruct(glm::quat*, glm::quat*);
|
||||
void quat_destruct(glm::quat*);
|
||||
void quat_constructFromValue(float, float, float, float, glm::quat*);
|
||||
|
||||
glm::vec3 quat_getEuler(glm::quat*);
|
||||
@ -26,10 +31,10 @@ namespace Deer {
|
||||
|
||||
void transform_construct(TransformComponent*);
|
||||
void camera_construct(CameraComponent*);
|
||||
void sceneCamera_Construct(SceneCamera*);
|
||||
void sceneCamera_Construct(WorldCamera*);
|
||||
|
||||
glm::vec3 transform_relative(glm::vec3, TransformComponent*);
|
||||
|
||||
void emptyDestructor();
|
||||
} // namespace StudioAPI
|
||||
} // namespace Scripting
|
||||
} // 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