Compare commits

..

35 Commits
main ... dev

Author SHA1 Message Date
9c5992db4a Working now 2026-03-11 23:04:28 +01:00
a4c8f44ae3 To server 2026-03-10 21:04:04 +01:00
0b1dcb5e55 Tst 2026-03-09 23:16:58 +01:00
76f2204074 Transition 2026-03-09 23:16:47 +01:00
b72fb412a7 Traspass 2026-03-09 18:07:35 +01:00
d377e99d31 Please fix 2026-03-08 22:25:55 +01:00
f154eac1e9 Refactoring resource 2026-03-06 00:42:55 +01:00
7489393d3d Working on studio resources and adding folder suport 2026-03-04 19:07:25 +01:00
1af4547c97 Changes 2026-03-04 00:03:43 +01:00
3e222b09be Refactoring Mesh System 2026-03-01 17:48:56 +01:00
7813d35cad VoxelAspect 2026-02-27 17:28:39 +01:00
efab720485 Refactoring to cluster 2026-02-18 09:39:05 +01:00
5d0741635c Working on voxels 2026-02-17 09:33:57 +01:00
041853a4a0 Gizmo working 2026-02-11 01:49:59 +01:00
946c9e0027 Loading and unloading working 2026-02-10 17:37:28 +01:00
6ee3cc146f Recreating serialization 2026-02-10 13:41:31 +01:00
398b655f3d Serializing 2026-02-09 16:51:49 +01:00
818941460f Default shader and mesh 2026-02-06 03:25:04 +01:00
2d15ff8c07 Finished refactoring 2026-02-05 21:38:30 +01:00
5d3fc40d74 Tree working 2026-02-03 03:53:40 +01:00
84fa7a450b Scripting system compiling 2026-02-03 00:49:34 +01:00
baba8f2e09 Huge Script System Refactor 2026-01-29 15:27:40 +01:00
9e6ee7b2e2 Changed Scene to World 2026-01-22 17:38:25 +01:00
f246d0e227 Changed environment to entity environment 2026-01-22 17:01:46 +01:00
67b316a70b Changed internal structure 2026-01-18 01:02:01 +01:00
54f8156b6b Finished refactoring angelscript internal api 2026-01-14 17:56:41 +01:00
47871fa1dc Remodelating system 2026-01-06 14:20:38 +01:00
ba42be46ba Staged 2026-01-05 22:22:05 +01:00
90f5569855 Working on 3d preview of meshes 2025-12-09 17:07:38 +01:00
a6328299ec Ignoring as.predefined 2025-12-09 10:33:18 +01:00
c9378c630d Cleanup codebase 2025-12-09 10:31:21 +01:00
19c342b921 Improving visuals and icons 2025-12-09 10:19:44 +01:00
3817b5a355 Scene videw working 2025-12-05 13:20:02 +01:00
ded41e7c3e Created Environment as a Resource 2025-12-04 23:41:43 +01:00
23989d5cf7 Cleaning Obsolete Script Engine Editor 2025-12-04 22:38:49 +01:00
649 changed files with 112028 additions and 205057 deletions

1
.gitignore vendored
View File

@ -5,6 +5,7 @@
*.dbscn
*.make
*.code-workspace
as.predefined
Makefile
as.predefined_tmp

View File

@ -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}")

View File

@ -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"
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View 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

View File

@ -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>

View File

@ -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__)

View 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

View 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

View File

@ -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 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::EditorEngine::getAngelScriptReturnCodeString(__r)); \
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); \
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)); \
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
return; \
} \
}

View 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

View 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

View 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
View 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

View File

@ -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();
}
}

View File

@ -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

View File

@ -1,2 +0,0 @@
#pragma once
#include "Deer/DataManager.h"

View File

@ -1,2 +0,0 @@
#pragma once
#include "Deer/DataManagment.h"

View File

@ -1,2 +0,0 @@
#pragma once
#include "Deer/DataStore.h"

View 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

View File

@ -0,0 +1,2 @@
#pragma once
#include "DeerCore/EntityEnviroment.h"

View File

@ -1,2 +0,0 @@
#pragma once
#include "Deer/Enviroment.h"

View File

@ -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();
}
}

View File

@ -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;
};
}

View File

@ -3,19 +3,25 @@
#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:
void setTextFont(ImFont*);
void setTitleFont(ImFont*);
ImFont* getTextFont();
ImFont* getTitleFont();
bool onMouseButtonPressedEvent(MouseButtonPressedEvent& e);
bool onMouseButtonReleasedEvent(MouseButtonReleasedEvent& e);
bool onMouseMovedEvent(MouseMovedEvent& e);
@ -24,6 +30,5 @@ namespace Deer {
bool onKeyReleasedEvent(KeyReleasedEvent& e);
bool onKeyTypedEvent(KeyTypedEvent& e);
bool onWindowResizeEvent(WindowResizeEvent& e);
};
}
}; // namespace ImGuiLayer
} // namespace Deer

View File

@ -1,6 +1,4 @@
#pragma once
#include "Deer/Application.h"
namespace Deer {
class Input {
public:

View File

@ -1,2 +1,2 @@
#pragma once
#include "Deer/Log.h"
#include "DeerCore/Log.h"

View File

@ -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

View File

@ -1,5 +1,5 @@
#pragma once
#include "Deer/Tools/Memory.h"
#include "DeerCore/Tools/Memory.h"
#include <string>
#include <vector>

View File

@ -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 {
@ -40,5 +41,4 @@ namespace Deer {
static FrameBuffer* create(const FrameBufferSpecification& spec);
};
}
} // namespace Deer

View File

@ -1,5 +1,5 @@
#pragma once
#include "Deer/Tools/Memory.h"
#include "DeerCore/Tools/Memory.h"
#include "glm/glm.hpp"

View File

@ -1,5 +1,5 @@
#pragma once
#include "Deer/Tools/Memory.h"
#include "DeerCore/Tools/Memory.h"
#include <string>

View File

@ -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;
};
}

View File

@ -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>();
}
Scope<ResourceBaseType> baseData = StorageBackend<DataSource>::template load<ResourceBaseType>(storageId);
data = ResourceBuilder<T>::buildResource(*baseData.get());
} else {
data = ResourceBuilder<T>::buildResource(); // No base data
}
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

View File

@ -0,0 +1,7 @@
#pragma once
#include "DeerCore/Scripting.h"
namespace Deer {
namespace Scripting {
}
} // namespace Deer

View File

@ -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

View File

@ -1,2 +1,2 @@
#pragma once
#include "Deer/Tools/Memory.h"
#include "DeerCore/Tools/Memory.h"

View File

@ -1,2 +1,2 @@
#pragma once
#include "Deer/Tools/Path.h"
#include "DeerCore/Tools/Path.h"

View File

@ -1,2 +1,2 @@
#pragma once
#include "Deer/Tools/SmallVector.h"
#include "DeerCore/Tools/SmallVector.h"

View File

@ -1,2 +1,2 @@
#pragma once
#include "Deer/Tools/TypeDefs.h"
#include "DeerCore/Tools/TypeDefs.h"

View File

@ -0,0 +1,2 @@
#pragma once
#include "DeerCore/Universe.h"

94
Deer/Include/DeerRender/Voxel.h Executable file → Normal file
View 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

View File

@ -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]; }
};
}

View File

@ -1,2 +0,0 @@
#pragma once
#include "Deer/VoxelWorld.h"

View File

@ -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) {
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));
}
}

View File

@ -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

View File

@ -1,10 +0,0 @@
#pragma once
#include <cstdint>
namespace Deer {
class Environment;
struct EntitySerializationStruct {
uint16_t entityID;
Environment* env;
};
} // namespace Deer

View File

@ -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

View File

@ -1,4 +0,0 @@
namespace Deer {
bool is_server_serialization = false;
}

View File

@ -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

View File

@ -1,7 +0,0 @@
#include "SerializationGlobalVars.h"
namespace Deer {
bool is_server_serialization = false;
}

View File

@ -1,5 +0,0 @@
#pragma once
namespace Deer {
extern bool is_server_serialization;
}

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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]();
}
}

View File

@ -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;
};
}

View File

@ -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());
}
}
}

View File

@ -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
};
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View 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
View 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

View File

@ -1,6 +1,6 @@
#pragma once
#include "Deer/Tools/Path.h"
#include "DeerCore/Tools/Path.h"
namespace Deer {
struct DataStructure {

View File

@ -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"

View File

@ -1,4 +1,4 @@
#include "Deer/Tools/Path.h"
#include "DeerCore/Tools/Path.h"
#include <algorithm>
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {

View 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

View File

@ -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

View File

@ -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 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::AngelScriptEngine::getAngelScriptReturnCodeString(__r)); \
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); \
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)); \
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \
return; \
} \
}

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -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