Changed internal structure
This commit is contained in:
parent
54f8156b6b
commit
67b316a70b
@ -19,8 +19,11 @@ project "DeerService"
|
|||||||
"vendor/entt/include",
|
"vendor/entt/include",
|
||||||
"vendor/cereal/include",
|
"vendor/cereal/include",
|
||||||
"vendor/angelScript/include",
|
"vendor/angelScript/include",
|
||||||
"vendor/smallVector"
|
"vendor/smallVector",
|
||||||
|
"vendor/enet/include"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
links {"enet"}
|
||||||
|
|
||||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||||
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
||||||
@ -55,4 +58,4 @@ project "DeerService"
|
|||||||
defines { "DIST" }
|
defines { "DIST" }
|
||||||
runtime "Release"
|
runtime "Release"
|
||||||
optimize "On"
|
optimize "On"
|
||||||
symbols "Off"
|
symbols "Off"
|
||||||
|
|||||||
@ -6,8 +6,8 @@ project "Deer"
|
|||||||
staticruntime "off"
|
staticruntime "off"
|
||||||
|
|
||||||
files {
|
files {
|
||||||
"src/Deer/**.h",
|
"src/DeerCore/**.h",
|
||||||
"src/Deer/**.cpp",
|
"src/DeerCore/**.cpp",
|
||||||
"src/DeerRender/**.h",
|
"src/DeerRender/**.h",
|
||||||
"src/DeerRender/**.cpp",
|
"src/DeerRender/**.cpp",
|
||||||
"src/Plattform/OpenGL/**.h",
|
"src/Plattform/OpenGL/**.h",
|
||||||
@ -35,7 +35,8 @@ project "Deer"
|
|||||||
"vendor/cereal/include",
|
"vendor/cereal/include",
|
||||||
"vendor/objload/include/objload",
|
"vendor/objload/include/objload",
|
||||||
"vendor/angelScript/include",
|
"vendor/angelScript/include",
|
||||||
"vendor/smallVector"
|
"vendor/smallVector",
|
||||||
|
"vendor/enet/include"
|
||||||
}
|
}
|
||||||
|
|
||||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||||
@ -81,7 +82,8 @@ project "Deer"
|
|||||||
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
||||||
"gio-2.0", -- GIO library
|
"gio-2.0", -- GIO library
|
||||||
"gobject-2.0", -- GObject library
|
"gobject-2.0", -- GObject library
|
||||||
"pthread" -- POSIX threads library
|
"pthread", -- POSIX threads library
|
||||||
|
"enet"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,4 +111,4 @@ project "Deer"
|
|||||||
defines { "DIST" }
|
defines { "DIST" }
|
||||||
runtime "Release"
|
runtime "Release"
|
||||||
optimize "On"
|
optimize "On"
|
||||||
symbols "Off"
|
symbols "Off"
|
||||||
|
|||||||
@ -1,296 +0,0 @@
|
|||||||
// Structure definition for voxel and voxel manipulation
|
|
||||||
// copyright Copyright (c) 2025 Deer
|
|
||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Deer/Tools/Memory.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/VoxelAspect.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class Texture2D;
|
|
||||||
class Shader;
|
|
||||||
} // namespace Deer
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VOXEL_INFO_TYPE_AIR "air"
|
|
||||||
#define VOXEL_INFO_TYPE_VOXEL "voxel"
|
|
||||||
#define VOXEL_INFO_TYPE_TRANSPARENT_VOXEL "transparentVoxel"
|
|
||||||
#define VOXEL_INFO_TYPE_CUSTOM "custom"
|
|
||||||
|
|
||||||
#define CHUNK_SIZE_X 32
|
|
||||||
#define CHUNK_SIZE_Y 32
|
|
||||||
#define CHUNK_SIZE_Z 32
|
|
||||||
#define CHUNK_SIZE(axis) \
|
|
||||||
((axis == 0) ? CHUNK_SIZE_X : (axis == 1) ? CHUNK_SIZE_Y \
|
|
||||||
: CHUNK_SIZE_Z)
|
|
||||||
|
|
||||||
#define LAYER_VOXELS CHUNK_SIZE_X* CHUNK_SIZE_Z
|
|
||||||
#define CHUNK_VOXELS CHUNK_SIZE_X* CHUNK_SIZE_Y* CHUNK_SIZE_Z
|
|
||||||
|
|
||||||
// TODO: Change this to be a inline function
|
|
||||||
#define VOXEL_POSITION(id) \
|
|
||||||
id.z + id.y* CHUNK_SIZE_Z + id.x* CHUNK_SIZE_Z* CHUNK_SIZE_Y
|
|
||||||
#define LAYER_VOXEL_POSITION(id) id.z + id.x* CHUNK_SIZE_Z
|
|
||||||
|
|
||||||
#define X_AXIS 0
|
|
||||||
#define Y_AXIS 1
|
|
||||||
#define Z_AXIS 2
|
|
||||||
|
|
||||||
// TODO: Change this to be a inline function
|
|
||||||
#define NORMAL_DIR(axis, normal) normalDirs[axis + normal * 3]
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
struct Voxel;
|
|
||||||
struct LayerVoxel;
|
|
||||||
|
|
||||||
extern Voxel nullVoxel;
|
|
||||||
extern Voxel emptyVoxel;
|
|
||||||
extern LayerVoxel nullLayerVoxel;
|
|
||||||
extern int normalDirs[3 * 6];
|
|
||||||
|
|
||||||
enum NormalDirection : uint8_t {
|
|
||||||
NORMAL_LEFT = 0,
|
|
||||||
NORMAL_RIGHT = 1,
|
|
||||||
NORMAL_DOWN = 2,
|
|
||||||
NORMAL_UP = 3,
|
|
||||||
NORMAL_BACK = 4,
|
|
||||||
NORMAL_FRONT = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class VoxelInfoType : uint8_t {
|
|
||||||
Air = 0,
|
|
||||||
Voxel = 1,
|
|
||||||
TransparentVoxel = 2,
|
|
||||||
Custom = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// Defines the general data of a voxel id stored in the array
|
|
||||||
// DataStore::voxelsInfo
|
|
||||||
struct VoxelInfo {
|
|
||||||
std::string name;
|
|
||||||
VoxelInfoType type = VoxelInfoType::Air;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Namespace to load and manage voxel data
|
|
||||||
namespace DataStore {
|
|
||||||
// List of the voxels loaded with loadVoxelsData()
|
|
||||||
extern std::vector<VoxelInfo> voxelsInfo;
|
|
||||||
|
|
||||||
// Loads basic voxel data from folder DEER_VOXEL_DATA_PATH defined in
|
|
||||||
// DataStore.h
|
|
||||||
void loadVoxelsData();
|
|
||||||
void createExampleVoxelData();
|
|
||||||
|
|
||||||
int32_t getVoxelID(const std::string&);
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
// List of the voxels Aspect loaded with loadVoxelsAspect()
|
|
||||||
extern std::vector<VoxelAspect> voxelsAspect;
|
|
||||||
|
|
||||||
// Loads voxel aspect from folder DEER_VOXEL_ASPECT_PATH defined in
|
|
||||||
// DataStore.h
|
|
||||||
void loadVoxelsAspect();
|
|
||||||
void createExampleVoxelAspect();
|
|
||||||
|
|
||||||
// Generates the texture atlas that the voxels demanded from folder
|
|
||||||
// DEER_VOXEL_TEXTURE_PATH defined in DataStore.h Warning : This
|
|
||||||
// function must be called with a render context, otherwise this will
|
|
||||||
// crash
|
|
||||||
void generateTextureAtlas();
|
|
||||||
// Loads the shaders for rendering chunks from folder
|
|
||||||
// DEER_VOXEL_SHADER_PATH defined in DataStore.h
|
|
||||||
void loadVoxelsShaders();
|
|
||||||
|
|
||||||
// Returns with & height of the texture atlas generated
|
|
||||||
// Warning: If you call this before generate Texture Atlas the return
|
|
||||||
// value will be 0
|
|
||||||
int getVoxelTextureAtlasSize();
|
|
||||||
// Texture atlas created with generateTextureAtlas() call
|
|
||||||
// Warning: You must have called generateTextureAtlas() in order to work
|
|
||||||
/// Ref<Texture2D>& getVoxelColorTextureAtlas();
|
|
||||||
// Returns the shader created with loadVoxelsShaders()
|
|
||||||
// Warning: You must have called loadVoxelsShaders() in order to work
|
|
||||||
/// Ref<Shader>& getSolidVoxelShader();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
} // namespace DataStore
|
|
||||||
|
|
||||||
// Structure to define what a voxel inside a world must have
|
|
||||||
struct Voxel {
|
|
||||||
// Reference to the voxel id
|
|
||||||
uint16_t id = 0;
|
|
||||||
|
|
||||||
Voxel() = default;
|
|
||||||
Voxel(uint16_t _id) : id(_id) {}
|
|
||||||
|
|
||||||
inline bool operator==(const Voxel& b) const { return id == b.id; }
|
|
||||||
inline bool isVoxelType() const {
|
|
||||||
return DataStore::voxelsInfo[id].type == VoxelInfoType::Voxel;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Structure to define the general cordinates of a voxel in the world
|
|
||||||
struct VoxelCordinates {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
int32_t x, y, z;
|
|
||||||
};
|
|
||||||
std::array<int32_t, 3> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
VoxelCordinates(int32_t _x = 0, int32_t _y = 0, int32_t _z = 0)
|
|
||||||
: x(_x), y(_y), z(_z) {}
|
|
||||||
|
|
||||||
inline int32_t& operator[](int id) { return data[id]; }
|
|
||||||
inline bool operator==(const VoxelCordinates& b) const {
|
|
||||||
return x == b.x && y == b.y && z == b.z;
|
|
||||||
}
|
|
||||||
inline bool isNull() const { return x < 0 || y < 0 || z < 0; }
|
|
||||||
inline void makeNull() { x = -1; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Stucture that defines the info of a layer voxel
|
|
||||||
struct LayerVoxel {
|
|
||||||
uint16_t height = 0;
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
uint16_t ambient_light_height = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LayerVoxel() = default;
|
|
||||||
LayerVoxel(uint16_t _height) : height(_height) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returning info of a raycast
|
|
||||||
struct VoxelRayResult {
|
|
||||||
float distance = 0;
|
|
||||||
VoxelCordinates hitPos;
|
|
||||||
uint8_t face = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Coordinates of a chunk
|
|
||||||
struct ChunkID {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint16_t x;
|
|
||||||
uint16_t y;
|
|
||||||
uint16_t z;
|
|
||||||
};
|
|
||||||
std::array<uint16_t, 3> axis;
|
|
||||||
};
|
|
||||||
|
|
||||||
ChunkID(uint16_t _x = 0, uint16_t _y = 0, uint16_t _z = 0)
|
|
||||||
: x(_x), y(_y), z(_z) {}
|
|
||||||
|
|
||||||
inline bool operator==(const ChunkID& b) const {
|
|
||||||
return x == b.x && y == b.y && z == b.z;
|
|
||||||
}
|
|
||||||
inline uint16_t& operator[](size_t i) { return axis[i]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ChunkIDHash {
|
|
||||||
size_t operator()(const ChunkID& chunk) const {
|
|
||||||
size_t h1 = std::hash<uint16_t>{}(chunk.x);
|
|
||||||
size_t h2 = std::hash<uint16_t>{}(chunk.y);
|
|
||||||
size_t h3 = std::hash<uint16_t>{}(chunk.z);
|
|
||||||
|
|
||||||
size_t result = h1;
|
|
||||||
result = result * 31 + h2;
|
|
||||||
result = result * 31 + h3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cordinates of a Layer
|
|
||||||
struct LayerID {
|
|
||||||
uint16_t x = 0;
|
|
||||||
uint16_t z = 0;
|
|
||||||
|
|
||||||
LayerID() = default;
|
|
||||||
LayerID(uint16_t _x, uint16_t _z) : x(_x), z(_z) {}
|
|
||||||
inline bool operator==(const LayerID& b) const {
|
|
||||||
return x == b.x && z == b.z;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Coordinates of a layer voxel relative to the Layer Chunk
|
|
||||||
struct LayerVoxelID {
|
|
||||||
uint8_t x = 0;
|
|
||||||
uint8_t z = 0;
|
|
||||||
|
|
||||||
LayerVoxelID() = default;
|
|
||||||
LayerVoxelID(uint8_t _x, uint8_t _z = 0) : x(_x), z(_z) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Coordinates of a voxel inside a Chunk
|
|
||||||
struct ChunkVoxelID {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t x;
|
|
||||||
uint8_t y;
|
|
||||||
uint8_t z;
|
|
||||||
};
|
|
||||||
std::array<uint8_t, 3> axis;
|
|
||||||
};
|
|
||||||
|
|
||||||
ChunkVoxelID(uint8_t _x = 0, uint8_t _y = 0, uint8_t _z = 0)
|
|
||||||
: x(_x), y(_y), z(_z) {}
|
|
||||||
inline uint8_t& operator[](size_t i) { return axis[i]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extracts the chunk coordinaes and the chunk voxel coordinates from a
|
|
||||||
// world position
|
|
||||||
inline void extractChunkCordinates(uint32_t x, uint32_t y, uint32_t z,
|
|
||||||
ChunkID& _chunkID,
|
|
||||||
ChunkVoxelID& _chunkVoxelID) {
|
|
||||||
uint16_t posX = x;
|
|
||||||
uint16_t posY = y;
|
|
||||||
uint16_t posZ = z;
|
|
||||||
|
|
||||||
_chunkID.x = posX >> 5;
|
|
||||||
_chunkID.y = posY >> 5;
|
|
||||||
_chunkID.z = posZ >> 5;
|
|
||||||
|
|
||||||
_chunkVoxelID.x = posX & 31;
|
|
||||||
_chunkVoxelID.y = posY & 31;
|
|
||||||
_chunkVoxelID.z = posZ & 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the chunk coordinaes and the chunk voxel chunk coordinates from
|
|
||||||
// a world position
|
|
||||||
inline void extractChunkCordinates(VoxelCordinates coords,
|
|
||||||
ChunkID& _chunkID,
|
|
||||||
ChunkVoxelID& _chunkVoxelID) {
|
|
||||||
uint16_t posX = coords.x;
|
|
||||||
uint16_t posY = coords.y;
|
|
||||||
uint16_t posZ = coords.z;
|
|
||||||
|
|
||||||
_chunkID.x = posX >> 5;
|
|
||||||
_chunkID.y = posY >> 5;
|
|
||||||
_chunkID.z = posZ >> 5;
|
|
||||||
|
|
||||||
_chunkVoxelID.x = posX & 31;
|
|
||||||
_chunkVoxelID.y = posY & 31;
|
|
||||||
_chunkVoxelID.z = posZ & 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the layer chunk coordinaes and the layer chunk voxel coordinates
|
|
||||||
// from a world position
|
|
||||||
inline void extractLayerCordinates(uint32_t x, uint32_t z,
|
|
||||||
LayerID& _layerID,
|
|
||||||
LayerVoxelID& _layerVoxelID) {
|
|
||||||
uint16_t posX = x;
|
|
||||||
uint16_t posZ = z;
|
|
||||||
|
|
||||||
_layerID.x = posX >> 5;
|
|
||||||
_layerID.z = posZ >> 5;
|
|
||||||
|
|
||||||
_layerVoxelID.x = posX & 31;
|
|
||||||
_layerVoxelID.z = posZ & 31;
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,209 +0,0 @@
|
|||||||
// copyright Copyright (c) 2025 Deer
|
|
||||||
#pragma once
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "Deer/Tools/Memory.h"
|
|
||||||
#include "Deer/Voxel.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class Chunk;
|
|
||||||
class Layer;
|
|
||||||
struct SceneCamera;
|
|
||||||
struct VoxelWorldProps;
|
|
||||||
struct VoxelWorldRenderData;
|
|
||||||
|
|
||||||
// Properties of a Voxel World
|
|
||||||
struct VoxelWorldProps {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t chunkSizeX;
|
|
||||||
uint8_t chunkSizeY;
|
|
||||||
uint8_t chunkSizeZ;
|
|
||||||
};
|
|
||||||
std::array<uint8_t, 3> axis;
|
|
||||||
};
|
|
||||||
|
|
||||||
VoxelWorldProps() = default;
|
|
||||||
VoxelWorldProps(uint8_t _chunkSizeX, uint8_t _chunkSizeY,
|
|
||||||
uint8_t _chunkSizeZ)
|
|
||||||
: chunkSizeX(_chunkSizeX),
|
|
||||||
chunkSizeY(_chunkSizeY),
|
|
||||||
chunkSizeZ(_chunkSizeZ) {}
|
|
||||||
|
|
||||||
inline uint8_t& operator[](size_t i) { return axis[i]; }
|
|
||||||
|
|
||||||
// Returns the count of chunks
|
|
||||||
inline int getChunkCount() const {
|
|
||||||
return chunkSizeX * chunkSizeY * chunkSizeZ;
|
|
||||||
}
|
|
||||||
// Returns the count of layers
|
|
||||||
inline int getLayerCount() const { return chunkSizeX * chunkSizeZ; }
|
|
||||||
// Returns the internal id of a chunk relative to a Voxel World Props
|
|
||||||
// from a chunk id
|
|
||||||
inline int getWorldChunkID(ChunkID chunkID) const {
|
|
||||||
return chunkID.z + chunkID.y * chunkSizeZ +
|
|
||||||
chunkID.x * chunkSizeZ * chunkSizeY;
|
|
||||||
}
|
|
||||||
// Returns the internal id of a layer relative to a Voxel World Props
|
|
||||||
// from a Layer id
|
|
||||||
inline int getWorldLayerID(LayerID layerID) const {
|
|
||||||
return layerID.z + layerID.x * chunkSizeZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the LayerID from a internal Layer id relative to Voxel World
|
|
||||||
// Props
|
|
||||||
inline LayerID getLayerID(int id) const {
|
|
||||||
LayerID l_id;
|
|
||||||
|
|
||||||
l_id.x = id / chunkSizeZ;
|
|
||||||
id -= l_id.x * chunkSizeZ;
|
|
||||||
|
|
||||||
l_id.z = id;
|
|
||||||
return l_id;
|
|
||||||
}
|
|
||||||
// Extracts the ChunkID from a internal Chunk id relative to Voxel World
|
|
||||||
// Props
|
|
||||||
inline ChunkID getChunkID(int id) const {
|
|
||||||
ChunkID c_id;
|
|
||||||
|
|
||||||
c_id.x = id / (chunkSizeZ * chunkSizeY);
|
|
||||||
id -= c_id.x * (chunkSizeZ * chunkSizeY);
|
|
||||||
|
|
||||||
c_id.y = id / chunkSizeZ;
|
|
||||||
id -= c_id.y * chunkSizeZ;
|
|
||||||
|
|
||||||
c_id.z = id;
|
|
||||||
return c_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the Chunk id is inside the voxel World bounds
|
|
||||||
inline bool isValid(ChunkID chunkID) const {
|
|
||||||
return chunkID.x >= 0 && chunkID.x < chunkSizeX && chunkID.y >= 0 &&
|
|
||||||
chunkID.y < chunkSizeY && chunkID.z >= 0 &&
|
|
||||||
chunkID.z < chunkSizeZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the Layer id is inside the voxel World bounds
|
|
||||||
inline bool isValid(LayerID layerID) const {
|
|
||||||
return layerID.x >= 0 && layerID.x < chunkSizeX && layerID.z >= 0 &&
|
|
||||||
layerID.z < chunkSizeZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the max amount of voxels in the Voxel World Props
|
|
||||||
inline int getMaxVoxelCount() const {
|
|
||||||
return getChunkCount() * CHUNK_VOXELS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clamps the coordinates of a Voxel World Coordinates to be inside the
|
|
||||||
// voxel world props
|
|
||||||
inline void clampCordinates(VoxelCordinates& coords) const {
|
|
||||||
if (coords.x < 0)
|
|
||||||
coords.x = 0;
|
|
||||||
else if (coords.x >= chunkSizeX * CHUNK_SIZE_X)
|
|
||||||
coords.x = chunkSizeX * CHUNK_SIZE_X - 1;
|
|
||||||
|
|
||||||
if (coords.y < 0)
|
|
||||||
coords.y = 0;
|
|
||||||
else if (coords.y >= chunkSizeY * CHUNK_SIZE_Y)
|
|
||||||
coords.y = chunkSizeY * CHUNK_SIZE_Y - 1;
|
|
||||||
|
|
||||||
if (coords.z < 0)
|
|
||||||
coords.z = 0;
|
|
||||||
else if (coords.z >= chunkSizeZ * CHUNK_SIZE_Z)
|
|
||||||
coords.z = chunkSizeZ * CHUNK_SIZE_Z - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes 2 Voxel coordinates and outputs them in the same variables
|
|
||||||
// being the min with the min values and the max with the max This is
|
|
||||||
// useful for loops
|
|
||||||
inline void clampAndSetMinMax(VoxelCordinates& min,
|
|
||||||
VoxelCordinates& max) const {
|
|
||||||
VoxelCordinates a_cache = min;
|
|
||||||
VoxelCordinates b_cache = max;
|
|
||||||
|
|
||||||
for (int x = 0; x < 3; x++) {
|
|
||||||
if (a_cache[x] > b_cache[x]) {
|
|
||||||
max[x] = a_cache[x];
|
|
||||||
min[x] = b_cache[x];
|
|
||||||
} else {
|
|
||||||
min[x] = a_cache[x];
|
|
||||||
max[x] = b_cache[x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clampCordinates(min);
|
|
||||||
clampCordinates(max);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Class to manage the voxels
|
|
||||||
namespace VoxelWorld {
|
|
||||||
void initialize(const VoxelWorldProps&);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
// Returns the voxel in a voxel coordinates
|
|
||||||
Voxel readVoxel(VoxelCordinates);
|
|
||||||
// Sets the voxel in the coordinates to the value
|
|
||||||
void setVoxel(VoxelCordinates, Voxel value);
|
|
||||||
|
|
||||||
// Fills a space with the voxel value inside the 2 coordinates
|
|
||||||
// Note that you don't have to give then ordeered by min and max
|
|
||||||
void fillVoxels(VoxelCordinates, VoxelCordinates, Voxel value);
|
|
||||||
// Remplaces the ref voxel with the value of a space inside the 2 coordinates
|
|
||||||
// Note that you don't have to give then ordeered by min and max
|
|
||||||
void remplaceVoxels(VoxelCordinates, VoxelCordinates, Voxel ref, Voxel value);
|
|
||||||
|
|
||||||
// Returns the layer data of a woorld coordinates
|
|
||||||
// Note out of bounds will return a default Layer Voxel
|
|
||||||
LayerVoxel readLayerVoxel(int x, int z);
|
|
||||||
// Calculates the max height of a layer in a space
|
|
||||||
// Note out of bounds will return a 0 of height
|
|
||||||
// Tip: this will calculate, you should use the cached height in a layer voxel
|
|
||||||
uint16_t calculateLayerVoxelHeight(int x, int z);
|
|
||||||
|
|
||||||
// Raycast a ray from a source and dir
|
|
||||||
VoxelRayResult rayCast(glm::vec3 position, glm::vec3 dir,
|
|
||||||
float maxDistance = 10.0f);
|
|
||||||
// Raycast a ray from a source and dir ignoring if the ray stats inside a voxel
|
|
||||||
VoxelRayResult rayCast_editor(glm::vec3 position, glm::vec3 dir,
|
|
||||||
float maxDistance = 10.0f);
|
|
||||||
|
|
||||||
bool isInitialized();
|
|
||||||
|
|
||||||
// Returns the voxel world props used in the voxel world
|
|
||||||
// Note that you can't change the world size unless you create a new Voxel World
|
|
||||||
const VoxelWorldProps& getWorldProps();
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
// Renders the current voxel world with a specified scene camera
|
|
||||||
void render(const SceneCamera&);
|
|
||||||
// Generates the next chunk mesh
|
|
||||||
void bakeNextChunk();
|
|
||||||
|
|
||||||
// Light data
|
|
||||||
VoxelLight readLight(VoxelCordinates);
|
|
||||||
VoxelLight& modLight(VoxelCordinates);
|
|
||||||
|
|
||||||
// Chunk vertex creation
|
|
||||||
void genSolidVoxel(ChunkID chunkID, ChunkVoxelID chunkVoxelID);
|
|
||||||
|
|
||||||
// --- Light propagation ---
|
|
||||||
// Warning: This function is private and needs to have min and max
|
|
||||||
// clamped and in order
|
|
||||||
void bakeVoxelLight(VoxelCordinates min, VoxelCordinates max);
|
|
||||||
void bakeVoxelLightFromPoint(VoxelCordinates);
|
|
||||||
void bakeAmbientLight(int minX, int maxX, int minZ, int maxZ);
|
|
||||||
void bakeAmbientLightFromPoint(int x, int z);
|
|
||||||
|
|
||||||
void resolveNextAmbientLightPropagation();
|
|
||||||
void resolveNextVoxelLightPropagation();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LayerVoxel& modLayerVoxel(int x, int z);
|
|
||||||
} // namespace VoxelWorld
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class ImGuiLayer;
|
class ImGuiLayer;
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
#include "Deer/Tools/SmallVector.h"
|
#include "DeerCore/Tools/SmallVector.h"
|
||||||
|
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
#include "glm/gtc/quaternion.hpp"
|
#include "glm/gtc/quaternion.hpp"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
#include "Deer/Tools/TypeDefs.h"
|
#include "DeerCore/Tools/TypeDefs.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -3,7 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
#define DEER_RESOURCE_PATH "Assets"
|
#define DEER_RESOURCE_PATH "Assets"
|
||||||
|
|
||||||
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Resource.h"
|
||||||
#include "Deer/Resource.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
#include "entt/entt.hpp"
|
#include "entt/entt.hpp"
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ namespace Deer {
|
|||||||
// Obtains the entity that is on the root of the environment
|
// Obtains the entity that is on the root of the environment
|
||||||
inline Entity& getRoot() { return getEntity(0); }
|
inline Entity& getRoot() { return getEntity(0); }
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
void render(SceneCamera& camera);
|
void render(const SceneCamera& camera);
|
||||||
#endif
|
#endif
|
||||||
Scope<entt::registry> m_registry;
|
Scope<entt::registry> m_registry;
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
35
Deer/Include/DeerCore/Network.h
Normal file
35
Deer/Include/DeerCore/Network.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
#include "DeerCore/Tools/TypeDefs.h"
|
||||||
|
|
||||||
|
typedef struct _ENetPeer ENetPeer;
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Network {
|
||||||
|
struct ServerSettings;
|
||||||
|
struct DeerClient;
|
||||||
|
|
||||||
|
void initServer(const ServerSettings&);
|
||||||
|
void shutdownServer();
|
||||||
|
|
||||||
|
void flushServerEvents();
|
||||||
|
|
||||||
|
enum class DeerClientState : int {
|
||||||
|
NotConnected = 0,
|
||||||
|
Connected = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DeerClient {
|
||||||
|
DeerClientState clientState = DeerClientState::NotConnected;
|
||||||
|
ENetPeer* internalPeer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerSettings {
|
||||||
|
uint32_t port = 500;
|
||||||
|
uint32_t maxClients = 32;
|
||||||
|
uint32_t maxOutgoingBand = 0;
|
||||||
|
uint32_t maxIncomingBand = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Network
|
||||||
|
} // namespace Deer
|
||||||
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/DataManagment.h"
|
#include "DeerCore/DataManagment.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
#include "Deer/Tools/TypeDefs.h"
|
#include "DeerCore/Tools/TypeDefs.h"
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -94,7 +94,7 @@ namespace Deer {
|
|||||||
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, const std::string& storageId) {
|
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, const std::string& storageId) {
|
||||||
if (resourceCache.contains(storageId))
|
if (resourceCache.contains(storageId))
|
||||||
return resourceCache[storageId];
|
return resourceCache[storageId];
|
||||||
|
|
||||||
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
||||||
|
|
||||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||||
@ -1,19 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/DataStore.h"
|
#include "DeerCore/Tools/TypeDefs.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 {
|
namespace Deer {
|
||||||
class Environment;
|
class Environment;
|
||||||
|
class SceneCamera;
|
||||||
class GizmoRenderer;
|
class GizmoRenderer;
|
||||||
|
|
||||||
// A scene is a 3d simulation with its environment and voxel world in case
|
// A scene is a 3d simulation with its environment and voxel world in case
|
||||||
@ -33,19 +23,10 @@ namespace Deer {
|
|||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
// This function renders with the default camera in the environment
|
// This function renders with the default camera in the environment
|
||||||
void render();
|
void render();
|
||||||
void render(SceneCamera);
|
void render(const SceneCamera&);
|
||||||
|
|
||||||
extern GizmoRenderer gizmoRenderer;
|
extern GizmoRenderer gizmoRenderer;
|
||||||
#endif
|
#endif
|
||||||
extern Environment environment;
|
extern Environment environment;
|
||||||
} // namespace Scene
|
} // 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
|
} // namespace Deer
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Deer/Application.h"
|
#include "DeerCore/Application.h"
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
#include "DeerRender/Events/ApplicationEvent.h"
|
#include "DeerRender/Events/ApplicationEvent.h"
|
||||||
@ -7,8 +7,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
namespace Application {
|
namespace Application {
|
||||||
using EventFunction = void(*)(Event&);
|
using EventFunction = void (*)(Event&);
|
||||||
|
|
||||||
void initWindow();
|
void initWindow();
|
||||||
void shutdownWindow();
|
void shutdownWindow();
|
||||||
@ -17,5 +17,5 @@ namespace Deer {
|
|||||||
void setEventCallback(EventFunction);
|
void setEventCallback(EventFunction);
|
||||||
|
|
||||||
Window& getWindow();
|
Window& getWindow();
|
||||||
}
|
} // namespace Application
|
||||||
}
|
} // namespace Deer
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
|
|
||||||
#include "DeerRender/Mesh.h"
|
#include "DeerRender/Mesh.h"
|
||||||
#include "DeerRender/Shader.h"
|
#include "DeerRender/Shader.h"
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/DataManagment.h"
|
#include "DeerCore/DataManagment.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/DataStore.h"
|
#include "DeerCore/DataStore.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
@ -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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,14 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Application.h"
|
#include "DeerCore/Application.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
static bool isKeyPressed(unsigned int key);
|
static bool isKeyPressed(unsigned int key);
|
||||||
static bool isMouseButtonPressed(int button);
|
static bool isMouseButtonPressed(int button);
|
||||||
static void getMousePos(float& x, float& y);
|
static void getMousePos(float& x, float& y);
|
||||||
};
|
};
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
|
|
||||||
// From GLFW
|
// From GLFW
|
||||||
#define DEER_KEY_SPACE 32
|
#define DEER_KEY_SPACE 32
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
enum class TextureBufferType {
|
enum class TextureBufferType {
|
||||||
@ -15,15 +15,15 @@ namespace Deer {
|
|||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
unsigned int samples;
|
unsigned int samples;
|
||||||
std::vector<TextureBufferType> frameBufferTextures;
|
std::vector<TextureBufferType> frameBufferTextures;
|
||||||
|
|
||||||
bool swapChainTarget = false;
|
bool swapChainTarget = false;
|
||||||
FrameBufferSpecification(unsigned int _width, unsigned int _height, std::initializer_list<TextureBufferType> _frameBufferTextures, unsigned int _samples = 1, bool _swapChainTarget = false)
|
FrameBufferSpecification(unsigned int _width, unsigned int _height, std::initializer_list<TextureBufferType> _frameBufferTextures, unsigned int _samples = 1, bool _swapChainTarget = false)
|
||||||
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameBuffer {
|
class FrameBuffer {
|
||||||
public:
|
public:
|
||||||
virtual ~FrameBuffer() = default;
|
virtual ~FrameBuffer() = default;
|
||||||
virtual const FrameBufferSpecification& getSpecification() = 0;
|
virtual const FrameBufferSpecification& getSpecification() = 0;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ namespace Deer {
|
|||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
virtual void resize(unsigned int width, unsigned int height) = 0;
|
virtual void resize(unsigned int width, unsigned int height) = 0;
|
||||||
|
|
||||||
virtual unsigned int getTextureBufferID(int id = 0) = 0;
|
virtual unsigned int getTextureBufferID(int id = 0) = 0;
|
||||||
virtual void clearBuffer(unsigned int bufferId, void* data) = 0;
|
virtual void clearBuffer(unsigned int bufferId, void* data) = 0;
|
||||||
|
|
||||||
@ -40,5 +40,4 @@ namespace Deer {
|
|||||||
|
|
||||||
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
||||||
};
|
};
|
||||||
}
|
} // namespace Deer
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Resource.h"
|
#include "DeerCore/Resource.h"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Scene.h"
|
#include "DeerCore/Scene.h"
|
||||||
#include "DeerRender/Components.h"
|
#include "DeerRender/Components.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
#include "DeerRender/Render/Shader.h"
|
#include "DeerRender/Render/Shader.h"
|
||||||
#include "DeerRender/Resource.h"
|
#include "DeerRender/Resource.h"
|
||||||
|
|
||||||
@ -22,6 +22,11 @@ namespace Deer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace RenderUtils {
|
||||||
|
void initializeRenderUtils();
|
||||||
|
void deinitializeRenderUtils();
|
||||||
|
} // namespace RenderUtils
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class ResourceBuilder<Shader> {
|
class ResourceBuilder<Shader> {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/SmallVector.h"
|
#include "DeerCore/Tools/SmallVector.h"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/TypeDefs.h"
|
#include "DeerCore/Tools/TypeDefs.h"
|
||||||
@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/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
|
|
||||||
|
|
||||||
#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]
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
struct VoxelLight;
|
|
||||||
extern VoxelLight lightVoxel;
|
|
||||||
|
|
||||||
extern int lightPropagationComplexDir[12 * 2];
|
|
||||||
extern int normalFacePositions[3 * 4 * 6];
|
|
||||||
extern int uvFace[2 * 4];
|
|
||||||
// 6 Dirs * 4 vertices * 2 checks * 3 dirs
|
|
||||||
extern int ambientOcclusionVertex[6 * 4 * 2 * 3];
|
|
||||||
extern int layerCheckDirections[2 * 8];
|
|
||||||
|
|
||||||
struct VoxelLight {
|
|
||||||
uint8_t r_light;
|
|
||||||
uint8_t g_light;
|
|
||||||
uint8_t b_light;
|
|
||||||
uint8_t ambient_light;
|
|
||||||
|
|
||||||
VoxelLight(uint8_t _ambient_light = 0) : r_light(0), g_light(0), b_light(0), ambient_light(_ambient_light) {}
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file VoxelAspect.h
|
|
||||||
* @author chewico@frostdeer.com
|
|
||||||
* @brief File to save the voxel aspect data
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2025
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include "Deer/Voxel.h"
|
|
||||||
|
|
||||||
// TEMP
|
|
||||||
#define VOXEL_TEXTURE_SIZE_X 128
|
|
||||||
#define VOXEL_TEXTURE_SIZE_Y 128
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
struct VoxelTextureFaceDefinition {
|
|
||||||
std::string textureFaces[6];
|
|
||||||
|
|
||||||
inline std::string& operator[](size_t index) {
|
|
||||||
return textureFaces[index];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VoxelColorEmission {
|
|
||||||
uint8_t r_value = 0;
|
|
||||||
uint8_t g_value = 0;
|
|
||||||
uint8_t b_value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VoxelAspectDefinition {
|
|
||||||
std::string voxelName;
|
|
||||||
VoxelTextureFaceDefinition textureFaces;
|
|
||||||
VoxelColorEmission colorEmission;
|
|
||||||
|
|
||||||
VoxelAspectDefinition() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VoxelAspect {
|
|
||||||
VoxelAspectDefinition definition;
|
|
||||||
uint16_t textureFacesIDs[6]{};
|
|
||||||
|
|
||||||
inline bool isLightSource() {
|
|
||||||
return definition.colorEmission.r_value || definition.colorEmission.g_value || definition.colorEmission.b_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the texture id for the voxel face
|
|
||||||
*
|
|
||||||
* @param face face of the texture defined in the enum NormalDirection of Voxel.h
|
|
||||||
* @return uint16_t texture id in the texture atlas
|
|
||||||
*/
|
|
||||||
inline uint16_t getTextureID(uint8_t face) { return textureFacesIDs[face]; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/VoxelWorld.h"
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
#include "DeerRender/Events/Event.h"
|
#include "DeerRender/Events/Event.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
#include "Deer/Application.h"
|
|
||||||
#include <functional>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Application {
|
|
||||||
// Implemented in DeerRender/Application
|
|
||||||
void runRender(float deltaTime);
|
|
||||||
void resolveEvents();
|
|
||||||
|
|
||||||
Function tickCallback;
|
|
||||||
bool running;
|
|
||||||
|
|
||||||
const double targetUpdateTime = 1.0 / 60.0; // Fixed 60 FPS update
|
|
||||||
double targetRenderTime = 1.0 / 160.0; // User-defined render FPS
|
|
||||||
|
|
||||||
void setTickCallback(Function _tick) {
|
|
||||||
tickCallback = _tick;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run() {
|
|
||||||
running = true;
|
|
||||||
|
|
||||||
auto previousTime = std::chrono::high_resolution_clock::now();
|
|
||||||
double accumulatedUpdateTime = 0.0;
|
|
||||||
double accumulatedRenderTime = 0.0;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
// Time handling
|
|
||||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
|
||||||
std::chrono::duration<double> deltaTime = currentTime - previousTime;
|
|
||||||
previousTime = currentTime;
|
|
||||||
|
|
||||||
accumulatedUpdateTime += deltaTime.count();
|
|
||||||
accumulatedRenderTime += deltaTime.count();
|
|
||||||
|
|
||||||
// Fixed Update loop (60 FPS)
|
|
||||||
while (accumulatedUpdateTime >= targetUpdateTime) {
|
|
||||||
Timestep timestep = (float)targetUpdateTime;
|
|
||||||
accumulatedUpdateTime -= targetUpdateTime;
|
|
||||||
|
|
||||||
if (tickCallback)
|
|
||||||
tickCallback();
|
|
||||||
|
|
||||||
}
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
if (accumulatedRenderTime >= targetRenderTime) {
|
|
||||||
runRender((float)targetRenderTime);
|
|
||||||
accumulatedRenderTime -= targetRenderTime;
|
|
||||||
}
|
|
||||||
resolveEvents();
|
|
||||||
#endif
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void shutdown() {
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
#include "Deer/Components.h"
|
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
|
||||||
#include "Deer/Log.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
glm::mat4 TransformComponent::getMatrix() const{
|
|
||||||
glm::mat4 scaleMat = glm::scale(glm::mat4(1.0f), scale);
|
|
||||||
glm::mat4 roatationMat = glm::mat4(rotation);
|
|
||||||
glm::mat4 positionMat = glm::translate(glm::mat4(1.0f), position);
|
|
||||||
|
|
||||||
return positionMat * roatationMat * scaleMat;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#include "Deer/Enviroment.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
Scope<Environment> ResourceBuilder<Environment>::buildResource(const BaseDataType& baseData) {
|
|
||||||
Scope<Environment> env = MakeScope<Environment>();
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#include "Deer/Enviroment.h"
|
|
||||||
#include "Deer/Tools/Memory.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/GizmoRenderer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace Scene {
|
|
||||||
Environment environment;
|
|
||||||
bool isExecuting = false;
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
GizmoRenderer gizmoRenderer;
|
|
||||||
#endif
|
|
||||||
} // namespace Scene
|
|
||||||
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/Components.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
|
|
||||||
// TRANSFORM COMPONENT
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive& archive,
|
|
||||||
TransformComponent& transform) {
|
|
||||||
|
|
||||||
archive(cereal::make_nvp("position", transform.position));
|
|
||||||
archive(cereal::make_nvp("scale", transform.scale));
|
|
||||||
archive(cereal::make_nvp("rotation", transform.rotation));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
#include "Chunk.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
Chunk::~Chunk() {
|
|
||||||
if (m_voxels) {
|
|
||||||
delete[] m_voxels;
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
delete[] m_lightInfo;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::loadVoxels() {
|
|
||||||
if (!m_voxels) {
|
|
||||||
m_voxels = new Voxel[CHUNK_VOXELS]();
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
m_lightInfo = new VoxelLight[CHUNK_VOXELS]();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/Voxel.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#include "DeerRender/VoxelAspect.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class Chunk {
|
|
||||||
public:
|
|
||||||
Chunk() = default;
|
|
||||||
~Chunk();
|
|
||||||
|
|
||||||
inline Voxel readVoxel(ChunkVoxelID id) {
|
|
||||||
if (m_voxels)
|
|
||||||
return m_voxels[VOXEL_POSITION(id)];
|
|
||||||
return emptyVoxel;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Voxel& modVoxel(ChunkVoxelID id) {
|
|
||||||
if (!m_voxels)
|
|
||||||
loadVoxels();
|
|
||||||
return m_voxels[VOXEL_POSITION(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void fillVoxels(ChunkVoxelID min, ChunkVoxelID max, Voxel info) {
|
|
||||||
if (!m_voxels)
|
|
||||||
loadVoxels();
|
|
||||||
|
|
||||||
ChunkVoxelID voxelID;
|
|
||||||
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
|
||||||
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
|
||||||
for (voxelID.z = min.z; voxelID.z <= max.x; voxelID.z++) {
|
|
||||||
m_voxels[VOXEL_POSITION(voxelID)] = info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void remplaceVoxels(ChunkVoxelID min, ChunkVoxelID max,
|
|
||||||
Voxel ref, Voxel value) {
|
|
||||||
if (!m_voxels)
|
|
||||||
loadVoxels();
|
|
||||||
|
|
||||||
ChunkVoxelID voxelID;
|
|
||||||
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
|
||||||
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
|
||||||
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
|
||||||
Voxel& currentVoxel = m_voxels[VOXEL_POSITION(voxelID)];
|
|
||||||
|
|
||||||
if (currentVoxel.id == ref.id)
|
|
||||||
currentVoxel = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t calculateLayerVoxelHeight(LayerVoxelID layerVoxelID) {
|
|
||||||
if (!m_voxels)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ChunkVoxelID voxelID(layerVoxelID.x, CHUNK_SIZE_Y - 1,
|
|
||||||
layerVoxelID.z);
|
|
||||||
for (int y = CHUNK_SIZE_Y - 1; y >= 0; y--) {
|
|
||||||
voxelID.y = y;
|
|
||||||
|
|
||||||
if (m_voxels[VOXEL_POSITION(voxelID)].id != 0)
|
|
||||||
return voxelID.y + 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Voxel* m_voxels = nullptr;
|
|
||||||
|
|
||||||
void loadVoxels();
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
public:
|
|
||||||
inline VoxelLight readLight(ChunkVoxelID id) {
|
|
||||||
if (m_voxels)
|
|
||||||
return m_lightInfo[VOXEL_POSITION(id)];
|
|
||||||
return VoxelLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline VoxelLight& modLight(ChunkVoxelID id) {
|
|
||||||
if (!m_voxels)
|
|
||||||
loadVoxels();
|
|
||||||
return m_lightInfo[VOXEL_POSITION(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void clearVoxelLight(ChunkVoxelID min, ChunkVoxelID max) {
|
|
||||||
ChunkVoxelID voxelID;
|
|
||||||
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
|
||||||
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
|
||||||
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].b_light = 0;
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].r_light = 0;
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].g_light = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is the same as clear Voxel Light but it also checks if
|
|
||||||
// there is a source of light
|
|
||||||
inline void clearVoxelLightAndSaveSources(
|
|
||||||
ChunkVoxelID min, ChunkVoxelID max, ChunkID chunkID,
|
|
||||||
std::vector<VoxelCordinates>& sources) {
|
|
||||||
if (!m_voxels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ChunkVoxelID voxelID;
|
|
||||||
for (voxelID.x = min.x; voxelID.x <= max.x; voxelID.x++) {
|
|
||||||
for (voxelID.y = min.y; voxelID.y <= max.y; voxelID.y++) {
|
|
||||||
for (voxelID.z = min.z; voxelID.z <= max.z; voxelID.z++) {
|
|
||||||
Voxel voxel = m_voxels[VOXEL_POSITION(voxelID)];
|
|
||||||
VoxelAspect& voxelAspect =
|
|
||||||
DataStore::voxelsAspect[voxel.id];
|
|
||||||
if (voxelAspect.isLightSource()) {
|
|
||||||
sources.push_back(VoxelCordinates(
|
|
||||||
voxelID.x + chunkID.x * CHUNK_SIZE_X,
|
|
||||||
voxelID.y + chunkID.y * CHUNK_SIZE_Y,
|
|
||||||
voxelID.z + chunkID.z * CHUNK_SIZE_Z));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].b_light = 0;
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].r_light = 0;
|
|
||||||
m_lightInfo[VOXEL_POSITION(voxelID)].g_light = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
VoxelLight* m_lightInfo = nullptr;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#include "Layer.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
Layer::~Layer() {
|
|
||||||
if (m_layerInfo)
|
|
||||||
delete[] m_layerInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Layer::loadData() {
|
|
||||||
m_layerInfo = new LayerVoxel[LAYER_VOXELS]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/Voxel.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class Layer {
|
|
||||||
public:
|
|
||||||
Layer() = default;
|
|
||||||
~Layer();
|
|
||||||
|
|
||||||
inline LayerVoxel readLayerVoxel(LayerVoxelID id) {
|
|
||||||
if (!m_layerInfo)
|
|
||||||
return LayerVoxel();
|
|
||||||
return m_layerInfo[LAYER_VOXEL_POSITION(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline LayerVoxel& modLayerVoxel(LayerVoxelID id) {
|
|
||||||
if (!m_layerInfo)
|
|
||||||
loadData();
|
|
||||||
return m_layerInfo[LAYER_VOXEL_POSITION(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void fillVoxelLayerMaxHeight(LayerVoxelID min, LayerVoxelID max, uint8_t maxHeight) {
|
|
||||||
if (!m_layerInfo)
|
|
||||||
loadData();
|
|
||||||
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
for (layerVoxelID.x = min.x; layerVoxelID.x <= max.x; layerVoxelID.x++) {
|
|
||||||
for (layerVoxelID.z = min.x; layerVoxelID.z <= max.z; layerVoxelID.z++) {
|
|
||||||
int id = LAYER_VOXEL_POSITION(layerVoxelID);
|
|
||||||
if (m_layerInfo[id].height <= maxHeight)
|
|
||||||
m_layerInfo[id].height = maxHeight + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void loadData();
|
|
||||||
|
|
||||||
LayerVoxel* m_layerInfo = nullptr;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/Voxel.h"
|
|
||||||
#include "Deer/Log.h"
|
|
||||||
|
|
||||||
#include "cereal/cereal.hpp"
|
|
||||||
#include "cereal/types/string.hpp"
|
|
||||||
|
|
||||||
namespace Deer{
|
|
||||||
template<class Archive>
|
|
||||||
void save(Archive & archive, VoxelInfo const & block) {
|
|
||||||
archive(cereal::make_nvp("name", block.name));
|
|
||||||
|
|
||||||
// To avoid breaking things we set it up to Air
|
|
||||||
const char* blockTypeChar = VOXEL_INFO_TYPE_AIR;
|
|
||||||
switch (block.type)
|
|
||||||
{
|
|
||||||
case VoxelInfoType::Air :
|
|
||||||
blockTypeChar = VOXEL_INFO_TYPE_AIR;
|
|
||||||
break;
|
|
||||||
case VoxelInfoType::Voxel :
|
|
||||||
blockTypeChar = VOXEL_INFO_TYPE_VOXEL;
|
|
||||||
break;
|
|
||||||
case VoxelInfoType::TransparentVoxel :
|
|
||||||
blockTypeChar = VOXEL_INFO_TYPE_TRANSPARENT_VOXEL;
|
|
||||||
break;
|
|
||||||
case VoxelInfoType::Custom :
|
|
||||||
blockTypeChar = VOXEL_INFO_TYPE_CUSTOM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string blockTypeString(blockTypeChar);
|
|
||||||
archive(cereal::make_nvp("type", blockTypeString));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Archive>
|
|
||||||
void load(Archive & archive, VoxelInfo & block) {archive(cereal::make_nvp("name", block.name));
|
|
||||||
std::string blockTypeString;
|
|
||||||
|
|
||||||
archive(cereal::make_nvp("name", block.name));
|
|
||||||
archive(cereal::make_nvp("type", blockTypeString));
|
|
||||||
|
|
||||||
if (blockTypeString == VOXEL_INFO_TYPE_AIR)
|
|
||||||
block.type = VoxelInfoType::Air;
|
|
||||||
else if (blockTypeString == VOXEL_INFO_TYPE_VOXEL)
|
|
||||||
block.type = VoxelInfoType::Voxel;
|
|
||||||
else if (blockTypeString == VOXEL_INFO_TYPE_TRANSPARENT_VOXEL)
|
|
||||||
block.type = VoxelInfoType::TransparentVoxel;
|
|
||||||
else if (blockTypeString == VOXEL_INFO_TYPE_CUSTOM)
|
|
||||||
block.type = VoxelInfoType::Custom;
|
|
||||||
else {
|
|
||||||
block.type = VoxelInfoType::Air;
|
|
||||||
DEER_CORE_ERROR("Failed to resolve voxel type for {0}, unknown type : {1}",
|
|
||||||
block.name.c_str(), blockTypeString.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#include "Deer/Voxel.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
// This means the voxel is null
|
|
||||||
Voxel nullVoxel(65535);
|
|
||||||
Voxel emptyVoxel;
|
|
||||||
|
|
||||||
LayerVoxel nullLayerVoxel(65535);
|
|
||||||
|
|
||||||
int normalDirs[3 * 6] = {
|
|
||||||
-1, 0, 0,
|
|
||||||
1, 0, 0,
|
|
||||||
0, -1, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
0, 0, -1,
|
|
||||||
0, 0, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,86 +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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t id = voxelsInfo.size();
|
|
||||||
|
|
||||||
voxelsInfo.push_back(voxelData);
|
|
||||||
blockIDMap[voxelData.name] = id;
|
|
||||||
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataStore::createExampleVoxelData() {
|
|
||||||
VoxelInfo block;
|
|
||||||
|
|
||||||
std::stringstream data;
|
|
||||||
{
|
|
||||||
cereal::JSONOutputArchive archive(data);
|
|
||||||
archive(cereal::make_nvp("voxel", block));
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStore::saveFile(Path(DEER_VOXEL_PATH) / "voxel.example",
|
|
||||||
(uint8_t*)(data.str().c_str()), data.str().size());
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
#include "Deer/VoxelWorld.h"
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
|
|
||||||
#include "Deer/Log.h"
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/Layer.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void VoxelWorld::initialize(const VoxelWorldProps& props) {
|
|
||||||
clear();
|
|
||||||
|
|
||||||
worldProps = props;
|
|
||||||
|
|
||||||
chunks = MakeScope<Chunk[]>(worldProps.getChunkCount());
|
|
||||||
layers = MakeScope<Layer[]>(worldProps.getLayerCount());
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
initializeRenderVars(props);
|
|
||||||
#endif
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::clear() {
|
|
||||||
chunks.reset();
|
|
||||||
layers.reset();
|
|
||||||
|
|
||||||
initialized = false;
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
clearRenderVars();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const VoxelWorldProps& VoxelWorld::getWorldProps() {
|
|
||||||
return worldProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t VoxelWorld::calculateLayerVoxelHeight(int x, int z) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
LayerID layerID;
|
|
||||||
|
|
||||||
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
|
||||||
ChunkID chunkID(layerID.x, 0, layerID.z);
|
|
||||||
|
|
||||||
for (int y = worldProps.chunkSizeY - 1; y >= 0; y--) {
|
|
||||||
chunkID.y = y;
|
|
||||||
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
uint8_t chunkVoxelHeight =
|
|
||||||
chunk.calculateLayerVoxelHeight(layerVoxelID);
|
|
||||||
|
|
||||||
if (chunkVoxelHeight != 0) {
|
|
||||||
return chunkVoxelHeight + chunkID.y * CHUNK_SIZE_Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/Layer.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace VoxelWorld {
|
|
||||||
VoxelWorldProps worldProps;
|
|
||||||
|
|
||||||
Scope<Chunk[]> chunks;
|
|
||||||
Scope<Layer[]> layers;
|
|
||||||
|
|
||||||
bool initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoxelWorld::isInitialized() {
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Deer/Tools/Memory.h"
|
|
||||||
#include "Deer/VoxelWorld.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace VoxelWorld {
|
|
||||||
extern VoxelWorldProps worldProps;
|
|
||||||
|
|
||||||
extern Scope<Chunk[]> chunks;
|
|
||||||
extern Scope<Layer[]> layers;
|
|
||||||
extern bool initialized;
|
|
||||||
} // namespace VoxelWorld
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,159 +0,0 @@
|
|||||||
#include "Deer/VoxelWorld.h"
|
|
||||||
#include "Deer/Log.h"
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/Layer.h"
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
VoxelRayResult VoxelWorld::rayCast(glm::vec3 position, glm::vec3 dir, float maxDistance) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
VoxelRayResult result;
|
|
||||||
|
|
||||||
result.hitPos.x = (int32_t)std::floor(position.x);
|
|
||||||
result.hitPos.y = (int32_t)std::floor(position.y);
|
|
||||||
result.hitPos.z = (int32_t)std::floor(position.z);
|
|
||||||
|
|
||||||
result.distance = 0;
|
|
||||||
|
|
||||||
if (dir.x == 0 && dir.y == 0 && dir.z == 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = glm::normalize(dir);
|
|
||||||
|
|
||||||
glm::vec3 stepAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
|
||||||
glm::vec3 distanceAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
|
||||||
|
|
||||||
int8_t directionAxis[3] = { 1, 1, 1 };
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (dir[i] < 0) {
|
|
||||||
stepAxis[i] = -1.0f / dir[i];
|
|
||||||
directionAxis[i] = -1;
|
|
||||||
distanceAxis[i] = stepAxis[i] * ((float)position[i] - (float)(&result.hitPos.x)[i]);
|
|
||||||
}
|
|
||||||
else if (dir[i] > 0) {
|
|
||||||
stepAxis[i] = 1.0f / dir[i];
|
|
||||||
distanceAxis[i] = stepAxis[i] * (1 - (float)position[i] + (float)(&result.hitPos.x)[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result.distance < maxDistance) {
|
|
||||||
float minDistance = distanceAxis[0];
|
|
||||||
for (int i = 1; i < 3; i++) {
|
|
||||||
if (distanceAxis[i] < minDistance)
|
|
||||||
minDistance = distanceAxis[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
result.distance = minDistance;
|
|
||||||
if (result.distance > maxDistance)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (minDistance == distanceAxis[i]) {
|
|
||||||
result.hitPos[i] += directionAxis[i];
|
|
||||||
distanceAxis[i] = minDistance + stepAxis[i];
|
|
||||||
|
|
||||||
Voxel hitVoxel = readVoxel(result.hitPos);
|
|
||||||
|
|
||||||
if (hitVoxel == nullVoxel)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (hitVoxel != 0) {
|
|
||||||
result.face = i * 2;
|
|
||||||
|
|
||||||
if (directionAxis[i] == -1)
|
|
||||||
result.face++;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.distance = maxDistance;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
VoxelRayResult VoxelWorld::rayCast_editor(glm::vec3 position, glm::vec3 dir, float maxDistance) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
VoxelRayResult result;
|
|
||||||
|
|
||||||
result.hitPos.x = (int32_t)std::floor(position.x);
|
|
||||||
result.hitPos.y = (int32_t)std::floor(position.y);
|
|
||||||
result.hitPos.z = (int32_t)std::floor(position.z);
|
|
||||||
|
|
||||||
result.distance = 0;
|
|
||||||
|
|
||||||
if (dir.x == 0 && dir.y == 0 && dir.z == 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = glm::normalize(dir);
|
|
||||||
|
|
||||||
glm::vec3 stepAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
|
||||||
glm::vec3 distanceAxis = glm::vec3(maxDistance, maxDistance, maxDistance);
|
|
||||||
|
|
||||||
int8_t directionAxis[3] = { 1, 1, 1 };
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (dir[i] < 0) {
|
|
||||||
stepAxis[i] = -1.0f / dir[i];
|
|
||||||
directionAxis[i] = -1;
|
|
||||||
distanceAxis[i] = stepAxis[i] * ((float)position[i] - (float)result.hitPos[i]);
|
|
||||||
}
|
|
||||||
else if (dir[i] > 0) {
|
|
||||||
stepAxis[i] = 1.0f / dir[i];
|
|
||||||
distanceAxis[i] = stepAxis[i] * (1 - (float)position[i] + (float)result.hitPos[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Voxel hitVoxel = readVoxel(result.hitPos);
|
|
||||||
bool has_exit_inner_walls = hitVoxel.id == 0;
|
|
||||||
while (result.distance < maxDistance) {
|
|
||||||
float minDistance = distanceAxis[0];
|
|
||||||
for (int i = 1; i < 3; i++) {
|
|
||||||
if (distanceAxis[i] < minDistance)
|
|
||||||
minDistance = distanceAxis[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
result.distance = minDistance;
|
|
||||||
if (result.distance > maxDistance)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (minDistance == distanceAxis[i]) {
|
|
||||||
result.hitPos[i] += directionAxis[i];
|
|
||||||
distanceAxis[i] = minDistance + stepAxis[i];
|
|
||||||
|
|
||||||
Voxel hitVoxel = readVoxel(result.hitPos);
|
|
||||||
|
|
||||||
if (hitVoxel.id == 0) {
|
|
||||||
if (has_exit_inner_walls && result.hitPos.y == -1 && directionAxis[1] == -1 && i == 1) {
|
|
||||||
result.face = NORMAL_UP;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
has_exit_inner_walls = true;
|
|
||||||
} else if (hitVoxel.id != 0 && has_exit_inner_walls) {
|
|
||||||
result.face = i * 2;
|
|
||||||
|
|
||||||
if (directionAxis[i] == -1)
|
|
||||||
result.face++;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.distance = maxDistance;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,255 +0,0 @@
|
|||||||
#include "Deer/Log.h"
|
|
||||||
#include "Deer/VoxelWorld.h"
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/Layer.h"
|
|
||||||
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
Voxel VoxelWorld::readVoxel(VoxelCordinates coords) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID chunkID;
|
|
||||||
ChunkVoxelID chunkVoxelID;
|
|
||||||
|
|
||||||
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
|
||||||
if (!worldProps.isValid(chunkID)) return emptyVoxel;
|
|
||||||
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
return chunk.readVoxel(chunkVoxelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::setVoxel(VoxelCordinates coords, Voxel info) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID chunkID;
|
|
||||||
ChunkVoxelID chunkVoxelID;
|
|
||||||
|
|
||||||
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
|
||||||
if (!worldProps.isValid(chunkID)) return;
|
|
||||||
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
chunk.modVoxel(chunkVoxelID) = info;
|
|
||||||
|
|
||||||
LayerID layerID;
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
|
|
||||||
extractLayerCordinates(coords.x, coords.z, layerID, layerVoxelID);
|
|
||||||
|
|
||||||
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
|
||||||
LayerVoxel& layerVoxel = layer.modLayerVoxel(layerVoxelID);
|
|
||||||
|
|
||||||
if (!info.isVoxelType())
|
|
||||||
layerVoxel.height = calculateLayerVoxelHeight(coords.x, coords.z);
|
|
||||||
else if (coords.y >= layerVoxel.height)
|
|
||||||
layerVoxel.height = coords.y + 1;
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
chunkQueue.addChunk(chunkID);
|
|
||||||
// For every axis, X & Y & Z
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (chunkVoxelID[i] == 0 && chunkID[i] != 0) {
|
|
||||||
ChunkID nextChunk = chunkID;
|
|
||||||
nextChunk[i]--;
|
|
||||||
chunkQueue.addChunk(nextChunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunkVoxelID[i] == CHUNK_SIZE(i) &&
|
|
||||||
chunkID[i] != worldProps[i] - 1) {
|
|
||||||
ChunkID nextChunk = chunkID;
|
|
||||||
nextChunk[i]++;
|
|
||||||
chunkQueue.addChunk(nextChunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we should update the lighting
|
|
||||||
bakeAmbientLightFromPoint(coords.x, coords.z);
|
|
||||||
bakeVoxelLightFromPoint(coords);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::fillVoxels(VoxelCordinates min, VoxelCordinates max, Voxel info) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID minChunkID;
|
|
||||||
ChunkID maxChunkID;
|
|
||||||
ChunkVoxelID minChunkVoxelID;
|
|
||||||
ChunkVoxelID maxChunkVoxelID;
|
|
||||||
|
|
||||||
worldProps.clampAndSetMinMax(min, max);
|
|
||||||
|
|
||||||
extractChunkCordinates(min, minChunkID, minChunkVoxelID);
|
|
||||||
extractChunkCordinates(max, maxChunkID, maxChunkVoxelID);
|
|
||||||
for (int chunkX = minChunkID.x; chunkX <= maxChunkID.x; chunkX++) {
|
|
||||||
for (int chunkY = minChunkID.y; chunkY <= maxChunkID.y; chunkY++) {
|
|
||||||
for (int chunkZ = minChunkID.z; chunkZ <= maxChunkID.z;
|
|
||||||
chunkZ++) {
|
|
||||||
ChunkID workingChunkID(chunkX, chunkY, chunkZ);
|
|
||||||
LayerID workingLayerID(chunkX, chunkZ);
|
|
||||||
Chunk& workingChunk =
|
|
||||||
chunks[worldProps.getWorldChunkID(workingChunkID)];
|
|
||||||
Layer& workingLayer =
|
|
||||||
layers[worldProps.getWorldLayerID(workingLayerID)];
|
|
||||||
|
|
||||||
ChunkVoxelID workingMin(0, 0, 0);
|
|
||||||
ChunkVoxelID workingMax(CHUNK_SIZE_X - 1, CHUNK_SIZE_Y - 1,
|
|
||||||
CHUNK_SIZE_Z - 1);
|
|
||||||
|
|
||||||
if (chunkX == minChunkID.x)
|
|
||||||
workingMin.x = minChunkVoxelID.x;
|
|
||||||
if (chunkY == minChunkID.y)
|
|
||||||
workingMin.y = minChunkVoxelID.y;
|
|
||||||
if (chunkZ == minChunkID.z)
|
|
||||||
workingMin.z = minChunkVoxelID.z;
|
|
||||||
|
|
||||||
if (chunkX == maxChunkID.x)
|
|
||||||
workingMax.x = maxChunkVoxelID.x;
|
|
||||||
if (chunkY == maxChunkID.y)
|
|
||||||
workingMax.y = maxChunkVoxelID.y;
|
|
||||||
if (chunkZ == maxChunkID.z)
|
|
||||||
workingMax.z = maxChunkVoxelID.z;
|
|
||||||
|
|
||||||
LayerVoxelID workingMinLayer(workingMin.x, workingMin.z);
|
|
||||||
LayerVoxelID workingMaxLayer(workingMax.x, workingMax.z);
|
|
||||||
|
|
||||||
workingChunk.fillVoxels(workingMin, workingMax, info);
|
|
||||||
workingLayer.fillVoxelLayerMaxHeight(
|
|
||||||
workingMinLayer, workingMaxLayer, max.y);
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
chunkQueue.addChunk(workingChunkID);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
VoxelCordinates minLightModification = min;
|
|
||||||
VoxelCordinates maxLightModification = max;
|
|
||||||
// We want to add a 16 layer border
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
minLightModification[i] -= 16;
|
|
||||||
maxLightModification[i] += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
worldProps.clampCordinates(minLightModification);
|
|
||||||
worldProps.clampCordinates(maxLightModification);
|
|
||||||
|
|
||||||
bakeAmbientLight(minLightModification.x, maxLightModification.x,
|
|
||||||
minLightModification.z, maxLightModification.z);
|
|
||||||
bakeVoxelLight(minLightModification, maxLightModification);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::remplaceVoxels(VoxelCordinates min, VoxelCordinates max,
|
|
||||||
Voxel ref, Voxel value) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID minChunkID;
|
|
||||||
ChunkID maxChunkID;
|
|
||||||
ChunkVoxelID minChunkVoxelID;
|
|
||||||
ChunkVoxelID maxChunkVoxelID;
|
|
||||||
|
|
||||||
worldProps.clampAndSetMinMax(min, max);
|
|
||||||
|
|
||||||
extractChunkCordinates(min, minChunkID, minChunkVoxelID);
|
|
||||||
extractChunkCordinates(max, maxChunkID, maxChunkVoxelID);
|
|
||||||
for (int chunkX = minChunkID.x; chunkX <= maxChunkID.x; chunkX++) {
|
|
||||||
for (int chunkY = minChunkID.y; chunkY <= maxChunkID.y; chunkY++) {
|
|
||||||
for (int chunkZ = minChunkID.z; chunkZ <= maxChunkID.z;
|
|
||||||
chunkZ++) {
|
|
||||||
ChunkID workingChunkID(chunkX, chunkY, chunkZ);
|
|
||||||
Chunk& workingChunk =
|
|
||||||
chunks[worldProps.getWorldChunkID(workingChunkID)];
|
|
||||||
|
|
||||||
ChunkVoxelID workingMin(0, 0, 0);
|
|
||||||
ChunkVoxelID workingMax(CHUNK_SIZE_X - 1, CHUNK_SIZE_Y - 1,
|
|
||||||
CHUNK_SIZE_Z - 1);
|
|
||||||
|
|
||||||
if (chunkX == minChunkID.x)
|
|
||||||
workingMin.x = minChunkVoxelID.x;
|
|
||||||
if (chunkY == minChunkID.y)
|
|
||||||
workingMin.y = minChunkVoxelID.y;
|
|
||||||
if (chunkZ == minChunkID.z)
|
|
||||||
workingMin.z = minChunkVoxelID.z;
|
|
||||||
|
|
||||||
if (chunkX == maxChunkID.x)
|
|
||||||
workingMax.x = maxChunkVoxelID.x;
|
|
||||||
if (chunkY == maxChunkID.y)
|
|
||||||
workingMax.y = maxChunkVoxelID.y;
|
|
||||||
if (chunkZ == maxChunkID.z)
|
|
||||||
workingMax.z = maxChunkVoxelID.z;
|
|
||||||
|
|
||||||
workingChunk.remplaceVoxels(workingMin, workingMax, ref,
|
|
||||||
value);
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
chunkQueue.addChunk(workingChunkID);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int xPos = min.x; xPos <= max.x; xPos++) {
|
|
||||||
for (int zPos = min.z; zPos <= max.z; zPos++) {
|
|
||||||
LayerID layerID;
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
|
|
||||||
extractLayerCordinates(xPos, zPos, layerID, layerVoxelID);
|
|
||||||
int worldLayerID = worldProps.getWorldLayerID(layerID);
|
|
||||||
|
|
||||||
layers[worldLayerID].modLayerVoxel(layerVoxelID).height =
|
|
||||||
calculateLayerVoxelHeight(xPos, zPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
VoxelCordinates minLightModification = min;
|
|
||||||
VoxelCordinates maxLightModification = max;
|
|
||||||
// We want to add a 16 layer border
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
minLightModification[i] -= 16;
|
|
||||||
maxLightModification[i] += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
worldProps.clampCordinates(minLightModification);
|
|
||||||
worldProps.clampCordinates(maxLightModification);
|
|
||||||
|
|
||||||
bakeAmbientLight(minLightModification.x, maxLightModification.x,
|
|
||||||
minLightModification.z, maxLightModification.z);
|
|
||||||
bakeVoxelLight(minLightModification, maxLightModification);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerVoxel VoxelWorld::readLayerVoxel(int x, int z) {
|
|
||||||
LayerID layerID;
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
|
|
||||||
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
|
||||||
if (!worldProps.isValid(layerID)) return LayerVoxel();
|
|
||||||
|
|
||||||
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
|
||||||
return layer.readLayerVoxel(layerVoxelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerVoxel& VoxelWorld::modLayerVoxel(int x, int z) {
|
|
||||||
LayerID layerID;
|
|
||||||
LayerVoxelID layerVoxelID;
|
|
||||||
|
|
||||||
extractLayerCordinates(x, z, layerID, layerVoxelID);
|
|
||||||
if (!worldProps.isValid(layerID)) return nullLayerVoxel;
|
|
||||||
|
|
||||||
Layer& layer = layers[worldProps.getWorldLayerID(layerID)];
|
|
||||||
return layer.modLayerVoxel(layerVoxelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Deer
|
|
||||||
59
Deer/src/DeerCore/Core/Application.cpp
Normal file
59
Deer/src/DeerCore/Core/Application.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "DeerCore/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;
|
||||||
|
}
|
||||||
|
} // namespace Application
|
||||||
|
} // namespace Deer
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
std::shared_ptr<spdlog::logger> Log::coreLogger;
|
std::shared_ptr<spdlog::logger> Log::coreLogger;
|
||||||
@ -1,13 +1,13 @@
|
|||||||
#include "Deer/DataStore.h"
|
#include "DeerCore/DataStore.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
#include "cereal/archives/portable_binary.hpp"
|
#include "cereal/archives/portable_binary.hpp"
|
||||||
#include "cereal/cereal.hpp"
|
#include "cereal/cereal.hpp"
|
||||||
#include "cereal/types/unordered_map.hpp"
|
#include "cereal/types/unordered_map.hpp"
|
||||||
|
|
||||||
#include "Deer/DataStore/DataStructure.h"
|
#include "DeerCore/DataStore/DataStructure.h"
|
||||||
#include "Deer/DataStore/DataStructureSerialization.h"
|
#include "DeerCore/DataStore/DataStructureSerialization.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
struct DataStructure {
|
struct DataStructure {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/DataStore/DataStructure.h"
|
#include "DeerCore/DataStore/DataStructure.h"
|
||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
#include "cereal/cereal.hpp"
|
#include "cereal/cereal.hpp"
|
||||||
#include "cereal/types/string.hpp"
|
#include "cereal/types/string.hpp"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Deer/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
||||||
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include "DeerCore/Log.h"
|
||||||
|
#include "DeerCore/Network.h"
|
||||||
|
|
||||||
|
#include "enet/enet.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Network {
|
||||||
|
ServerSettings serverSettings;
|
||||||
|
ENetHost* enetServer;
|
||||||
|
|
||||||
|
void clientConnect(ENetPeer* refPeer);
|
||||||
|
void clientDisconnect(ENetPeer* refPeer);
|
||||||
|
void clientData(ENetPeer* peer, ENetPacket* packet);
|
||||||
|
|
||||||
|
// Fixed array of clients, defined by max player count
|
||||||
|
Scope<DeerClient[]> clients;
|
||||||
|
} // namespace Network
|
||||||
|
|
||||||
|
void Network::initServer(const ServerSettings& config) {
|
||||||
|
serverSettings = config;
|
||||||
|
if (enet_initialize() != 0) {
|
||||||
|
DEER_CORE_ERROR("An error ocurred while initing enet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ENetAddress serverAddress;
|
||||||
|
|
||||||
|
serverAddress.host = ENET_HOST_ANY;
|
||||||
|
serverAddress.port = config.port;
|
||||||
|
|
||||||
|
enetServer = enet_host_create(&serverAddress, config.maxClients, 2, config.maxOutgoingBand, config.maxIncomingBand);
|
||||||
|
if (!enetServer) {
|
||||||
|
DEER_CORE_ERROR("An error ocurred while initing server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients = MakeScope<DeerClient[]>(serverSettings.maxClients);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::shutdownServer() {
|
||||||
|
enet_deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::flushServerEvents() {
|
||||||
|
ENetEvent event;
|
||||||
|
while (enet_host_service(enetServer, &event, 0) > 0) {
|
||||||
|
switch (event.type) {
|
||||||
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
|
clientConnect(event.peer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
clientData(event.peer, event.packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
|
clientDisconnect(event.peer);
|
||||||
|
break;
|
||||||
|
case ENET_EVENT_TYPE_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::clientConnect(ENetPeer* peer) {
|
||||||
|
DeerClient* client = nullptr;
|
||||||
|
int clientId = -1;
|
||||||
|
for (int i = 0; i < serverSettings.maxClients; i++) {
|
||||||
|
if (clients[i].clientState == DeerClientState::NotConnected) {
|
||||||
|
client = &client[i];
|
||||||
|
clientId = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client) {
|
||||||
|
DEER_CORE_ERROR("Server full, critical error");
|
||||||
|
enet_peer_disconnect(peer, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->clientState = DeerClientState::Connected;
|
||||||
|
client->internalPeer = peer;
|
||||||
|
peer->data = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::clientDisconnect(ENetPeer* peer) {
|
||||||
|
DeerClient& client = *(DeerClient*)peer->data;
|
||||||
|
client.clientState = DeerClientState::NotConnected;
|
||||||
|
client.internalPeer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::clientData(ENetPeer* peer, ENetPacket* packetData) {
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
14
Deer/src/DeerCore/Scene/Components.cpp
Executable file
14
Deer/src/DeerCore/Scene/Components.cpp
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#include "DeerCore/Components.h"
|
||||||
|
#include "DeerCore/Log.h"
|
||||||
|
#include "glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
Entity::Entity(entt::entity handle, Environment* scene, uint16_t entityID)
|
Entity::Entity(entt::entity handle, Environment* scene, uint16_t entityID)
|
||||||
@ -1,10 +1,9 @@
|
|||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
|
|
||||||
#include "Deer/Application.h"
|
#include "DeerCore/Application.h"
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "DeerRender/Render/Render.h"
|
#include "DeerRender/Render/Render.h"
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
#include "DeerRender/Render/Texture.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
8
Deer/src/DeerCore/Scene/EnvironmentBuilder.cpp
Normal file
8
Deer/src/DeerCore/Scene/EnvironmentBuilder.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "DeerCore/Enviroment.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
Scope<Environment> ResourceBuilder<Environment>::buildResource(const BaseDataType& baseData) {
|
||||||
|
Scope<Environment> env = MakeScope<Environment>();
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
@ -1,28 +1,20 @@
|
|||||||
#include "Deer/Scene.h"
|
#include "DeerCore/Scene.h"
|
||||||
|
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Scene/SceneData.h"
|
||||||
#include "Deer/VoxelWorld.h"
|
#include "DeerCore/Tools/Memory.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
|
#ifdef DEER_RENDER
|
||||||
#include "DeerRender/FrameBuffer.h"
|
#include "DeerRender/FrameBuffer.h"
|
||||||
#include "DeerRender/Mesh.h"
|
#include "DeerRender/Mesh.h"
|
||||||
#include "DeerRender/Shader.h"
|
#include "DeerRender/Shader.h"
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
void Scene::clear() {
|
void Scene::clear() {
|
||||||
environment.clear();
|
environment.clear();
|
||||||
VoxelWorld::clear();
|
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
ResourceManager<Shader>::unloadResources();
|
ResourceManager<Shader>::unloadResources();
|
||||||
10
Deer/src/DeerCore/Scene/SceneData.cpp
Normal file
10
Deer/src/DeerCore/Scene/SceneData.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "DeerCore/Enviroment.h"
|
||||||
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Scene {
|
||||||
|
Environment environment;
|
||||||
|
bool isExecuting = false;
|
||||||
|
} // namespace Scene
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -1,9 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Tools/Memory.h"
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
#include "DeerRender/GizmoRenderer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class Environment;
|
class Environment;
|
||||||
@ -11,10 +7,6 @@ namespace Deer {
|
|||||||
namespace Scene {
|
namespace Scene {
|
||||||
extern Environment environment;
|
extern Environment environment;
|
||||||
extern bool isExecuting;
|
extern bool isExecuting;
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
|
||||||
extern GizmoRenderer gizmoRenderer;
|
|
||||||
#endif
|
|
||||||
} // namespace Scene
|
} // namespace Scene
|
||||||
|
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
// RELATIONSHIP COMPONENT
|
// RELATIONSHIP COMPONENT
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DeerCore/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));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Deer/Components.h"
|
#include "DeerCore/Components.h"
|
||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
#include "DeerCore/Scene/Serialization/SerializationGlobalVars.h"
|
||||||
#include "EntitySerializationStruct.h"
|
#include "EntitySerializationStruct.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
@ -2,7 +2,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Deer/Enviroment.h"
|
#include "DeerCore/Enviroment.h"
|
||||||
#include "EntitySerializationStruct.h"
|
#include "EntitySerializationStruct.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
@ -54,4 +54,4 @@ namespace Deer {
|
|||||||
archive(serializationStruct);
|
archive(serializationStruct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
@ -5,19 +5,19 @@
|
|||||||
#include "cereal/types/vector.hpp"
|
#include "cereal/types/vector.hpp"
|
||||||
|
|
||||||
// Serialization Vars
|
// Serialization Vars
|
||||||
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
#include "DeerCore/Scene/Serialization/SerializationGlobalVars.h"
|
||||||
|
|
||||||
// GENERICS
|
// GENERICS
|
||||||
#include "Deer/Scene/Serialization/QuatSerialization.h"
|
#include "DeerCore/Scene/Serialization/QuatSerialization.h"
|
||||||
#include "Deer/Scene/Serialization/Vec3Serialization.h"
|
#include "DeerCore/Scene/Serialization/Vec3Serialization.h"
|
||||||
|
|
||||||
// SCENE SPECIFIC
|
// SCENE SPECIFIC
|
||||||
#include "Deer/Scene/Serialization/EntitySerialization.h"
|
#include "DeerCore/Scene/Serialization/EntitySerialization.h"
|
||||||
#include "Deer/Scene/Serialization/EnvironmentSerialization.h"
|
#include "DeerCore/Scene/Serialization/EnvironmentSerialization.h"
|
||||||
|
|
||||||
// COMPONENTS SPECIFIC
|
// COMPONENTS SPECIFIC
|
||||||
#include "Deer/Scene/Serialization/Components/RelationshipComponentSerialization.h"
|
#include "DeerCore/Scene/Serialization/Components/RelationshipComponentSerialization.h"
|
||||||
#include "Deer/Scene/Serialization/Components/TransformComponentSerialization.h"
|
#include "DeerCore/Scene/Serialization/Components/TransformComponentSerialization.h"
|
||||||
|
|
||||||
// RENDER SPECIFIC
|
// RENDER SPECIFIC
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "DeerRender/Render/Render.h"
|
#include "DeerRender/Render/Render.h"
|
||||||
#include "DeerRender/Render/RenderCommand.h"
|
#include "DeerRender/Render/RenderCommand.h"
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Log.h"
|
#include "DeerRender/Log.h"
|
||||||
|
|
||||||
@ -46,7 +45,6 @@ namespace Deer {
|
|||||||
imGuiLayer = MakeScope<ImGuiLayer>();
|
imGuiLayer = MakeScope<ImGuiLayer>();
|
||||||
imGuiLayer->onAttach();
|
imGuiLayer->onAttach();
|
||||||
|
|
||||||
RenderUtils::initializeRenderUtils();
|
|
||||||
RenderCommand::init();
|
RenderCommand::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "RenderUtils.h"
|
#include "RenderUtils.h"
|
||||||
#include "DeerRender/Render/VertexArray.h"
|
|
||||||
#include "DeerRender/Render/Buffer.h"
|
#include "DeerRender/Render/Buffer.h"
|
||||||
#include "DeerRender/Render/Shader.h"
|
#include "DeerRender/Render/Shader.h"
|
||||||
|
#include "DeerRender/Render/VertexArray.h"
|
||||||
|
|
||||||
#ifdef DEER_RENDER
|
#ifdef DEER_RENDER
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ namespace Deer {
|
|||||||
Scope<VertexArray> genFaceVertexArray();
|
Scope<VertexArray> genFaceVertexArray();
|
||||||
Scope<Shader> getLineShader();
|
Scope<Shader> getLineShader();
|
||||||
Scope<Shader> getFaceShader();
|
Scope<Shader> getFaceShader();
|
||||||
}
|
} // namespace RenderUtils
|
||||||
|
|
||||||
void RenderUtils::initializeRenderUtils() {
|
void RenderUtils::initializeRenderUtils() {
|
||||||
m_lineVertexArray = genLineVertexArray();
|
m_lineVertexArray = genLineVertexArray();
|
||||||
@ -25,18 +25,23 @@ namespace Deer {
|
|||||||
m_faceShader = getFaceShader();
|
m_faceShader = getFaceShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderUtils::deinitializeRenderUtils() {
|
||||||
|
m_lineVertexArray.reset();
|
||||||
|
m_lineShader.reset();
|
||||||
|
m_faceVertexArray.reset();
|
||||||
|
m_faceShader.reset();
|
||||||
|
}
|
||||||
|
|
||||||
Scope<VertexArray> RenderUtils::genLineVertexArray() {
|
Scope<VertexArray> RenderUtils::genLineVertexArray() {
|
||||||
unsigned int vertices[2] = { 0, 1 };
|
unsigned int vertices[2] = {0, 1};
|
||||||
|
|
||||||
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
||||||
vertexArray->bind();
|
vertexArray->bind();
|
||||||
|
|
||||||
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
||||||
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(vertices, sizeof(vertices), IndexDataType::Unsigned_Int);
|
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(vertices, sizeof(vertices), IndexDataType::Unsigned_Int);
|
||||||
|
|
||||||
BufferLayout layout({
|
BufferLayout layout({{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}});
|
||||||
{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}
|
|
||||||
});
|
|
||||||
|
|
||||||
vertexBuffer->setLayout(layout);
|
vertexBuffer->setLayout(layout);
|
||||||
vertexArray->addVertexBuffer(vertexBuffer);
|
vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
@ -87,11 +92,9 @@ void main()
|
|||||||
|
|
||||||
Scope<VertexArray> RenderUtils::genFaceVertexArray() {
|
Scope<VertexArray> RenderUtils::genFaceVertexArray() {
|
||||||
unsigned int vertices[4] = {
|
unsigned int vertices[4] = {
|
||||||
0, 1, 2, 3
|
0, 1, 2, 3};
|
||||||
};
|
|
||||||
unsigned int indices[6] = {
|
unsigned int indices[6] = {
|
||||||
0, 2, 1, 1, 2, 3
|
0, 2, 1, 1, 2, 3};
|
||||||
};
|
|
||||||
|
|
||||||
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
||||||
vertexArray->bind();
|
vertexArray->bind();
|
||||||
@ -99,9 +102,7 @@ void main()
|
|||||||
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
||||||
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(indices, sizeof(indices), IndexDataType::Unsigned_Int);
|
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(indices, sizeof(indices), IndexDataType::Unsigned_Int);
|
||||||
|
|
||||||
BufferLayout layout({
|
BufferLayout layout({{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}});
|
||||||
{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}
|
|
||||||
});
|
|
||||||
|
|
||||||
vertexBuffer->setLayout(layout);
|
vertexBuffer->setLayout(layout);
|
||||||
vertexArray->addVertexBuffer(vertexBuffer);
|
vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
@ -178,5 +179,5 @@ void main()
|
|||||||
return Scope<Shader>(Shader::create(vertexSrc, fragmentSrc));
|
return Scope<Shader>(Shader::create(vertexSrc, fragmentSrc));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace Deer
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -12,5 +12,6 @@ namespace Deer {
|
|||||||
extern Scope<Shader> m_faceShader;
|
extern Scope<Shader> m_faceShader;
|
||||||
|
|
||||||
void initializeRenderUtils();
|
void initializeRenderUtils();
|
||||||
|
void deinitializeRenderUtils();
|
||||||
} // namespace RenderUtils
|
} // namespace RenderUtils
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
#include "DeerRender/Application.h"
|
#include "DeerRender/Application.h"
|
||||||
|
|
||||||
#include "DeerRender/Components.h"
|
#include "DeerRender/Components.h"
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Mesh.h"
|
#include "DeerRender/Mesh.h"
|
||||||
#include "DeerRender/Render/Render.h"
|
#include "DeerRender/Render/Render.h"
|
||||||
@ -14,7 +13,7 @@
|
|||||||
#include "DeerRender/Log.h"
|
#include "DeerRender/Log.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
void Environment::render(SceneCamera& camera) {
|
void Environment::render(const SceneCamera& camera) {
|
||||||
glm::mat4 camMatrix = glm::inverse(camera.transform.getMatrix());
|
glm::mat4 camMatrix = glm::inverse(camera.transform.getMatrix());
|
||||||
glm::mat4 projectionMatrix = camera.camera.getMatrix();
|
glm::mat4 projectionMatrix = camera.camera.getMatrix();
|
||||||
glm::mat4 invertZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
|
glm::mat4 invertZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
|
||||||
|
|||||||
@ -1,163 +0,0 @@
|
|||||||
#include "DeerRender/GizmoRenderer.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Components.h"
|
|
||||||
#include "DeerRender/Render/Render.h"
|
|
||||||
#include "DeerRender/Render/RenderCommand.h"
|
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
|
||||||
#include "DeerRender/Scene.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void GizmoRenderer::drawLine(glm::vec3 a, glm::vec3 b, glm::vec3 color) {
|
|
||||||
m_lines.push_back({a, b, color});
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::drawVoxelLine(int _x, int _y, int _z, glm::vec3 color) {
|
|
||||||
for (int x = 0; x < 2; x++) {
|
|
||||||
for (int y = 0; y < 2; y++) {
|
|
||||||
glm::vec3 a = glm::vec3(x + _x, y + _y, 0 + _z);
|
|
||||||
glm::vec3 b = glm::vec3(x + _x, y + _y, 1 + _z);
|
|
||||||
|
|
||||||
drawLine(a, b, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int z = 0; z < 2; z++) {
|
|
||||||
for (int y = 0; y < 2; y++) {
|
|
||||||
glm::vec3 a = glm::vec3(0 + _x, y + _y, z + _z);
|
|
||||||
glm::vec3 b = glm::vec3(1 + _x, y + _y, z + _z);
|
|
||||||
|
|
||||||
drawLine(a, b, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int x = 0; x < 2; x++) {
|
|
||||||
for (int z = 0; z < 2; z++) {
|
|
||||||
glm::vec3 a = glm::vec3(x + _x, 0 + _y, z + _z);
|
|
||||||
glm::vec3 b = glm::vec3(x + _x, 1 + _y, z + _z);
|
|
||||||
|
|
||||||
drawLine(a, b, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::drawVoxelLineFace(int x, int y, int z, uint8_t face,
|
|
||||||
glm::vec3 color) {
|
|
||||||
glm::vec3 points[4];
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
points[i] = {x + NORMAL_VERTEX_POS(X_AXIS, i, face),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, i, face),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, i, face)};
|
|
||||||
}
|
|
||||||
|
|
||||||
drawLine(points[0], points[1], color);
|
|
||||||
drawLine(points[2], points[3], color);
|
|
||||||
drawLine(points[0], points[2], color);
|
|
||||||
drawLine(points[1], points[3], color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::drawVoxelFace(int x, int y, int z, uint16_t voxelID,
|
|
||||||
uint8_t faceID, uint8_t priority) {
|
|
||||||
glm::vec3 points[4];
|
|
||||||
VoxelAspect& aspect = DataStore::voxelsAspect[voxelID];
|
|
||||||
GizmoFace face;
|
|
||||||
face.textureID = aspect.textureFacesIDs[faceID];
|
|
||||||
face.face = faceID;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
face.positions[i] = {x + NORMAL_VERTEX_POS(X_AXIS, i, faceID),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, i, faceID),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, i, faceID)};
|
|
||||||
}
|
|
||||||
|
|
||||||
m_faces[priority].push_back(face);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::drawVoxelFaceInverted(int x, int y, int z,
|
|
||||||
uint16_t voxelID, uint8_t faceID,
|
|
||||||
uint8_t priority) {
|
|
||||||
glm::vec3 points[4];
|
|
||||||
VoxelAspect& aspect = DataStore::voxelsAspect[voxelID];
|
|
||||||
GizmoFace face;
|
|
||||||
face.textureID = aspect.textureFacesIDs[faceID];
|
|
||||||
face.face = faceID;
|
|
||||||
|
|
||||||
face.positions[0] = {x + NORMAL_VERTEX_POS(X_AXIS, 0, faceID),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, 0, faceID),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, 0, faceID)};
|
|
||||||
|
|
||||||
face.positions[2] = {x + NORMAL_VERTEX_POS(X_AXIS, 1, faceID),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, 1, faceID),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, 1, faceID)};
|
|
||||||
|
|
||||||
face.positions[1] = {x + NORMAL_VERTEX_POS(X_AXIS, 2, faceID),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, 2, faceID),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, 2, faceID)};
|
|
||||||
|
|
||||||
face.positions[3] = {x + NORMAL_VERTEX_POS(X_AXIS, 3, faceID),
|
|
||||||
y + NORMAL_VERTEX_POS(Y_AXIS, 3, faceID),
|
|
||||||
z + NORMAL_VERTEX_POS(Z_AXIS, 3, faceID)};
|
|
||||||
|
|
||||||
m_faces[priority].push_back(face);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::render(const SceneCamera& camera) {
|
|
||||||
RenderCommand::setDepthBuffer(true);
|
|
||||||
|
|
||||||
// We make a exact camera but with less far clip to give priority in the
|
|
||||||
// depht test
|
|
||||||
CameraComponent camera_lessDistance = camera.camera;
|
|
||||||
camera_lessDistance.farZ *= 1.1f;
|
|
||||||
|
|
||||||
glm::mat4 camMatrix = glm::inverse(camera.transform.getMatrix());
|
|
||||||
glm::mat4 projectionMatrix = camera_lessDistance.getMatrix();
|
|
||||||
glm::mat4 invertZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
|
|
||||||
|
|
||||||
glm::mat4 cameraProjectionMatrix =
|
|
||||||
projectionMatrix * invertZ * camMatrix;
|
|
||||||
|
|
||||||
// DataStore::getVoxelColorTextureAtlas()->bind(0);
|
|
||||||
RenderUtils::m_faceShader->bind();
|
|
||||||
RenderUtils::m_faceShader->uploadUniformMat4("u_viewMatrix", cameraProjectionMatrix);
|
|
||||||
RenderUtils::m_faceShader->uploadUniformInt("u_texture", 0);
|
|
||||||
// RenderUtils::m_faceShader->uploadUniformInt("u_textureSize", DataStore::getVoxelTextureAtlasSize());
|
|
||||||
|
|
||||||
for (int i = 0; i < GIZMO_DEPTH; i++) {
|
|
||||||
for (GizmoFace& face : m_faces[i]) {
|
|
||||||
RenderUtils::m_faceShader->uploadUniformInt("u_textureID",
|
|
||||||
face.textureID);
|
|
||||||
|
|
||||||
RenderUtils::m_faceShader->uploadUniformFloat3(
|
|
||||||
"u_posA", face.positions[0]);
|
|
||||||
RenderUtils::m_faceShader->uploadUniformFloat3(
|
|
||||||
"u_posB", face.positions[1]);
|
|
||||||
RenderUtils::m_faceShader->uploadUniformFloat3(
|
|
||||||
"u_posC", face.positions[2]);
|
|
||||||
RenderUtils::m_faceShader->uploadUniformFloat3(
|
|
||||||
"u_posD", face.positions[3]);
|
|
||||||
|
|
||||||
Render::submit(*RenderUtils::m_faceVertexArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderCommand::setDepthBuffer(false);
|
|
||||||
|
|
||||||
for (std::array<glm::vec3, 3>& line : m_lines) {
|
|
||||||
RenderUtils::m_lineShader->bind();
|
|
||||||
RenderUtils::m_lineShader->uploadUniformMat4(
|
|
||||||
"u_viewMatrix", cameraProjectionMatrix);
|
|
||||||
RenderUtils::m_lineShader->uploadUniformFloat3("u_color", line[2]);
|
|
||||||
|
|
||||||
RenderUtils::m_lineShader->uploadUniformFloat3("u_posA", line[0]);
|
|
||||||
RenderUtils::m_lineShader->uploadUniformFloat3("u_posB", line[1]);
|
|
||||||
|
|
||||||
Render::submitLine(*RenderUtils::m_lineVertexArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GizmoRenderer::refresh() {
|
|
||||||
m_lines.clear();
|
|
||||||
for (int i = 0; i < GIZMO_DEPTH; i++)
|
|
||||||
m_faces[i].clear();
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -3,7 +3,7 @@
|
|||||||
#include "DeerRender/Components.h"
|
#include "DeerRender/Components.h"
|
||||||
#include "DeerRender/Enviroment.h"
|
#include "DeerRender/Enviroment.h"
|
||||||
#include "DeerRender/Render/RenderCommand.h"
|
#include "DeerRender/Render/RenderCommand.h"
|
||||||
#include "DeerRender/VoxelWorld.h"
|
#include "DeerRender/Scene.h"
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
void Scene::render() {
|
void Scene::render() {
|
||||||
@ -19,15 +19,11 @@ namespace Deer {
|
|||||||
Scene::render(sceneCamera);
|
Scene::render(sceneCamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::render(SceneCamera sceneCamera) {
|
void Scene::render(const SceneCamera& sceneCamera) {
|
||||||
RenderCommand::setDepthBuffer(true);
|
RenderCommand::setDepthBuffer(true);
|
||||||
environment.render(sceneCamera);
|
environment.render(sceneCamera);
|
||||||
|
|
||||||
if (VoxelWorld::isInitialized())
|
|
||||||
VoxelWorld::render(sceneCamera);
|
|
||||||
|
|
||||||
RenderCommand::setDepthBuffer(false);
|
RenderCommand::setDepthBuffer(false);
|
||||||
gizmoRenderer.render(sceneCamera);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Deer
|
} // namespace Deer
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void ChunkUpdateQueue::addChunk(ChunkID chunkID) {
|
|
||||||
if (m_containingChunks.contains(chunkID))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_containingChunks.insert(chunkID);
|
|
||||||
m_updateOrder.push(chunkID);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkID ChunkUpdateQueue::pullChunk() {
|
|
||||||
ChunkID chunkID = m_updateOrder.front();
|
|
||||||
m_updateOrder.pop();
|
|
||||||
m_containingChunks.erase(chunkID);
|
|
||||||
return chunkID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChunkUpdateQueue::reset() {
|
|
||||||
while (!m_updateOrder.empty()) {
|
|
||||||
m_updateOrder.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_containingChunks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChunkUpdateQueue::hasChunk() {
|
|
||||||
return m_updateOrder.size() > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#include "DeerRender/VoxelAspect.h"
|
|
||||||
|
|
||||||
#include "cereal/cereal.hpp"
|
|
||||||
#include "cereal/types/string.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive& archive, VoxelTextureFaceDefinition& textureFaceDefinitions) {
|
|
||||||
archive(cereal::make_nvp("left", textureFaceDefinitions.textureFaces[NORMAL_LEFT]));
|
|
||||||
archive(cereal::make_nvp("right", textureFaceDefinitions.textureFaces[NORMAL_RIGHT]));
|
|
||||||
archive(cereal::make_nvp("down", textureFaceDefinitions.textureFaces[NORMAL_DOWN]));
|
|
||||||
archive(cereal::make_nvp("up", textureFaceDefinitions.textureFaces[NORMAL_UP]));
|
|
||||||
archive(cereal::make_nvp("front", textureFaceDefinitions.textureFaces[NORMAL_FRONT]));
|
|
||||||
archive(cereal::make_nvp("back", textureFaceDefinitions.textureFaces[NORMAL_BACK]));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive& archive, VoxelColorEmission& voxelEmission) {
|
|
||||||
archive(cereal::make_nvp("red", voxelEmission.r_value));
|
|
||||||
archive(cereal::make_nvp("green", voxelEmission.g_value));
|
|
||||||
archive(cereal::make_nvp("blue", voxelEmission.b_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive& archive, VoxelAspectDefinition& voxelAspectDefinition) {
|
|
||||||
archive(cereal::make_nvp("name", voxelAspectDefinition.voxelName));
|
|
||||||
archive(cereal::make_nvp("textureFaces", voxelAspectDefinition.textureFaces));
|
|
||||||
archive(cereal::make_nvp("emission", voxelAspectDefinition.colorEmission));
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
#include "DeerRender/Voxel.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
VoxelLight lightVoxel(255);
|
|
||||||
|
|
||||||
int lightPropagationComplexDir[12 * 2] = {
|
|
||||||
NORMAL_LEFT, NORMAL_DOWN,
|
|
||||||
NORMAL_RIGHT, NORMAL_DOWN,
|
|
||||||
NORMAL_LEFT, NORMAL_UP,
|
|
||||||
NORMAL_RIGHT, NORMAL_UP,
|
|
||||||
NORMAL_LEFT, NORMAL_BACK,
|
|
||||||
NORMAL_RIGHT, NORMAL_BACK,
|
|
||||||
NORMAL_LEFT, NORMAL_FRONT,
|
|
||||||
NORMAL_RIGHT, NORMAL_FRONT,
|
|
||||||
NORMAL_DOWN, NORMAL_BACK,
|
|
||||||
NORMAL_UP, NORMAL_BACK,
|
|
||||||
NORMAL_DOWN, NORMAL_FRONT,
|
|
||||||
NORMAL_UP, NORMAL_FRONT};
|
|
||||||
|
|
||||||
int normalFacePositions[3 * 4 * 6] = {
|
|
||||||
// Left
|
|
||||||
0, 0, 1,
|
|
||||||
0, 0, 0,
|
|
||||||
0, 1, 1,
|
|
||||||
0, 1, 0,
|
|
||||||
// Right
|
|
||||||
1, 0, 0,
|
|
||||||
1, 0, 1,
|
|
||||||
1, 1, 0,
|
|
||||||
1, 1, 1,
|
|
||||||
// Down
|
|
||||||
0, 0, 1,
|
|
||||||
1, 0, 1,
|
|
||||||
0, 0, 0,
|
|
||||||
1, 0, 0,
|
|
||||||
// Up
|
|
||||||
0, 1, 0,
|
|
||||||
1, 1, 0,
|
|
||||||
0, 1, 1,
|
|
||||||
1, 1, 1,
|
|
||||||
// Back
|
|
||||||
0, 0, 0,
|
|
||||||
1, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
1, 1, 0,
|
|
||||||
// Front
|
|
||||||
1, 0, 1,
|
|
||||||
0, 0, 1,
|
|
||||||
1, 1, 1,
|
|
||||||
0, 1, 1};
|
|
||||||
|
|
||||||
int uvFace[2 * 4] = {
|
|
||||||
0, 0,
|
|
||||||
1, 0,
|
|
||||||
0, 1,
|
|
||||||
1, 1};
|
|
||||||
|
|
||||||
int ambientOcclusionVertex[6 * 2 * 4 * 3]{
|
|
||||||
0, -1, 0, 0, 0, 1,
|
|
||||||
0, -1, 0, 0, 0, -1,
|
|
||||||
0, 1, 0, 0, 0, 1,
|
|
||||||
0, 1, 0, 0, 0, -1,
|
|
||||||
0, -1, 0, 0, 0, -1,
|
|
||||||
0, -1, 0, 0, 0, 1,
|
|
||||||
0, 1, 0, 0, 0, -1,
|
|
||||||
0, 1, 0, 0, 0, 1,
|
|
||||||
-1, 0, 0, 0, 0, 1,
|
|
||||||
1, 0, 0, 0, 0, 1,
|
|
||||||
-1, 0, 0, 0, 0, -1,
|
|
||||||
1, 0, 0, 0, 0, -1,
|
|
||||||
-1, 0, 0, 0, 0, -1,
|
|
||||||
1, 0, 0, 0, 0, -1,
|
|
||||||
-1, 0, 0, 0, 0, 1,
|
|
||||||
1, 0, 0, 0, 0, 1,
|
|
||||||
-1, 0, 0, 0, -1, 0,
|
|
||||||
1, 0, 0, 0, -1, 0,
|
|
||||||
-1, 0, 0, 0, 1, 0,
|
|
||||||
1, 0, 0, 0, 1, 0,
|
|
||||||
1, 0, 0, 0, -1, 0,
|
|
||||||
-1, 0, 0, 0, -1, 0,
|
|
||||||
1, 0, 0, 0, 1, 0,
|
|
||||||
-1, 0, 0, 0, 1, 0};
|
|
||||||
|
|
||||||
int layerCheckDirections[2 * 8]{
|
|
||||||
-1, 0,
|
|
||||||
-1, 1,
|
|
||||||
0, 1,
|
|
||||||
1, 1,
|
|
||||||
1, 0,
|
|
||||||
1, -1,
|
|
||||||
0, -1,
|
|
||||||
-1, -1};
|
|
||||||
|
|
||||||
void calcFaces() {
|
|
||||||
std::string out;
|
|
||||||
|
|
||||||
for (int f = 0; f < 6; f++) {
|
|
||||||
int normalDirX = NORMAL_DIR(X_AXIS, f);
|
|
||||||
int normalDirY = NORMAL_DIR(Y_AXIS, f);
|
|
||||||
int normalDirZ = NORMAL_DIR(Z_AXIS, f);
|
|
||||||
|
|
||||||
for (int vertex = 0; vertex < 4; vertex++) {
|
|
||||||
int xPos = NORMAL_VERTEX_POS(X_AXIS, vertex, f);
|
|
||||||
int yPos = NORMAL_VERTEX_POS(Y_AXIS, vertex, f);
|
|
||||||
int zPos = NORMAL_VERTEX_POS(Z_AXIS, vertex, f);
|
|
||||||
|
|
||||||
int sideX = (xPos == 1) ? 1 : -1;
|
|
||||||
int sideY = (yPos == 1) ? 1 : -1;
|
|
||||||
int sideZ = (zPos == 1) ? 1 : -1;
|
|
||||||
|
|
||||||
if (normalDirX == 1 || normalDirX == -1) {
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(sideY) + ", ";
|
|
||||||
out += std::to_string(0) + ",\t";
|
|
||||||
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(sideZ) + ",\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalDirY == 1 || normalDirY == -1) {
|
|
||||||
out += std::to_string(sideX) + ", ";
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(0) + ",\t";
|
|
||||||
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(sideZ) + ",\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalDirZ == 1 || normalDirZ == -1) {
|
|
||||||
out += std::to_string(sideX) + ", ";
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(0) + ",\t";
|
|
||||||
|
|
||||||
out += std::to_string(0) + ", ";
|
|
||||||
out += std::to_string(sideY) + ", ";
|
|
||||||
out += std::to_string(0) + ",\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << out;
|
|
||||||
} /**/
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "DeerRender/DataStore.h"
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "DeerRender/Render/Shader.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#include "DeerRender/VoxelAspect.h"
|
|
||||||
#include "DeerRender/Voxels/Serialization/VoxelAspect_Serialization.h"
|
|
||||||
#include "cereal/archives/json.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace DataStore {
|
|
||||||
std::vector<VoxelAspect> voxelsAspect;
|
|
||||||
std::unordered_map<std::string, uint16_t> texturesIDs;
|
|
||||||
Ref<Shader> solidVoxelShader;
|
|
||||||
} // namespace DataStore
|
|
||||||
|
|
||||||
void DataStore::loadVoxelsAspect() {
|
|
||||||
std::vector<Path> voxelsAspectPath =
|
|
||||||
DataStore::getFiles(DEER_VOXEL_ASPECT_PATH, ".vaspect");
|
|
||||||
voxelsAspect.clear();
|
|
||||||
voxelsAspect.resize(voxelsInfo.size());
|
|
||||||
|
|
||||||
voxelsAspect[0].definition.voxelName = VOXEL_INFO_TYPE_AIR;
|
|
||||||
|
|
||||||
DEER_CORE_TRACE("Loading voxel aspect ");
|
|
||||||
// DEER_CORE_TRACE(" default - air");
|
|
||||||
for (Path& voxelAspectPath : voxelsAspectPath) {
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t* data = DataStore::readFile(voxelAspectPath, &size);
|
|
||||||
|
|
||||||
std::string dataString((char*)data, size);
|
|
||||||
std::istringstream inputStream(dataString);
|
|
||||||
|
|
||||||
VoxelAspectDefinition aspectDefinition;
|
|
||||||
{
|
|
||||||
cereal::JSONInputArchive archive(inputStream);
|
|
||||||
archive(cereal::make_nvp("voxelAspect", aspectDefinition));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aspectDefinition.voxelName.empty()) {
|
|
||||||
DEER_CORE_ERROR("{0} has an empty name",
|
|
||||||
voxelAspectPath.generic_string().c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t voxelID = getVoxelID(aspectDefinition.voxelName);
|
|
||||||
if (voxelID == -1) {
|
|
||||||
DEER_CORE_ERROR(
|
|
||||||
"Voxel aspect {0} references {1} but it does not exist",
|
|
||||||
voxelAspectPath.generic_string().c_str(),
|
|
||||||
aspectDefinition.voxelName.c_str());
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
voxelsAspect[voxelID].definition = aspectDefinition;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEER_CORE_TRACE("Extracting textures ");
|
|
||||||
for (VoxelAspect& voxelAspect : voxelsAspect) {
|
|
||||||
if (voxelsInfo[DataStore::getVoxelID(
|
|
||||||
voxelAspect.definition.voxelName)]
|
|
||||||
.type != VoxelInfoType::Voxel)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
std::string& faceTextureString =
|
|
||||||
voxelAspect.definition.textureFaces[i];
|
|
||||||
|
|
||||||
if (faceTextureString.empty()) {
|
|
||||||
DEER_CORE_WARN(
|
|
||||||
"{0} has an empty texture at position {1} this could "
|
|
||||||
"cause unwanted behaviour!",
|
|
||||||
voxelAspect.definition.voxelName.c_str(), i);
|
|
||||||
|
|
||||||
voxelAspect.textureFacesIDs[i] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texturesIDs.contains(faceTextureString))
|
|
||||||
voxelAspect.textureFacesIDs[i] =
|
|
||||||
texturesIDs[faceTextureString];
|
|
||||||
else {
|
|
||||||
uint16_t textureID = texturesIDs.size();
|
|
||||||
|
|
||||||
texturesIDs[faceTextureString] = textureID;
|
|
||||||
voxelAspect.textureFacesIDs[i] = textureID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataStore::createExampleVoxelAspect() {
|
|
||||||
VoxelAspectDefinition voxelAspectDefinition;
|
|
||||||
|
|
||||||
std::ostringstream outputStream;
|
|
||||||
{
|
|
||||||
cereal::JSONOutputArchive archive(outputStream);
|
|
||||||
archive(cereal::make_nvp("voxelAspect", voxelAspectDefinition));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string restultString = outputStream.str();
|
|
||||||
DataStore::saveFile(Path(DEER_VOXEL_PATH) / "vaspect.example",
|
|
||||||
(uint8_t*)restultString.c_str(),
|
|
||||||
restultString.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataStore::loadVoxelsShaders() {
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t* data = DataStore::readFile(
|
|
||||||
Path(DEER_VOXEL_SHADER_PATH) / "solid_voxel.glsl", &size);
|
|
||||||
|
|
||||||
solidVoxelShader = Shader::create(data, size);
|
|
||||||
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ref<Shader>& DataStore::getSolidVoxelShader() { return solidVoxelShader; }
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "DeerRender/DataStore.h"
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#include "DeerRender/VoxelAspect.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace DataStore {
|
|
||||||
extern std::unordered_map<std::string, uint16_t> texturesIDs;
|
|
||||||
|
|
||||||
int squareTextureSize = 0;
|
|
||||||
uint8_t* voxelColorTextureAtlasData = nullptr;
|
|
||||||
Ref<Texture2D> voxelColorTextureAtlas = nullptr;
|
|
||||||
} // namespace DataStore
|
|
||||||
|
|
||||||
void DataStore::generateTextureAtlas() {
|
|
||||||
if (voxelColorTextureAtlasData != nullptr) {
|
|
||||||
delete[] voxelColorTextureAtlasData;
|
|
||||||
voxelColorTextureAtlasData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
squareTextureSize = 1;
|
|
||||||
int textureCount = texturesIDs.size();
|
|
||||||
while (squareTextureSize * squareTextureSize < textureCount)
|
|
||||||
squareTextureSize++;
|
|
||||||
|
|
||||||
int textureAtlasSize = squareTextureSize * VOXEL_TEXTURE_SIZE_X *
|
|
||||||
squareTextureSize * VOXEL_TEXTURE_SIZE_Y * 4;
|
|
||||||
voxelColorTextureAtlasData = new uint8_t[textureAtlasSize]{};
|
|
||||||
|
|
||||||
DEER_CORE_TRACE("Creating Texture Atlas ");
|
|
||||||
for (auto& texture : texturesIDs) {
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t* fileData = DataStore::readFile(
|
|
||||||
Path(DEER_VOXEL_TEXTURE_PATH) / (texture.first + ".png"),
|
|
||||||
&size);
|
|
||||||
|
|
||||||
// DEER_CORE_TRACE(" {0}.png - {1}", texture.first.c_str(),
|
|
||||||
// texture.second);
|
|
||||||
if (fileData == nullptr) {
|
|
||||||
DEER_CORE_ERROR("{0}.png does not exists",
|
|
||||||
texture.first.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int width, height, channels;
|
|
||||||
uint8_t* textureData = stbi_load_from_memory(fileData, size, &width,
|
|
||||||
&height, &channels, 4);
|
|
||||||
|
|
||||||
if (channels < 3) {
|
|
||||||
DEER_CORE_ERROR(
|
|
||||||
"{0}.png has {1} channels and it must be bigger than {2}",
|
|
||||||
texture.first.c_str(), channels, 3);
|
|
||||||
} else if (width != VOXEL_TEXTURE_SIZE_X) {
|
|
||||||
DEER_CORE_ERROR("{0}.png has a width of {1} and it must be {2}",
|
|
||||||
texture.first.c_str(), width,
|
|
||||||
VOXEL_TEXTURE_SIZE_X);
|
|
||||||
} else if (height != VOXEL_TEXTURE_SIZE_Y) {
|
|
||||||
DEER_CORE_ERROR(
|
|
||||||
"{0}.png has a height of {1} and it must be {2}",
|
|
||||||
texture.first.c_str(), height, VOXEL_TEXTURE_SIZE_Y);
|
|
||||||
} else {
|
|
||||||
int yOffset = (int)(texture.second / squareTextureSize);
|
|
||||||
int xOffset = texture.second - yOffset * squareTextureSize;
|
|
||||||
|
|
||||||
int yOffsetPixels = yOffset * VOXEL_TEXTURE_SIZE_Y;
|
|
||||||
int xOffsetPixels = xOffset * VOXEL_TEXTURE_SIZE_X;
|
|
||||||
|
|
||||||
for (int y = 0; y < VOXEL_TEXTURE_SIZE_Y; y++) {
|
|
||||||
for (int x = 0; x < VOXEL_TEXTURE_SIZE_X; x++) {
|
|
||||||
int inputTextureIndex = (x + y * width) * 4;
|
|
||||||
int outputTextureIndex =
|
|
||||||
(x + xOffsetPixels +
|
|
||||||
(y + yOffsetPixels) * VOXEL_TEXTURE_SIZE_X *
|
|
||||||
squareTextureSize) *
|
|
||||||
4;
|
|
||||||
|
|
||||||
voxelColorTextureAtlasData[outputTextureIndex + 0] =
|
|
||||||
textureData[inputTextureIndex + 0];
|
|
||||||
voxelColorTextureAtlasData[outputTextureIndex + 1] =
|
|
||||||
textureData[inputTextureIndex + 1];
|
|
||||||
voxelColorTextureAtlasData[outputTextureIndex + 2] =
|
|
||||||
textureData[inputTextureIndex + 2];
|
|
||||||
voxelColorTextureAtlasData[outputTextureIndex + 3] =
|
|
||||||
textureData[inputTextureIndex + 3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stbi_image_free(textureData);
|
|
||||||
delete[] fileData;
|
|
||||||
}
|
|
||||||
|
|
||||||
voxelColorTextureAtlas =
|
|
||||||
Texture2D::create(voxelColorTextureAtlasData,
|
|
||||||
squareTextureSize * VOXEL_TEXTURE_SIZE_X,
|
|
||||||
squareTextureSize * VOXEL_TEXTURE_SIZE_Y, 4);
|
|
||||||
|
|
||||||
// temp
|
|
||||||
// Path savePath = DataStore::rootPath / DEER_TEMP_PATH / "voxel_texture_atlas.png";
|
|
||||||
// DataStore::createFolder(DataStore::rootPath / DEER_TEMP_PATH);
|
|
||||||
// stbi_write_png(savePath.generic_string().c_str(), squareTextureSize * VOXEL_TEXTURE_SIZE_X, squareTextureSize * VOXEL_TEXTURE_SIZE_Y, 4, voxelColorTextureAtlasData, squareTextureSize * VOXEL_TEXTURE_SIZE_X * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DataStore::getVoxelTextureAtlasSize() { return squareTextureSize; }
|
|
||||||
|
|
||||||
Ref<Texture2D>& DataStore::getVoxelColorTextureAtlas() {
|
|
||||||
return voxelColorTextureAtlas;
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
*/
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
#include "DeerRender/Application.h"
|
|
||||||
#include "DeerRender/Components.h"
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "DeerRender/Tools/Memory.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Render/Render.h"
|
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
|
||||||
#include "DeerRender/Scene.h"
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
#include "glm/gtc/matrix_inverse.hpp"
|
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
VoxelLight VoxelWorld::readLight(VoxelCordinates coords) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID chunkID;
|
|
||||||
ChunkVoxelID chunkVoxelID;
|
|
||||||
|
|
||||||
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
|
||||||
if (!worldProps.isValid(chunkID))
|
|
||||||
return lightVoxel;
|
|
||||||
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
return chunk.readLight(chunkVoxelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
VoxelLight& VoxelWorld::modLight(VoxelCordinates coords) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
ChunkID chunkID;
|
|
||||||
ChunkVoxelID chunkVoxelID;
|
|
||||||
|
|
||||||
extractChunkCordinates(coords, chunkID, chunkVoxelID);
|
|
||||||
if (!worldProps.isValid(chunkID))
|
|
||||||
return lightVoxel;
|
|
||||||
|
|
||||||
chunkQueue.addChunk(chunkID);
|
|
||||||
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
return chunk.modLight(chunkVoxelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::render(const SceneCamera& camera) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
glm::mat4 camMatrix = glm::inverse(camera.transform.getMatrix());
|
|
||||||
glm::mat4 projectionMatrix = camera.camera.getMatrix();
|
|
||||||
glm::mat4 invertZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
|
|
||||||
|
|
||||||
// Lets invert the z axis for engine convenience
|
|
||||||
glm::mat4 cameraProjectionMatrix =
|
|
||||||
projectionMatrix * invertZ * camMatrix;
|
|
||||||
|
|
||||||
// DataStore::getVoxelColorTextureAtlas()->bind(0);
|
|
||||||
|
|
||||||
// Ref<Shader>& shader = DataStore::getSolidVoxelShader();
|
|
||||||
// shader->bind();
|
|
||||||
|
|
||||||
// shader->uploadUniformMat4("u_viewMatrix", cameraProjectionMatrix);
|
|
||||||
// shader->uploadUniformMat4("u_worldMatrix", glm::mat4(1.0f));
|
|
||||||
// shader->uploadUniformInt("u_texture", 0);
|
|
||||||
// shader->uploadUniformInt("u_textureSize",
|
|
||||||
// DataStore::getVoxelTextureAtlasSize());
|
|
||||||
|
|
||||||
for (int x = 0; x < worldProps.getChunkCount(); x++) {
|
|
||||||
ChunkRender& chunkRender = chunksRender[x];
|
|
||||||
if (!chunkRender.hasData)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ChunkID chunkID = worldProps.getChunkID(x);
|
|
||||||
chunkRender.solidVoxel->bind();
|
|
||||||
|
|
||||||
// shader->uploadUniformInt("u_chunkID_x", chunkID.x);
|
|
||||||
// shader->uploadUniformInt("u_chunkID_y", chunkID.y);
|
|
||||||
// shader->uploadUniformInt("u_chunkID_z", chunkID.z);
|
|
||||||
|
|
||||||
Render::submit(*chunkRender.solidVoxel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace VoxelWorld {
|
|
||||||
// Chunk render data
|
|
||||||
Scope<ChunkRender[]> chunksRender;
|
|
||||||
ChunkUpdateQueue chunkQueue;
|
|
||||||
|
|
||||||
// Voxel creation data
|
|
||||||
std::vector<uint32_t> indices;
|
|
||||||
std::vector<SolidVoxelVertexData> vertexData;
|
|
||||||
std::queue<VoxelCordinates> ambientLightPropagation;
|
|
||||||
std::queue<VoxelCordinates> voxelLightPropagation;
|
|
||||||
std::vector<VoxelCordinates> tmp_voxelLightSource;
|
|
||||||
} // namespace VoxelWorld
|
|
||||||
|
|
||||||
void VoxelWorld::clearRenderVars() {
|
|
||||||
chunksRender.reset();
|
|
||||||
chunkQueue.reset();
|
|
||||||
|
|
||||||
indices.clear();
|
|
||||||
vertexData.clear();
|
|
||||||
|
|
||||||
while (!ambientLightPropagation.empty()) {
|
|
||||||
ambientLightPropagation.pop();
|
|
||||||
}
|
|
||||||
while (!voxelLightPropagation.empty()) {
|
|
||||||
voxelLightPropagation.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp_voxelLightSource.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::initializeRenderVars(const VoxelWorldProps& props) {
|
|
||||||
chunksRender = MakeScope<ChunkRender[]>(props.getChunkCount());
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "DeerRender/Render/VertexArray.h"
|
|
||||||
#include "DeerRender/Tools/Memory.h"
|
|
||||||
#include "DeerRender/Voxel.h"
|
|
||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
struct ChunkRender {
|
|
||||||
Scope<VertexArray> solidVoxel;
|
|
||||||
bool hasData = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SolidVoxelVertexData {
|
|
||||||
uint16_t textureID = 0;
|
|
||||||
uint8_t ambient_occlusion = 0;
|
|
||||||
|
|
||||||
uint8_t xPos = 0;
|
|
||||||
uint8_t yPos = 0;
|
|
||||||
uint8_t zPos = 0;
|
|
||||||
|
|
||||||
uint8_t a_light = 0;
|
|
||||||
uint8_t r_light = 0;
|
|
||||||
uint8_t g_light = 0;
|
|
||||||
uint8_t b_light = 0;
|
|
||||||
|
|
||||||
uint8_t normal = 0;
|
|
||||||
|
|
||||||
uint8_t u = 0;
|
|
||||||
uint8_t v = 0;
|
|
||||||
|
|
||||||
SolidVoxelVertexData() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChunkUpdateQueue {
|
|
||||||
public:
|
|
||||||
// TODO: Add priority
|
|
||||||
void addChunk(ChunkID);
|
|
||||||
void reset();
|
|
||||||
ChunkID pullChunk();
|
|
||||||
bool hasChunk();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::queue<ChunkID> m_updateOrder;
|
|
||||||
std::unordered_set<ChunkID, ChunkIDHash> m_containingChunks;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace VoxelWorld {
|
|
||||||
// Chunk render data
|
|
||||||
extern Scope<ChunkRender[]> chunksRender;
|
|
||||||
extern ChunkUpdateQueue chunkQueue;
|
|
||||||
|
|
||||||
// Voxel creation data
|
|
||||||
extern std::vector<uint32_t> indices;
|
|
||||||
extern std::vector<SolidVoxelVertexData> vertexData;
|
|
||||||
|
|
||||||
// Voxel temp light variables
|
|
||||||
extern std::queue<VoxelCordinates> ambientLightPropagation;
|
|
||||||
extern std::queue<VoxelCordinates> voxelLightPropagation;
|
|
||||||
extern std::vector<VoxelCordinates> tmp_voxelLightSource;
|
|
||||||
|
|
||||||
void clearRenderVars();
|
|
||||||
void initializeRenderVars(const VoxelWorldProps& props);
|
|
||||||
} // namespace VoxelWorld
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,177 +0,0 @@
|
|||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "DeerRender/Application.h"
|
|
||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
#include "DeerRender/Components.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Render/Render.h"
|
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
#include "glm/gtc/matrix_inverse.hpp"
|
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void VoxelWorld::bakeAmbientLight(int minX, int maxX, int minZ, int maxZ) {
|
|
||||||
int xPos = minX;
|
|
||||||
for (; xPos <= maxX; xPos++) {
|
|
||||||
int zPos = minZ;
|
|
||||||
for (; zPos <= maxZ; zPos++) {
|
|
||||||
LayerVoxel layer = readLayerVoxel(xPos, zPos);
|
|
||||||
uint16_t maxHeight = layer.height;
|
|
||||||
uint16_t minHeight = layer.ambient_light_height;
|
|
||||||
|
|
||||||
if (minHeight > layer.height)
|
|
||||||
minHeight = layer.height;
|
|
||||||
|
|
||||||
uint16_t maxHeightSorroundings = maxHeight;
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
int checkX = xPos + LAYER_CHECK_DIRS(X_AXIS, i);
|
|
||||||
int checkZ = zPos + LAYER_CHECK_DIRS(Y_AXIS, i);
|
|
||||||
|
|
||||||
LayerVoxel layer = readLayerVoxel(checkX, checkZ);
|
|
||||||
if (layer.height > maxHeightSorroundings)
|
|
||||||
maxHeightSorroundings = layer.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
maxHeightSorroundings++;
|
|
||||||
if (maxHeightSorroundings >= CHUNK_SIZE_Y * worldProps.chunkSizeY)
|
|
||||||
maxHeightSorroundings = CHUNK_SIZE_Y * worldProps.chunkSizeY - 1;
|
|
||||||
|
|
||||||
ChunkID chunkID;
|
|
||||||
ChunkVoxelID chunkVoxelID;
|
|
||||||
|
|
||||||
// Depending if it's an edge we will add to queue to propagate the light
|
|
||||||
bool isPositionEdge =
|
|
||||||
(xPos == minX) || (xPos == maxX) ||
|
|
||||||
(zPos == minZ) || (zPos == maxZ);
|
|
||||||
|
|
||||||
if (xPos == 0 || zPos == 0 || xPos == CHUNK_SIZE_X * worldProps.chunkSizeX - 1 || zPos == CHUNK_SIZE_Z * worldProps.chunkSizeZ - 1)
|
|
||||||
isPositionEdge = false;
|
|
||||||
|
|
||||||
// All light voxelsInfo under the max height must be put to 0 ambient light and above to 255
|
|
||||||
// I think this is optional
|
|
||||||
|
|
||||||
int yPos = minHeight;
|
|
||||||
if (!isPositionEdge) {
|
|
||||||
// Empty the ilumination
|
|
||||||
for (; yPos < maxHeight; yPos++) {
|
|
||||||
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
VoxelLight& voxelLight = chunk.modLight(chunkVoxelID);
|
|
||||||
|
|
||||||
voxelLight.ambient_light = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Add to queue
|
|
||||||
for (; yPos < maxHeight; yPos++) {
|
|
||||||
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
VoxelLight voxelLight = chunk.readLight(chunkVoxelID);
|
|
||||||
|
|
||||||
if (voxelLight.ambient_light > 0)
|
|
||||||
ambientLightPropagation.push(VoxelCordinates(xPos, yPos, zPos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill with light voxelsInfo and add queue to update light propagation
|
|
||||||
for (; yPos < maxHeightSorroundings; yPos++) {
|
|
||||||
extractChunkCordinates(xPos, yPos, zPos, chunkID, chunkVoxelID);
|
|
||||||
Chunk& chunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
VoxelLight& voxelLight = chunk.modLight(chunkVoxelID);
|
|
||||||
|
|
||||||
voxelLight.ambient_light = 255;
|
|
||||||
ambientLightPropagation.push(VoxelCordinates(xPos, yPos, zPos));
|
|
||||||
}
|
|
||||||
|
|
||||||
modLayerVoxel(xPos, zPos).ambient_light_height = CHUNK_SIZE_Y * worldProps.chunkSizeY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve ambient light propagation
|
|
||||||
while (!ambientLightPropagation.empty()) {
|
|
||||||
resolveNextAmbientLightPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::bakeAmbientLightFromPoint(int x, int z) {
|
|
||||||
int minX = x - 16;
|
|
||||||
int maxX = x + 16;
|
|
||||||
|
|
||||||
int minZ = z - 16;
|
|
||||||
int maxZ = z + 16;
|
|
||||||
|
|
||||||
minX = (minX < 0) ? 0 : minX;
|
|
||||||
maxX = (maxX >= worldProps.chunkSizeX * CHUNK_SIZE_X) ? worldProps.chunkSizeX * CHUNK_SIZE_X - 1 : maxX;
|
|
||||||
|
|
||||||
minZ = (minZ < 0) ? 0 : minZ;
|
|
||||||
maxZ = (maxZ >= worldProps.chunkSizeZ * CHUNK_SIZE_Z) ? worldProps.chunkSizeZ * CHUNK_SIZE_Z - 1 : maxZ;
|
|
||||||
|
|
||||||
bakeAmbientLight(minX, maxX, minZ, maxZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::resolveNextAmbientLightPropagation() {
|
|
||||||
VoxelCordinates position = ambientLightPropagation.front();
|
|
||||||
ambientLightPropagation.pop();
|
|
||||||
|
|
||||||
LayerVoxel& layerVoxel = modLayerVoxel(position.x, position.z);
|
|
||||||
|
|
||||||
if (layerVoxel.ambient_light_height > position.y)
|
|
||||||
layerVoxel.ambient_light_height = position.y;
|
|
||||||
|
|
||||||
VoxelLight currentLight = readLight(position);
|
|
||||||
bool solidCheck[6] = {false};
|
|
||||||
// Check for every simple dir
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
VoxelCordinates next(
|
|
||||||
position.x + NORMAL_DIR(X_AXIS, i),
|
|
||||||
position.y + NORMAL_DIR(Y_AXIS, i),
|
|
||||||
position.z + NORMAL_DIR(Z_AXIS, i));
|
|
||||||
|
|
||||||
Voxel nextVoxel = readVoxel(next);
|
|
||||||
solidCheck[i] = nextVoxel.isVoxelType();
|
|
||||||
if (solidCheck[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelLight& nextLight = modLight(next);
|
|
||||||
int nextLightMinValue = currentLight.ambient_light - LIGHT_PROPAGATION_SIMPLE_FALL;
|
|
||||||
|
|
||||||
if (nextLight.ambient_light < nextLightMinValue) {
|
|
||||||
nextLight.ambient_light = nextLightMinValue;
|
|
||||||
ambientLightPropagation.push(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
// TODO
|
|
||||||
// Check for every complex dir
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
int cDir0 = LIGHT_PROPAGATION_COMPLEX_DIR(0, i);
|
|
||||||
int cDir1 = LIGHT_PROPAGATION_COMPLEX_DIR(1, i);
|
|
||||||
|
|
||||||
if (solidCheck[cDir0] || solidCheck[cDir1])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelCordinates next(
|
|
||||||
NORMAL_DIR(X_AXIS, cDir0) + NORMAL_DIR(X_AXIS, cDir1),
|
|
||||||
NORMAL_DIR(Y_AXIS, cDir0) + NORMAL_DIR(Y_AXIS, cDir1),
|
|
||||||
NORMAL_DIR(Z_AXIS, cDir0) + NORMAL_DIR(Z_AXIS, cDir1));
|
|
||||||
|
|
||||||
Voxel nextVoxel = readVoxel(next);
|
|
||||||
if (nextVoxel.isVoxelType())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelLight& nextLight = modLight(next);
|
|
||||||
int nextLightMinValue = currentLight.ambient_light - LIGHT_PROPAGATION_COMPLEX_FALL;
|
|
||||||
|
|
||||||
if (nextLight.ambient_light < nextLightMinValue) {
|
|
||||||
nextLight.ambient_light = nextLightMinValue;
|
|
||||||
ambientLightPropagation.push(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,263 +0,0 @@
|
|||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
#include "DeerRender/Application.h"
|
|
||||||
#include "DeerRender/Components.h"
|
|
||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
|
|
||||||
#include "DeerRender/Render/Render.h"
|
|
||||||
#include "DeerRender/Render/RenderUtils.h"
|
|
||||||
#include "DeerRender/Render/Texture.h"
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
#include "glm/glm.hpp"
|
|
||||||
#include "glm/gtc/matrix_inverse.hpp"
|
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void VoxelWorld::bakeNextChunk() {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
if (!chunkQueue.hasChunk())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Pull the next chunk to render
|
|
||||||
ChunkID nextChunk = chunkQueue.pullChunk();
|
|
||||||
vertexData.clear();
|
|
||||||
indices.clear();
|
|
||||||
|
|
||||||
// For each voxel
|
|
||||||
for (int x = 0; x < CHUNK_SIZE_X; x++) {
|
|
||||||
for (int y = 0; y < CHUNK_SIZE_Y; y++) {
|
|
||||||
for (int z = 0; z < CHUNK_SIZE_Z; z++) {
|
|
||||||
genSolidVoxel(nextChunk, ChunkVoxelID(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the data to the GPU
|
|
||||||
Scope<VertexArray> va = Scope<VertexArray>(VertexArray::create());
|
|
||||||
va->bind();
|
|
||||||
Ref<VertexBuffer> vb = VertexBuffer::create(
|
|
||||||
vertexData.data(),
|
|
||||||
vertexData.size() * sizeof(SolidVoxelVertexData));
|
|
||||||
Ref<IndexBuffer> ib =
|
|
||||||
IndexBuffer::create(indices.data(),
|
|
||||||
indices.size() * sizeof(uint32_t),
|
|
||||||
IndexDataType::Unsigned_Int);
|
|
||||||
|
|
||||||
BufferLayout layout(
|
|
||||||
{{"a_textureID", DataType::Unsigned_Short2, ShaderDataType::Integer,
|
|
||||||
offsetof(SolidVoxelVertexData, textureID)},
|
|
||||||
{"a_ambient_occlusion", DataType::Unsigned_Byte,
|
|
||||||
ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, ambient_occlusion)},
|
|
||||||
|
|
||||||
{"a_xPos", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, xPos)},
|
|
||||||
{"a_yPos", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, yPos)},
|
|
||||||
{"a_zPos", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, zPos)},
|
|
||||||
|
|
||||||
{"a_a_light", DataType::Unsigned_Byte,
|
|
||||||
ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, a_light)},
|
|
||||||
{"a_r_light", DataType::Unsigned_Byte,
|
|
||||||
ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, r_light)},
|
|
||||||
{"a_g_light", DataType::Unsigned_Byte,
|
|
||||||
ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, g_light)},
|
|
||||||
{"a_b_light", DataType::Unsigned_Byte,
|
|
||||||
ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, b_light)},
|
|
||||||
|
|
||||||
{"a_normal", DataType::Unsigned_Byte, ShaderDataType::Integer,
|
|
||||||
offsetof(SolidVoxelVertexData, normal)},
|
|
||||||
|
|
||||||
{"a_u", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, u)},
|
|
||||||
{"a_v", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint,
|
|
||||||
offsetof(SolidVoxelVertexData, v)}},
|
|
||||||
sizeof(SolidVoxelVertexData));
|
|
||||||
|
|
||||||
vb->setLayout(layout);
|
|
||||||
va->addVertexBuffer(vb);
|
|
||||||
va->setIndexBuffer(ib);
|
|
||||||
|
|
||||||
// Update the data to the chunk render
|
|
||||||
int id = worldProps.getWorldChunkID(nextChunk);
|
|
||||||
ChunkRender& chunkRender = chunksRender[id];
|
|
||||||
chunkRender.solidVoxel = std::move(va);
|
|
||||||
chunkRender.hasData = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::genSolidVoxel(ChunkID chunkID, ChunkVoxelID chunkVoxelID) {
|
|
||||||
Chunk& workingChunk = chunks[worldProps.getWorldChunkID(chunkID)];
|
|
||||||
Voxel voxel = workingChunk.readVoxel(chunkVoxelID);
|
|
||||||
|
|
||||||
if (!voxel.isVoxelType())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
// front means the front voxel of the face
|
|
||||||
VoxelCordinates frontID(NORMAL_DIR(X_AXIS, i) + chunkVoxelID.x +
|
|
||||||
CHUNK_SIZE_X * chunkID.x,
|
|
||||||
NORMAL_DIR(Y_AXIS, i) + chunkVoxelID.y +
|
|
||||||
CHUNK_SIZE_Y * chunkID.y,
|
|
||||||
NORMAL_DIR(Z_AXIS, i) + chunkVoxelID.z +
|
|
||||||
CHUNK_SIZE_Z * chunkID.z);
|
|
||||||
|
|
||||||
Voxel frontVoxel = readVoxel(frontID);
|
|
||||||
// If the face is inside 2 Voxels we will not render it
|
|
||||||
if (frontVoxel.isVoxelType())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelLight frontVoxelLight = readLight(frontID);
|
|
||||||
|
|
||||||
// front2ID means the front voxel in 2 voxels apart
|
|
||||||
VoxelCordinates front2ID(
|
|
||||||
NORMAL_DIR(X_AXIS, i) * 2 + chunkVoxelID.x +
|
|
||||||
CHUNK_SIZE_X * chunkID.x,
|
|
||||||
NORMAL_DIR(Y_AXIS, i) * 2 + chunkVoxelID.y +
|
|
||||||
CHUNK_SIZE_Y * chunkID.y,
|
|
||||||
NORMAL_DIR(Z_AXIS, i) * 2 + chunkVoxelID.z +
|
|
||||||
CHUNK_SIZE_Z * chunkID.z);
|
|
||||||
|
|
||||||
Voxel front2Voxel = readVoxel(frontID);
|
|
||||||
VoxelLight front2VoxelLight = readLight(frontID);
|
|
||||||
|
|
||||||
// Face Shadow means that face is not in the direction of the light
|
|
||||||
bool isFaceShadow = frontVoxelLight.ambient_light != 255 &&
|
|
||||||
(frontVoxel.isVoxelType() ||
|
|
||||||
frontVoxelLight.ambient_light >
|
|
||||||
front2VoxelLight.ambient_light);
|
|
||||||
|
|
||||||
// Save the vertex id for later
|
|
||||||
int vertexID = vertexData.size();
|
|
||||||
|
|
||||||
int voxel_count[4];
|
|
||||||
|
|
||||||
// For every vertex
|
|
||||||
for (int v = 0; v < 4; v++) {
|
|
||||||
// This var takes the count of the voxels that where added in
|
|
||||||
// voxel_light
|
|
||||||
int sample_count = 1;
|
|
||||||
// Count the blocks to calculate the ambient occlusion, min
|
|
||||||
// value 0 max value 2
|
|
||||||
voxel_count[v] = 0;
|
|
||||||
|
|
||||||
// col 0 -> ambient oclusion
|
|
||||||
// col 1 -> red light
|
|
||||||
// col 2 -> green light
|
|
||||||
// col 3 -> blue light
|
|
||||||
int voxel_light[4];
|
|
||||||
|
|
||||||
voxel_light[0] = frontVoxelLight.ambient_light;
|
|
||||||
voxel_light[1] = frontVoxelLight.r_light;
|
|
||||||
voxel_light[2] = frontVoxelLight.g_light;
|
|
||||||
voxel_light[3] = frontVoxelLight.b_light;
|
|
||||||
|
|
||||||
// Checks if there is air on the blocks of the side
|
|
||||||
bool airEdge[2];
|
|
||||||
|
|
||||||
// Calculate ambient occlusion and light difusion
|
|
||||||
for (int a = 0; a < 2; a++) {
|
|
||||||
VoxelCordinates checkChordsID(
|
|
||||||
frontID.x + AMBIENT_OCCLUSION_VERTEX(X_AXIS, a, v, i),
|
|
||||||
frontID.y + AMBIENT_OCCLUSION_VERTEX(Y_AXIS, a, v, i),
|
|
||||||
frontID.z + AMBIENT_OCCLUSION_VERTEX(Z_AXIS, a, v, i));
|
|
||||||
|
|
||||||
Voxel checkChordsVoxel = readVoxel(checkChordsID);
|
|
||||||
VoxelLight checkChordsVoxelLight = readLight(checkChordsID);
|
|
||||||
|
|
||||||
// Check for the same chords but 2 voxels apart
|
|
||||||
airEdge[a] = !checkChordsVoxel.isVoxelType();
|
|
||||||
if (airEdge[a]) {
|
|
||||||
sample_count++;
|
|
||||||
|
|
||||||
voxel_light[0] += checkChordsVoxelLight.ambient_light;
|
|
||||||
voxel_light[1] += checkChordsVoxelLight.r_light;
|
|
||||||
voxel_light[2] += checkChordsVoxelLight.g_light;
|
|
||||||
voxel_light[3] += checkChordsVoxelLight.b_light;
|
|
||||||
} else {
|
|
||||||
voxel_count[v]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (airEdge[0] || airEdge[1]) {
|
|
||||||
VoxelCordinates checkChordsID(
|
|
||||||
frontID.x + AMBIENT_OCCLUSION_VERTEX(X_AXIS, 0, v, i) +
|
|
||||||
AMBIENT_OCCLUSION_VERTEX(X_AXIS, 1, v, i),
|
|
||||||
frontID.y + AMBIENT_OCCLUSION_VERTEX(Y_AXIS, 0, v, i) +
|
|
||||||
AMBIENT_OCCLUSION_VERTEX(Y_AXIS, 1, v, i),
|
|
||||||
frontID.z + AMBIENT_OCCLUSION_VERTEX(Z_AXIS, 0, v, i) +
|
|
||||||
AMBIENT_OCCLUSION_VERTEX(Z_AXIS, 1, v, i));
|
|
||||||
|
|
||||||
Voxel checkChordsVoxel = readVoxel(checkChordsID);
|
|
||||||
VoxelLight checkChordsVoxelLight = readLight(checkChordsID);
|
|
||||||
|
|
||||||
if (!checkChordsVoxel.isVoxelType()) {
|
|
||||||
sample_count++;
|
|
||||||
|
|
||||||
voxel_light[0] += checkChordsVoxelLight.ambient_light;
|
|
||||||
voxel_light[1] += checkChordsVoxelLight.r_light;
|
|
||||||
voxel_light[2] += checkChordsVoxelLight.g_light;
|
|
||||||
voxel_light[3] += checkChordsVoxelLight.b_light;
|
|
||||||
} else {
|
|
||||||
voxel_count[v]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int xi = 0; xi < 4; xi++) {
|
|
||||||
voxel_light[xi] = (voxel_light[xi]) / sample_count;
|
|
||||||
voxel_light[xi] =
|
|
||||||
(voxel_light[xi] > 255) ? 255 : voxel_light[xi];
|
|
||||||
}
|
|
||||||
|
|
||||||
SolidVoxelVertexData vertex_data;
|
|
||||||
vertex_data.textureID =
|
|
||||||
DataStore::voxelsAspect[voxel.id].getTextureID(i);
|
|
||||||
vertex_data.ambient_occlusion = voxel_count[v];
|
|
||||||
|
|
||||||
vertex_data.xPos =
|
|
||||||
chunkVoxelID.x + NORMAL_VERTEX_POS(X_AXIS, v, i);
|
|
||||||
vertex_data.yPos =
|
|
||||||
chunkVoxelID.y + NORMAL_VERTEX_POS(Y_AXIS, v, i);
|
|
||||||
vertex_data.zPos =
|
|
||||||
chunkVoxelID.z + NORMAL_VERTEX_POS(Z_AXIS, v, i);
|
|
||||||
|
|
||||||
vertex_data.a_light = voxel_light[0];
|
|
||||||
vertex_data.r_light = voxel_light[1];
|
|
||||||
vertex_data.g_light = voxel_light[2];
|
|
||||||
vertex_data.b_light = voxel_light[3];
|
|
||||||
|
|
||||||
vertex_data.normal = i;
|
|
||||||
|
|
||||||
vertex_data.u = VERTEX_UV(X_AXIS, v);
|
|
||||||
vertex_data.v = VERTEX_UV(Y_AXIS, v);
|
|
||||||
|
|
||||||
vertexData.push_back(vertex_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voxel_count[0] + voxel_count[3] >
|
|
||||||
voxel_count[1] + voxel_count[2]) {
|
|
||||||
indices.push_back(vertexID);
|
|
||||||
indices.push_back(vertexID + 2);
|
|
||||||
indices.push_back(vertexID + 1);
|
|
||||||
|
|
||||||
indices.push_back(vertexID + 1);
|
|
||||||
indices.push_back(vertexID + 2);
|
|
||||||
indices.push_back(vertexID + 3);
|
|
||||||
} else {
|
|
||||||
indices.push_back(vertexID);
|
|
||||||
indices.push_back(vertexID + 3);
|
|
||||||
indices.push_back(vertexID + 1);
|
|
||||||
|
|
||||||
indices.push_back(vertexID + 2);
|
|
||||||
indices.push_back(vertexID + 3);
|
|
||||||
indices.push_back(vertexID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,250 +0,0 @@
|
|||||||
#include "Deer/Voxels/Chunk.h"
|
|
||||||
#include "Deer/Voxels/VoxelWorldData.h"
|
|
||||||
#include "DeerRender/Log.h"
|
|
||||||
#include "DeerRender/VoxelWorld.h"
|
|
||||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
void VoxelWorld::bakeVoxelLightFromPoint(VoxelCordinates coords) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
VoxelCordinates min = VoxelCordinates(coords.x - 16, coords.y - 16, coords.z - 16);
|
|
||||||
VoxelCordinates max = VoxelCordinates(coords.x + 16, coords.y + 16, coords.z + 16);
|
|
||||||
|
|
||||||
worldProps.clampCordinates(min);
|
|
||||||
worldProps.clampCordinates(max);
|
|
||||||
|
|
||||||
bakeVoxelLight(min, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::bakeVoxelLight(VoxelCordinates min, VoxelCordinates max) {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
// We want to make the box 1 layer smaller
|
|
||||||
// For every axis, X & Y & Z
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
min[i]++;
|
|
||||||
max[i]--;
|
|
||||||
}
|
|
||||||
ChunkID minChunkID;
|
|
||||||
ChunkID maxChunkID;
|
|
||||||
ChunkVoxelID minChunkVoxelID;
|
|
||||||
ChunkVoxelID maxChunkVoxelID;
|
|
||||||
|
|
||||||
extractChunkCordinates(min, minChunkID, minChunkVoxelID);
|
|
||||||
extractChunkCordinates(max, maxChunkID, maxChunkVoxelID);
|
|
||||||
|
|
||||||
tmp_voxelLightSource.clear();
|
|
||||||
|
|
||||||
// We want to empty the voxel light of the section first
|
|
||||||
ChunkID workingChunkID;
|
|
||||||
for (workingChunkID.x = minChunkID.x; workingChunkID.x <= maxChunkID.x;
|
|
||||||
workingChunkID.x++) {
|
|
||||||
for (workingChunkID.y = minChunkID.y;
|
|
||||||
workingChunkID.y <= maxChunkID.y; workingChunkID.y++) {
|
|
||||||
for (workingChunkID.z = minChunkID.z;
|
|
||||||
workingChunkID.z <= maxChunkID.z; workingChunkID.z++) {
|
|
||||||
ChunkVoxelID workingMinVoxelID(
|
|
||||||
(workingChunkID.x == minChunkID.x) ? minChunkVoxelID.x
|
|
||||||
: 0,
|
|
||||||
(workingChunkID.y == minChunkID.y) ? minChunkVoxelID.y
|
|
||||||
: 0,
|
|
||||||
(workingChunkID.z == minChunkID.z) ? minChunkVoxelID.z
|
|
||||||
: 0);
|
|
||||||
ChunkVoxelID workingMaxVoxelID(
|
|
||||||
(workingChunkID.x == maxChunkID.x) ? maxChunkVoxelID.x
|
|
||||||
: CHUNK_SIZE_X - 1,
|
|
||||||
(workingChunkID.y == maxChunkID.y) ? maxChunkVoxelID.y
|
|
||||||
: CHUNK_SIZE_Y - 1,
|
|
||||||
(workingChunkID.z == maxChunkID.z) ? maxChunkVoxelID.z
|
|
||||||
: CHUNK_SIZE_Z - 1);
|
|
||||||
|
|
||||||
Chunk& workingChunk =
|
|
||||||
chunks[worldProps.getWorldChunkID(workingChunkID)];
|
|
||||||
workingChunk.clearVoxelLightAndSaveSources(
|
|
||||||
workingMinVoxelID, workingMaxVoxelID, workingChunkID,
|
|
||||||
tmp_voxelLightSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cover all 6 edges with light propagation
|
|
||||||
for (int x = min.x; x <= max.x; x++) {
|
|
||||||
for (int y = min.y; y <= max.y; y++) {
|
|
||||||
VoxelCordinates minZEdge(x, y, min.z - 1);
|
|
||||||
VoxelCordinates maxZEdge(x, y, max.z + 1);
|
|
||||||
|
|
||||||
VoxelLight minZEdgeLight = readLight(minZEdge);
|
|
||||||
VoxelLight maxZEdgeLight = readLight(maxZEdge);
|
|
||||||
|
|
||||||
if (minZEdgeLight.b_light || minZEdgeLight.g_light ||
|
|
||||||
minZEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(minZEdge);
|
|
||||||
if (maxZEdgeLight.b_light || maxZEdgeLight.g_light ||
|
|
||||||
maxZEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(maxZEdge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = min.x; x <= max.x; x++) {
|
|
||||||
for (int z = min.z; z <= max.z; z++) {
|
|
||||||
VoxelCordinates minYEdge(x, min.y - 1, z);
|
|
||||||
VoxelCordinates maxYEdge(x, max.y + 1, z);
|
|
||||||
|
|
||||||
VoxelLight minYEdgeLight = readLight(minYEdge);
|
|
||||||
VoxelLight maxYEdgeLight = readLight(maxYEdge);
|
|
||||||
|
|
||||||
if (minYEdgeLight.b_light || minYEdgeLight.g_light ||
|
|
||||||
minYEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(minYEdge);
|
|
||||||
if (maxYEdgeLight.b_light || maxYEdgeLight.g_light ||
|
|
||||||
maxYEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(maxYEdge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = min.y; y <= max.y; y++) {
|
|
||||||
for (int z = min.z; z <= max.z; z++) {
|
|
||||||
VoxelCordinates minXEdge(min.x - 1, y, z);
|
|
||||||
VoxelCordinates maxXEdge(max.x + 1, y, z);
|
|
||||||
|
|
||||||
VoxelLight minXEdgeLight = readLight(minXEdge);
|
|
||||||
VoxelLight maxXEdgeLight = readLight(maxXEdge);
|
|
||||||
|
|
||||||
if (minXEdgeLight.b_light || minXEdgeLight.g_light ||
|
|
||||||
minXEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(minXEdge);
|
|
||||||
if (maxXEdgeLight.b_light || maxXEdgeLight.g_light ||
|
|
||||||
maxXEdgeLight.b_light)
|
|
||||||
voxelLightPropagation.push(maxXEdge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (VoxelCordinates& cordinates : tmp_voxelLightSource) {
|
|
||||||
VoxelLight& voxelLight = modLight(cordinates);
|
|
||||||
Voxel voxel = readVoxel(cordinates);
|
|
||||||
|
|
||||||
VoxelAspect& voxelAspect = DataStore::voxelsAspect[voxel.id];
|
|
||||||
voxelLight.r_light = voxelAspect.definition.colorEmission.r_value;
|
|
||||||
voxelLight.g_light = voxelAspect.definition.colorEmission.g_value;
|
|
||||||
voxelLight.b_light = voxelAspect.definition.colorEmission.b_value;
|
|
||||||
|
|
||||||
voxelLightPropagation.push(cordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!voxelLightPropagation.empty()) {
|
|
||||||
resolveNextVoxelLightPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelWorld::resolveNextVoxelLightPropagation() {
|
|
||||||
DEER_CORE_ASSERT(initialized, "Voxel World is not initialized");
|
|
||||||
|
|
||||||
VoxelCordinates position = voxelLightPropagation.front();
|
|
||||||
voxelLightPropagation.pop();
|
|
||||||
|
|
||||||
VoxelLight currentLight = readLight(position);
|
|
||||||
bool voxelCheck[6] = {false};
|
|
||||||
|
|
||||||
int highestRGBValue = currentLight.r_light;
|
|
||||||
if (highestRGBValue < currentLight.g_light)
|
|
||||||
highestRGBValue = currentLight.g_light;
|
|
||||||
if (highestRGBValue < currentLight.b_light)
|
|
||||||
highestRGBValue = currentLight.b_light;
|
|
||||||
|
|
||||||
int proportionalDecrease =
|
|
||||||
(LIGHT_PROPAGATION_SIMPLE_FALL * 100) / highestRGBValue;
|
|
||||||
|
|
||||||
int nextLightRedMinValue =
|
|
||||||
currentLight.r_light -
|
|
||||||
(proportionalDecrease * currentLight.r_light) / 100;
|
|
||||||
int nextLightGreenMinValue =
|
|
||||||
currentLight.g_light -
|
|
||||||
(proportionalDecrease * currentLight.g_light) / 100;
|
|
||||||
int nextLightBlueMinValue =
|
|
||||||
currentLight.b_light -
|
|
||||||
(proportionalDecrease * currentLight.b_light) / 100;
|
|
||||||
|
|
||||||
// Check for every simple dir
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
VoxelCordinates next(position.x + NORMAL_DIR(X_AXIS, i),
|
|
||||||
position.y + NORMAL_DIR(Y_AXIS, i),
|
|
||||||
position.z + NORMAL_DIR(Z_AXIS, i));
|
|
||||||
|
|
||||||
Voxel nextVoxel = readVoxel(next);
|
|
||||||
voxelCheck[i] = nextVoxel.isVoxelType();
|
|
||||||
if (voxelCheck[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelLight& nextLight = modLight(next);
|
|
||||||
|
|
||||||
bool nextVoxelModified = false;
|
|
||||||
if (nextLight.r_light < nextLightRedMinValue) {
|
|
||||||
nextLight.r_light = nextLightRedMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextLight.g_light < nextLightGreenMinValue) {
|
|
||||||
nextLight.g_light = nextLightGreenMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextLight.b_light < nextLightBlueMinValue) {
|
|
||||||
nextLight.b_light = nextLightBlueMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextVoxelModified)
|
|
||||||
voxelLightPropagation.push(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
// TODO
|
|
||||||
// Check for every complex dir
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
int cDir0 = LIGHT_PROPAGATION_COMPLEX_DIR(0, i);
|
|
||||||
int cDir1 = LIGHT_PROPAGATION_COMPLEX_DIR(1, i);
|
|
||||||
|
|
||||||
if (voxelCheck[cDir0] || voxelCheck[cDir1])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelCordinates next(position.x + NORMAL_DIR(X_AXIS, cDir0) +
|
|
||||||
NORMAL_DIR(X_AXIS, cDir1),
|
|
||||||
position.y + NORMAL_DIR(Y_AXIS, cDir0) +
|
|
||||||
NORMAL_DIR(Y_AXIS, cDir1),
|
|
||||||
position.z + NORMAL_DIR(Z_AXIS, cDir0) +
|
|
||||||
NORMAL_DIR(Z_AXIS, cDir1));
|
|
||||||
|
|
||||||
Voxel nextVoxel = readVoxel(next);
|
|
||||||
if (nextVoxel.isVoxelType())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
VoxelLight& nextLight = modLight(next);
|
|
||||||
int nextLightRedMinValue =
|
|
||||||
currentLight.r_light - LIGHT_PROPAGATION_COMPLEX_FALL;
|
|
||||||
int nextLightGreenMinValue =
|
|
||||||
currentLight.g_light - LIGHT_PROPAGATION_COMPLEX_FALL;
|
|
||||||
int nextLightBlueMinValue =
|
|
||||||
currentLight.b_light - LIGHT_PROPAGATION_COMPLEX_FALL;
|
|
||||||
|
|
||||||
bool nextVoxelModified = false;
|
|
||||||
if (nextLight.r_light < nextLightRedMinValue) {
|
|
||||||
nextLight.r_light = nextLightRedMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextLight.g_light < nextLightGreenMinValue) {
|
|
||||||
nextLight.g_light = nextLightGreenMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextLight.b_light < nextLightBlueMinValue) {
|
|
||||||
nextLight.b_light = nextLightBlueMinValue;
|
|
||||||
nextVoxelModified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextVoxelModified)
|
|
||||||
voxelLightPropagation.push(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Deer
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#include "LinuxWindow.h"
|
#include "LinuxWindow.h"
|
||||||
#include "Deer/Application.h"
|
#include "DeerCore/Application.h"
|
||||||
#include "Deer/Log.h"
|
#include "DeerCore/Log.h"
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user