Changed internal structure
This commit is contained in:
parent
54f8156b6b
commit
67b316a70b
@ -19,9 +19,12 @@ project "DeerService"
|
||||
"vendor/entt/include",
|
||||
"vendor/cereal/include",
|
||||
"vendor/angelScript/include",
|
||||
"vendor/smallVector"
|
||||
"vendor/smallVector",
|
||||
"vendor/enet/include"
|
||||
}
|
||||
|
||||
links {"enet"}
|
||||
|
||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||
objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}")
|
||||
|
||||
|
||||
@ -6,8 +6,8 @@ project "Deer"
|
||||
staticruntime "off"
|
||||
|
||||
files {
|
||||
"src/Deer/**.h",
|
||||
"src/Deer/**.cpp",
|
||||
"src/DeerCore/**.h",
|
||||
"src/DeerCore/**.cpp",
|
||||
"src/DeerRender/**.h",
|
||||
"src/DeerRender/**.cpp",
|
||||
"src/Plattform/OpenGL/**.h",
|
||||
@ -35,7 +35,8 @@ project "Deer"
|
||||
"vendor/cereal/include",
|
||||
"vendor/objload/include/objload",
|
||||
"vendor/angelScript/include",
|
||||
"vendor/smallVector"
|
||||
"vendor/smallVector",
|
||||
"vendor/enet/include"
|
||||
}
|
||||
|
||||
targetdir ("../bin/" .. OutputDir .. "/%{prj.name}")
|
||||
@ -81,7 +82,8 @@ project "Deer"
|
||||
"gdk_pixbuf-2.0", -- GDK Pixbuf library
|
||||
"gio-2.0", -- GIO library
|
||||
"gobject-2.0", -- GObject library
|
||||
"pthread" -- POSIX threads library
|
||||
"pthread", -- POSIX threads library
|
||||
"enet"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,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
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
namespace Deer {
|
||||
class ImGuiLayer;
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Tools/SmallVector.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/SmallVector.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <stdint.h>
|
||||
@ -9,7 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/quaternion.hpp"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Tools/TypeDefs.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@ -3,7 +3,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
#define DEER_RESOURCE_PATH "Assets"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "Deer/Components.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Resource.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Resource.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
@ -63,7 +63,7 @@ namespace Deer {
|
||||
// Obtains the entity that is on the root of the environment
|
||||
inline Entity& getRoot() { return getEntity(0); }
|
||||
#ifdef DEER_RENDER
|
||||
void render(SceneCamera& camera);
|
||||
void render(const SceneCamera& camera);
|
||||
#endif
|
||||
Scope<entt::registry> m_registry;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "spdlog/sinks/stdout_color_sinks.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
|
||||
#include "Deer/DataManagment.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "Deer/Tools/TypeDefs.h"
|
||||
#include "DeerCore/DataManagment.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <unordered_map>
|
||||
@ -1,19 +1,9 @@
|
||||
#pragma once
|
||||
#include "Deer/DataStore.h"
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/Tools/Path.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/GizmoRenderer.h"
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
namespace Deer {
|
||||
class Environment;
|
||||
class SceneCamera;
|
||||
class GizmoRenderer;
|
||||
|
||||
// A scene is a 3d simulation with its environment and voxel world in case
|
||||
@ -33,19 +23,10 @@ namespace Deer {
|
||||
#ifdef DEER_RENDER
|
||||
// This function renders with the default camera in the environment
|
||||
void render();
|
||||
void render(SceneCamera);
|
||||
void render(const SceneCamera&);
|
||||
|
||||
extern GizmoRenderer gizmoRenderer;
|
||||
#endif
|
||||
extern Environment environment;
|
||||
} // namespace Scene
|
||||
|
||||
// Namespace to manage scenes in memory
|
||||
namespace DataStore {
|
||||
void loadScene(const Path& name);
|
||||
void exportScene(const Path& name);
|
||||
|
||||
void exportRuntimeScene();
|
||||
void importRuntimeScene();
|
||||
} // namespace DataStore
|
||||
} // namespace Deer
|
||||
@ -1,4 +1,4 @@
|
||||
#include "Deer/Application.h"
|
||||
#include "DeerCore/Application.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/Events/ApplicationEvent.h"
|
||||
@ -7,8 +7,8 @@
|
||||
#endif
|
||||
|
||||
namespace Deer {
|
||||
namespace Application {
|
||||
using EventFunction = void(*)(Event&);
|
||||
namespace Application {
|
||||
using EventFunction = void (*)(Event&);
|
||||
|
||||
void initWindow();
|
||||
void shutdownWindow();
|
||||
@ -17,5 +17,5 @@ namespace Deer {
|
||||
void setEventCallback(EventFunction);
|
||||
|
||||
Window& getWindow();
|
||||
}
|
||||
}
|
||||
} // namespace Application
|
||||
} // namespace Deer
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Components.h"
|
||||
#include "DeerCore/Components.h"
|
||||
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Shader.h"
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/DataManagment.h"
|
||||
#include "DeerCore/DataManagment.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/DataStore.h"
|
||||
#include "DeerCore/DataStore.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#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
|
||||
#include "Deer/Application.h"
|
||||
#include "DeerCore/Application.h"
|
||||
|
||||
namespace Deer {
|
||||
class Input {
|
||||
public:
|
||||
public:
|
||||
static bool isKeyPressed(unsigned int key);
|
||||
static bool isMouseButtonPressed(int button);
|
||||
static void getMousePos(float& x, float& y);
|
||||
};
|
||||
} // namespace Deer
|
||||
} // namespace Deer
|
||||
|
||||
// From GLFW
|
||||
#define DEER_KEY_SPACE 32
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Log.h"
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Log.h"
|
||||
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
enum class TextureBufferType {
|
||||
@ -18,12 +18,12 @@ namespace Deer {
|
||||
|
||||
bool swapChainTarget = false;
|
||||
FrameBufferSpecification(unsigned int _width, unsigned int _height, std::initializer_list<TextureBufferType> _frameBufferTextures, unsigned int _samples = 1, bool _swapChainTarget = false)
|
||||
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
||||
: width(_width), height(_height), samples(_samples), frameBufferTextures(_frameBufferTextures), swapChainTarget(_swapChainTarget) {
|
||||
}
|
||||
};
|
||||
|
||||
class FrameBuffer {
|
||||
public:
|
||||
public:
|
||||
virtual ~FrameBuffer() = default;
|
||||
virtual const FrameBufferSpecification& getSpecification() = 0;
|
||||
|
||||
@ -40,5 +40,4 @@ namespace Deer {
|
||||
|
||||
static FrameBuffer* create(const FrameBufferSpecification& spec);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Deer
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Resource.h"
|
||||
#include "DeerCore/Resource.h"
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Scene.h"
|
||||
#include "DeerCore/Scene.h"
|
||||
#include "DeerRender/Components.h"
|
||||
|
||||
namespace Deer {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerRender/Render/Shader.h"
|
||||
#include "DeerRender/Resource.h"
|
||||
|
||||
@ -22,6 +22,11 @@ namespace Deer {
|
||||
}
|
||||
};
|
||||
|
||||
namespace RenderUtils {
|
||||
void initializeRenderUtils();
|
||||
void deinitializeRenderUtils();
|
||||
} // namespace RenderUtils
|
||||
|
||||
template <>
|
||||
class ResourceBuilder<Shader> {
|
||||
public:
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/SmallVector.h"
|
||||
#include "DeerCore/Tools/SmallVector.h"
|
||||
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include "Deer/Tools/TypeDefs.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
@ -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
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerRender/Events/Event.h"
|
||||
|
||||
#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 {
|
||||
std::shared_ptr<spdlog::logger> Log::coreLogger;
|
||||
@ -1,13 +1,13 @@
|
||||
#include "Deer/DataStore.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/DataStore.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/types/unordered_map.hpp"
|
||||
|
||||
#include "Deer/DataStore/DataStructure.h"
|
||||
#include "Deer/DataStore/DataStructureSerialization.h"
|
||||
#include "DeerCore/DataStore/DataStructure.h"
|
||||
#include "DeerCore/DataStore/DataStructureSerialization.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
namespace Deer {
|
||||
struct DataStructure {
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Deer/DataStore/DataStructure.h"
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/DataStore/DataStructure.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
@ -1,4 +1,4 @@
|
||||
#include "Deer/Tools/Path.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include <algorithm>
|
||||
|
||||
Deer::Path Deer::toLowerCasePath(const Path& inputPath) {
|
||||
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
96
Deer/src/DeerCore/Network/Server.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Network.h"
|
||||
|
||||
#include "enet/enet.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
namespace Network {
|
||||
ServerSettings serverSettings;
|
||||
ENetHost* enetServer;
|
||||
|
||||
void clientConnect(ENetPeer* refPeer);
|
||||
void clientDisconnect(ENetPeer* refPeer);
|
||||
void clientData(ENetPeer* peer, ENetPacket* packet);
|
||||
|
||||
// Fixed array of clients, defined by max player count
|
||||
Scope<DeerClient[]> clients;
|
||||
} // namespace Network
|
||||
|
||||
void Network::initServer(const ServerSettings& config) {
|
||||
serverSettings = config;
|
||||
if (enet_initialize() != 0) {
|
||||
DEER_CORE_ERROR("An error ocurred while initing enet");
|
||||
return;
|
||||
}
|
||||
ENetAddress serverAddress;
|
||||
|
||||
serverAddress.host = ENET_HOST_ANY;
|
||||
serverAddress.port = config.port;
|
||||
|
||||
enetServer = enet_host_create(&serverAddress, config.maxClients, 2, config.maxOutgoingBand, config.maxIncomingBand);
|
||||
if (!enetServer) {
|
||||
DEER_CORE_ERROR("An error ocurred while initing server");
|
||||
return;
|
||||
}
|
||||
|
||||
clients = MakeScope<DeerClient[]>(serverSettings.maxClients);
|
||||
}
|
||||
|
||||
void Network::shutdownServer() {
|
||||
enet_deinitialize();
|
||||
}
|
||||
|
||||
void Network::flushServerEvents() {
|
||||
ENetEvent event;
|
||||
while (enet_host_service(enetServer, &event, 0) > 0) {
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
clientConnect(event.peer);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
clientData(event.peer, event.packet);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
clientDisconnect(event.peer);
|
||||
break;
|
||||
case ENET_EVENT_TYPE_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Network::clientConnect(ENetPeer* peer) {
|
||||
DeerClient* client = nullptr;
|
||||
int clientId = -1;
|
||||
for (int i = 0; i < serverSettings.maxClients; i++) {
|
||||
if (clients[i].clientState == DeerClientState::NotConnected) {
|
||||
client = &client[i];
|
||||
clientId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
DEER_CORE_ERROR("Server full, critical error");
|
||||
enet_peer_disconnect(peer, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
client->clientState = DeerClientState::Connected;
|
||||
client->internalPeer = peer;
|
||||
peer->data = client;
|
||||
}
|
||||
|
||||
void Network::clientDisconnect(ENetPeer* peer) {
|
||||
DeerClient& client = *(DeerClient*)peer->data;
|
||||
client.clientState = DeerClientState::NotConnected;
|
||||
client.internalPeer = nullptr;
|
||||
}
|
||||
|
||||
void Network::clientData(ENetPeer* peer, ENetPacket* packetData) {
|
||||
}
|
||||
} // namespace Deer
|
||||
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 "Deer/Enviroment.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Enviroment.h"
|
||||
#include "DeerCore/Log.h"
|
||||
|
||||
namespace Deer {
|
||||
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 "Deer/Components.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Application.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerRender/Render/Render.h"
|
||||
#include "DeerRender/Render/RenderUtils.h"
|
||||
#include "DeerRender/Render/Texture.h"
|
||||
|
||||
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 "Deer/Enviroment.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "Deer/Tools/Memory.h"
|
||||
#include "Deer/VoxelWorld.h"
|
||||
#include "Deer/Voxels/Chunk.h"
|
||||
#include "Deer/Voxels/Layer.h"
|
||||
#include "Deer/Voxels/VoxelWorldData.h"
|
||||
|
||||
#include "Deer/Enviroment.h"
|
||||
#include "Deer/Scene/SceneData.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Enviroment.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Scene/SceneData.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/FrameBuffer.h"
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Shader.h"
|
||||
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
|
||||
#endif
|
||||
|
||||
namespace Deer {
|
||||
void Scene::clear() {
|
||||
environment.clear();
|
||||
VoxelWorld::clear();
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
ResourceManager<Shader>::unloadResources();
|
||||
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
|
||||
#include "Deer/Tools/Memory.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/GizmoRenderer.h"
|
||||
#endif
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
namespace Deer {
|
||||
class Environment;
|
||||
@ -11,10 +7,6 @@ namespace Deer {
|
||||
namespace Scene {
|
||||
extern Environment environment;
|
||||
extern bool isExecuting;
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
extern GizmoRenderer gizmoRenderer;
|
||||
#endif
|
||||
} // namespace Scene
|
||||
|
||||
} // namespace Deer
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "Deer/Components.h"
|
||||
#include "DeerCore/Components.h"
|
||||
|
||||
namespace Deer {
|
||||
// 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
|
||||
|
||||
#include "Deer/Components.h"
|
||||
#include "Deer/Enviroment.h"
|
||||
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Enviroment.h"
|
||||
#include "DeerCore/Scene/Serialization/SerializationGlobalVars.h"
|
||||
#include "EntitySerializationStruct.h"
|
||||
|
||||
namespace Deer {
|
||||
@ -2,7 +2,7 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "Deer/Enviroment.h"
|
||||
#include "DeerCore/Enviroment.h"
|
||||
#include "EntitySerializationStruct.h"
|
||||
|
||||
namespace Deer {
|
||||
@ -54,4 +54,4 @@ namespace Deer {
|
||||
archive(serializationStruct);
|
||||
}
|
||||
}
|
||||
} // namespace Deer
|
||||
} // namespace Deer
|
||||
@ -5,19 +5,19 @@
|
||||
#include "cereal/types/vector.hpp"
|
||||
|
||||
// Serialization Vars
|
||||
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
|
||||
#include "DeerCore/Scene/Serialization/SerializationGlobalVars.h"
|
||||
|
||||
// GENERICS
|
||||
#include "Deer/Scene/Serialization/QuatSerialization.h"
|
||||
#include "Deer/Scene/Serialization/Vec3Serialization.h"
|
||||
#include "DeerCore/Scene/Serialization/QuatSerialization.h"
|
||||
#include "DeerCore/Scene/Serialization/Vec3Serialization.h"
|
||||
|
||||
// SCENE SPECIFIC
|
||||
#include "Deer/Scene/Serialization/EntitySerialization.h"
|
||||
#include "Deer/Scene/Serialization/EnvironmentSerialization.h"
|
||||
#include "DeerCore/Scene/Serialization/EntitySerialization.h"
|
||||
#include "DeerCore/Scene/Serialization/EnvironmentSerialization.h"
|
||||
|
||||
// COMPONENTS SPECIFIC
|
||||
#include "Deer/Scene/Serialization/Components/RelationshipComponentSerialization.h"
|
||||
#include "Deer/Scene/Serialization/Components/TransformComponentSerialization.h"
|
||||
#include "DeerCore/Scene/Serialization/Components/RelationshipComponentSerialization.h"
|
||||
#include "DeerCore/Scene/Serialization/Components/TransformComponentSerialization.h"
|
||||
|
||||
// RENDER SPECIFIC
|
||||
#ifdef DEER_RENDER
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
#include "DeerRender/Render/Render.h"
|
||||
#include "DeerRender/Render/RenderCommand.h"
|
||||
#include "DeerRender/Render/RenderUtils.h"
|
||||
|
||||
#include "DeerRender/Log.h"
|
||||
|
||||
@ -46,7 +45,6 @@ namespace Deer {
|
||||
imGuiLayer = MakeScope<ImGuiLayer>();
|
||||
imGuiLayer->onAttach();
|
||||
|
||||
RenderUtils::initializeRenderUtils();
|
||||
RenderCommand::init();
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "RenderUtils.h"
|
||||
#include "DeerRender/Render/VertexArray.h"
|
||||
#include "DeerRender/Render/Buffer.h"
|
||||
#include "DeerRender/Render/Shader.h"
|
||||
#include "DeerRender/Render/VertexArray.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Deer {
|
||||
Scope<VertexArray> genFaceVertexArray();
|
||||
Scope<Shader> getLineShader();
|
||||
Scope<Shader> getFaceShader();
|
||||
}
|
||||
} // namespace RenderUtils
|
||||
|
||||
void RenderUtils::initializeRenderUtils() {
|
||||
m_lineVertexArray = genLineVertexArray();
|
||||
@ -25,8 +25,15 @@ namespace Deer {
|
||||
m_faceShader = getFaceShader();
|
||||
}
|
||||
|
||||
void RenderUtils::deinitializeRenderUtils() {
|
||||
m_lineVertexArray.reset();
|
||||
m_lineShader.reset();
|
||||
m_faceVertexArray.reset();
|
||||
m_faceShader.reset();
|
||||
}
|
||||
|
||||
Scope<VertexArray> RenderUtils::genLineVertexArray() {
|
||||
unsigned int vertices[2] = { 0, 1 };
|
||||
unsigned int vertices[2] = {0, 1};
|
||||
|
||||
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
||||
vertexArray->bind();
|
||||
@ -34,9 +41,7 @@ namespace Deer {
|
||||
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
||||
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(vertices, sizeof(vertices), IndexDataType::Unsigned_Int);
|
||||
|
||||
BufferLayout layout({
|
||||
{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}
|
||||
});
|
||||
BufferLayout layout({{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}});
|
||||
|
||||
vertexBuffer->setLayout(layout);
|
||||
vertexArray->addVertexBuffer(vertexBuffer);
|
||||
@ -87,11 +92,9 @@ void main()
|
||||
|
||||
Scope<VertexArray> RenderUtils::genFaceVertexArray() {
|
||||
unsigned int vertices[4] = {
|
||||
0, 1, 2, 3
|
||||
};
|
||||
0, 1, 2, 3};
|
||||
unsigned int indices[6] = {
|
||||
0, 2, 1, 1, 2, 3
|
||||
};
|
||||
0, 2, 1, 1, 2, 3};
|
||||
|
||||
Scope<VertexArray> vertexArray = Scope<VertexArray>(VertexArray::create());
|
||||
vertexArray->bind();
|
||||
@ -99,9 +102,7 @@ void main()
|
||||
Ref<VertexBuffer> vertexBuffer = VertexBuffer::create(vertices, sizeof(vertices));
|
||||
Ref<IndexBuffer> indexBuffer = IndexBuffer::create(indices, sizeof(indices), IndexDataType::Unsigned_Int);
|
||||
|
||||
BufferLayout layout({
|
||||
{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}
|
||||
});
|
||||
BufferLayout layout({{"a_vertexID", DataType::Unsigned_Int, ShaderDataType::Integer}});
|
||||
|
||||
vertexBuffer->setLayout(layout);
|
||||
vertexArray->addVertexBuffer(vertexBuffer);
|
||||
@ -178,5 +179,5 @@ void main()
|
||||
return Scope<Shader>(Shader::create(vertexSrc, fragmentSrc));
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Deer
|
||||
#endif
|
||||
|
||||
@ -12,5 +12,6 @@ namespace Deer {
|
||||
extern Scope<Shader> m_faceShader;
|
||||
|
||||
void initializeRenderUtils();
|
||||
void deinitializeRenderUtils();
|
||||
} // namespace RenderUtils
|
||||
} // namespace Deer
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include "DeerRender/Application.h"
|
||||
|
||||
#include "DeerRender/Components.h"
|
||||
#include "DeerRender/Voxel.h"
|
||||
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Render/Render.h"
|
||||
@ -14,7 +13,7 @@
|
||||
#include "DeerRender/Log.h"
|
||||
|
||||
namespace Deer {
|
||||
void Environment::render(SceneCamera& camera) {
|
||||
void Environment::render(const SceneCamera& camera) {
|
||||
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));
|
||||
|
||||
@ -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/Enviroment.h"
|
||||
#include "DeerRender/Render/RenderCommand.h"
|
||||
#include "DeerRender/VoxelWorld.h"
|
||||
#include "DeerRender/Scene.h"
|
||||
|
||||
namespace Deer {
|
||||
void Scene::render() {
|
||||
@ -19,15 +19,11 @@ namespace Deer {
|
||||
Scene::render(sceneCamera);
|
||||
}
|
||||
|
||||
void Scene::render(SceneCamera sceneCamera) {
|
||||
void Scene::render(const SceneCamera& sceneCamera) {
|
||||
RenderCommand::setDepthBuffer(true);
|
||||
environment.render(sceneCamera);
|
||||
|
||||
if (VoxelWorld::isInitialized())
|
||||
VoxelWorld::render(sceneCamera);
|
||||
|
||||
RenderCommand::setDepthBuffer(false);
|
||||
gizmoRenderer.render(sceneCamera);
|
||||
}
|
||||
|
||||
} // 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 "Deer/Application.h"
|
||||
#include "Deer/Log.h"
|
||||
#include "DeerCore/Application.h"
|
||||
#include "DeerCore/Log.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