├── src ├── events │ ├── event.cc │ ├── event-keyboard.h │ ├── event-mousemotion.h │ ├── events-pool.h │ ├── keyboard.h │ ├── events-pool.cc │ ├── event.h │ ├── mouse.h │ ├── keyboard.cc │ └── mouse.cc ├── main.cc ├── utils │ ├── time.h │ ├── constants.h │ ├── time.cc │ ├── random.h │ ├── log.h │ └── random.cc ├── texture │ ├── atlas-texture.cc │ ├── atlas-texture.h │ ├── sky-texture.h │ ├── stars-texture.h │ ├── texture-2d.h │ ├── texture-cube.h │ ├── sky-texture.cc │ ├── stars-texture.cc │ ├── texture.h │ ├── texture.cc │ ├── texture-2d.cc │ └── texture-cube.cc ├── shader │ ├── sun-shader.h │ ├── moon-shader.h │ ├── basic-shader.h │ ├── cloud-shader.h │ ├── stars-shader.h │ ├── water-shader.h │ ├── skybox-shader.h │ ├── skyboxtex-shader.h │ ├── underwater-shader.h │ ├── skybox-shader.cc │ ├── sun-shader.cc │ ├── moon-shader.cc │ ├── underwater-shader.cc │ ├── basic-shader.cc │ ├── cloud-shader.cc │ ├── stars-shader.cc │ ├── water-shader.cc │ ├── skyboxtex-shader.cc │ ├── shader.h │ └── shader.cc ├── world │ ├── environnement │ │ ├── tree.h │ │ └── tree.cc │ ├── block │ │ ├── block-type.h │ │ ├── block-base.h │ │ ├── block.cc │ │ ├── block.h │ │ ├── block-props.h │ │ ├── block-base.cc │ │ └── block-props.cc │ ├── biome │ │ ├── biome.cc │ │ ├── mountain-biome.h │ │ ├── grassland-biome.h │ │ ├── biome.h │ │ ├── grassland-biome.cc │ │ └── mountain-biome.cc │ ├── player.h │ ├── chunk │ │ ├── chunk-manager.h │ │ ├── mesh.h │ │ ├── superchunk.h │ │ ├── chunk-manager.cc │ │ ├── chunk.h │ │ ├── mesh.cc │ │ ├── superchunk.cc │ │ └── chunk.cc │ ├── noise-generator.h │ ├── world-generator.h │ ├── world.h │ ├── noise-generator.cc │ ├── player.cc │ ├── world-generator.cc │ └── world.cc ├── maths │ ├── glm.h │ ├── general.h │ ├── general.cc │ ├── vector.h │ ├── type.h │ └── type.cc ├── vertex │ ├── vertex-buffer.h │ ├── index-buffer.h │ ├── vertex-array.h │ ├── vertex-buffer.cc │ ├── index-buffer.cc │ ├── vertex-buffer-layout.cc │ ├── vertex-buffer-layout.h │ └── vertex-array.cc ├── core │ ├── view-frustum.h │ ├── camera.h │ ├── window.h │ ├── model.h │ ├── application.h │ ├── entity.h │ ├── camera.cc │ ├── model.cc │ ├── view-frustum.cc │ ├── entity.cc │ ├── application.cc │ └── window.cc └── renderer │ ├── underwater-renderer.h │ ├── chunk-renderer.h │ ├── cloud-renderer.h │ ├── water-renderer.h │ ├── renderer.h │ ├── underwater-renderer.cc │ ├── sky-renderer.h │ ├── cloud-renderer.cc │ ├── water-renderer.cc │ ├── chunk-renderer.cc │ ├── renderer.cc │ └── sky-renderer.cc ├── .gitignore ├── res ├── blocks │ ├── sun.block │ ├── cloud.block │ ├── dirt.block │ ├── leaf.block │ ├── moon.block │ ├── sand.block │ ├── stone.block │ ├── water.block │ ├── wood.block │ ├── plant.block │ ├── flower-yellow.block │ └── grass.block ├── textures │ ├── atlas.png │ ├── atlas.xcf │ ├── sky │ │ ├── sky_top.png │ │ ├── sky_side.png │ │ └── sky_bottom.png │ └── stars │ │ ├── stars_side.png │ │ ├── stars_top.png │ │ └── stars_bottom.png └── shaders │ ├── underwater.shader │ ├── cloud.shader │ ├── sun.shader │ ├── moon.shader │ ├── skybox.shader │ ├── water.shader │ ├── stars.shader │ ├── basic.shader │ └── skyboxtex.shader ├── main ├── lib └── stb_image.a ├── include └── stb_image │ └── stb_image.cc ├── Makefile └── README.md /src/events/event.cc: -------------------------------------------------------------------------------- 1 | #include "event.h" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | .vscode 3 | .settings -------------------------------------------------------------------------------- /res/blocks/sun.block: -------------------------------------------------------------------------------- 1 | TexAll: 8 1 2 | Collidable: 0 3 | Opaque: 1 -------------------------------------------------------------------------------- /main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/main -------------------------------------------------------------------------------- /res/blocks/cloud.block: -------------------------------------------------------------------------------- 1 | TexAll: 8 0 2 | Collidable: 0 3 | Opaque: 0 -------------------------------------------------------------------------------- /res/blocks/dirt.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 2 2 | Collidable: 1 3 | Opaque: 0 -------------------------------------------------------------------------------- /res/blocks/leaf.block: -------------------------------------------------------------------------------- 1 | TexAll: 8 3 2 | Collidable: 1 3 | Opaque: 1 -------------------------------------------------------------------------------- /res/blocks/moon.block: -------------------------------------------------------------------------------- 1 | TexAll: 8 2 2 | Collidable: 0 3 | Opaque: 1 -------------------------------------------------------------------------------- /res/blocks/sand.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 9 2 | Collidable: 1 3 | Opaque: 0 -------------------------------------------------------------------------------- /res/blocks/stone.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 4 2 | Collidable: 1 3 | Opaque: 0 -------------------------------------------------------------------------------- /res/blocks/water.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 3 2 | Collidable: 0 3 | Opaque: 1 -------------------------------------------------------------------------------- /res/blocks/wood.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 6 2 | Collidable: 1 3 | Opaque: 0 -------------------------------------------------------------------------------- /res/blocks/plant.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 8 2 | Type: 2 3 | Collidable: 0 4 | Opaque: 0 -------------------------------------------------------------------------------- /lib/stb_image.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/lib/stb_image.a -------------------------------------------------------------------------------- /res/blocks/flower-yellow.block: -------------------------------------------------------------------------------- 1 | TexAll: 9 5 2 | Type: 1 3 | Collidable: 0 4 | Opaque: 0 -------------------------------------------------------------------------------- /include/stb_image/stb_image.cc: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "stb_image.h" -------------------------------------------------------------------------------- /res/blocks/grass.block: -------------------------------------------------------------------------------- 1 | TexTop: 9 0 2 | TexSide: 9 1 3 | TexBottom: 9 2 4 | Collidable: 1 5 | Opaque: 0 -------------------------------------------------------------------------------- /res/textures/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/atlas.png -------------------------------------------------------------------------------- /res/textures/atlas.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/atlas.xcf -------------------------------------------------------------------------------- /res/textures/sky/sky_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/sky/sky_top.png -------------------------------------------------------------------------------- /res/textures/sky/sky_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/sky/sky_side.png -------------------------------------------------------------------------------- /res/textures/sky/sky_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/sky/sky_bottom.png -------------------------------------------------------------------------------- /res/textures/stars/stars_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/stars/stars_side.png -------------------------------------------------------------------------------- /res/textures/stars/stars_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/stars/stars_top.png -------------------------------------------------------------------------------- /src/main.cc: -------------------------------------------------------------------------------- 1 | #include "core/application.h" 2 | 3 | int main(void) 4 | { 5 | Application::Run(); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /res/textures/stars/stars_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvingcode/Minecraft/HEAD/res/textures/stars/stars_bottom.png -------------------------------------------------------------------------------- /src/utils/time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Time{ 6 | std::chrono::milliseconds GetMTime(); 7 | } -------------------------------------------------------------------------------- /src/texture/atlas-texture.cc: -------------------------------------------------------------------------------- 1 | #include "atlas-texture.h" 2 | 3 | AtlasTexture::AtlasTexture(): Texture2d("res/textures/atlas.png"){ 4 | } -------------------------------------------------------------------------------- /src/texture/atlas-texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "texture-2d.h" 3 | 4 | class AtlasTexture: public Texture2d{ 5 | public: 6 | AtlasTexture(); 7 | }; -------------------------------------------------------------------------------- /src/texture/sky-texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "texture-cube.h" 3 | 4 | class SkyTexture : public TextureCube { 5 | public: 6 | SkyTexture(); 7 | }; -------------------------------------------------------------------------------- /src/shader/sun-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class SunShader : public Shader{ 5 | public: 6 | SunShader(); 7 | ~SunShader(); 8 | }; -------------------------------------------------------------------------------- /src/texture/stars-texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "texture-cube.h" 3 | 4 | class StarsTexture : public TextureCube { 5 | public: 6 | StarsTexture(); 7 | }; -------------------------------------------------------------------------------- /src/shader/moon-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class MoonShader : public Shader{ 5 | public: 6 | MoonShader(); 7 | ~MoonShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/basic-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class BasicShader : public Shader{ 5 | public: 6 | BasicShader(); 7 | ~BasicShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/cloud-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class CloudShader : public Shader{ 5 | public: 6 | CloudShader(); 7 | ~CloudShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/stars-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class StarsShader : public Shader{ 5 | public: 6 | StarsShader(); 7 | ~StarsShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/water-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class WaterShader : public Shader{ 5 | public: 6 | WaterShader(); 7 | ~WaterShader(); 8 | }; -------------------------------------------------------------------------------- /src/utils/constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define CHUNK_SIZE 16 3 | #define SCREEN_WIDTH 1270 4 | #define SCREEN_HEIGHT 800 5 | #define WATER_LEVEL 40 6 | #define SKY_LEVEL 120 -------------------------------------------------------------------------------- /src/shader/skybox-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class SkyBoxShader : public Shader{ 5 | public: 6 | SkyBoxShader(); 7 | ~SkyBoxShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/skyboxtex-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class SkyBoxTexShader : public Shader{ 5 | public: 6 | SkyBoxTexShader(); 7 | ~SkyBoxTexShader(); 8 | }; -------------------------------------------------------------------------------- /src/shader/underwater-shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shader.h" 3 | 4 | class UnderWaterShader : public Shader{ 5 | public: 6 | UnderWaterShader(); 7 | ~UnderWaterShader(); 8 | }; -------------------------------------------------------------------------------- /src/events/event-keyboard.h: -------------------------------------------------------------------------------- 1 | struct EventKeyboard{ 2 | int m_Key, m_Scancode; 3 | EventKeyboard(int key, int scancode): m_Key(key), m_Scancode(scancode){} 4 | EventKeyboard(): m_Key(0), m_Scancode(0){} 5 | }; -------------------------------------------------------------------------------- /src/world/environnement/tree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "maths/glm.h" 3 | #include "utils/random.h" 4 | 5 | class SuperChunk; 6 | 7 | namespace Tree{ 8 | void GenerateOak(SuperChunk& chunk, glm::vec3 tree); 9 | }; -------------------------------------------------------------------------------- /src/events/event-mousemotion.h: -------------------------------------------------------------------------------- 1 | struct EventMouseMotion{ 2 | double m_Xpos; 3 | double m_Ypos; 4 | EventMouseMotion(): m_Xpos(0), m_Ypos(0){} 5 | EventMouseMotion(double xpos, double ypos): m_Xpos(xpos), m_Ypos(ypos){} 6 | }; -------------------------------------------------------------------------------- /src/maths/glm.h: -------------------------------------------------------------------------------- 1 | #include // glm::vec3 2 | #include // glm::vec4 3 | #include // glm::mat4 4 | #include // glm::translate, glm::rotate, glm::scale, glm::perspective -------------------------------------------------------------------------------- /src/utils/time.cc: -------------------------------------------------------------------------------- 1 | #include "time.h" 2 | 3 | namespace Time{ 4 | std::chrono::milliseconds GetMTime(){ 5 | return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); 6 | } 7 | } -------------------------------------------------------------------------------- /src/shader/skybox-shader.cc: -------------------------------------------------------------------------------- 1 | #include "skybox-shader.h" 2 | 3 | SkyBoxShader::SkyBoxShader(): Shader("res/shaders/skybox.shader"){ 4 | Bind(); 5 | } 6 | 7 | SkyBoxShader::~SkyBoxShader(){ 8 | LogTrace("Destructing SkyBoxShader %d...\n", u_ID); 9 | } -------------------------------------------------------------------------------- /src/texture/texture-2d.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "texture.h" 3 | 4 | class Texture2d : public Texture{ 5 | public: 6 | Texture2d(std::string filepath); 7 | void Bind(unsigned int slot = 0) const override; 8 | void Unbind() const override; 9 | }; -------------------------------------------------------------------------------- /src/texture/texture-cube.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "texture.h" 3 | 4 | class TextureCube : public Texture{ 5 | public: 6 | TextureCube(std::string filepath[6]); 7 | void Bind(unsigned int slot = 0) const override; 8 | void Unbind() const override; 9 | }; -------------------------------------------------------------------------------- /src/events/events-pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "event.h" 5 | 6 | class EventsPool{ 7 | public: 8 | void Push(Event* event); 9 | EventsPool(); 10 | Event* PollEvent(); 11 | private: 12 | std::queue events; 13 | }; -------------------------------------------------------------------------------- /src/utils/random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Random{ 5 | public: 6 | static Random& Get(); 7 | void SetSeed(int seed); 8 | int GetIntInRange(int min, int max); 9 | private: 10 | Random(); 11 | std::mt19937 m_Random; 12 | }; -------------------------------------------------------------------------------- /src/shader/sun-shader.cc: -------------------------------------------------------------------------------- 1 | #include "sun-shader.h" 2 | 3 | SunShader::SunShader(): Shader("res/shaders/sun.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | SunShader::~SunShader(){ 9 | LogTrace("Destructing SunShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/shader/moon-shader.cc: -------------------------------------------------------------------------------- 1 | #include "moon-shader.h" 2 | 3 | MoonShader::MoonShader(): Shader("res/shaders/moon.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | MoonShader::~MoonShader(){ 9 | LogTrace("Destructing MoonShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/shader/underwater-shader.cc: -------------------------------------------------------------------------------- 1 | #include "underwater-shader.h" 2 | 3 | UnderWaterShader::UnderWaterShader(): Shader("res/shaders/underwater.shader"){ 4 | Bind(); 5 | } 6 | 7 | UnderWaterShader::~UnderWaterShader(){ 8 | LogTrace("Destructing UnderWaterShader %d...\n", u_ID); 9 | } -------------------------------------------------------------------------------- /src/shader/basic-shader.cc: -------------------------------------------------------------------------------- 1 | #include "basic-shader.h" 2 | 3 | BasicShader::BasicShader(): Shader("res/shaders/basic.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | BasicShader::~BasicShader(){ 9 | LogTrace("Destructing BasicShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/shader/cloud-shader.cc: -------------------------------------------------------------------------------- 1 | #include "cloud-shader.h" 2 | 3 | CloudShader::CloudShader(): Shader("res/shaders/cloud.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | CloudShader::~CloudShader(){ 9 | LogTrace("Destructing CloudShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/shader/stars-shader.cc: -------------------------------------------------------------------------------- 1 | #include "stars-shader.h" 2 | 3 | StarsShader::StarsShader(): Shader("res/shaders/stars.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | StarsShader::~StarsShader(){ 9 | LogTrace("Destructing StarsShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/shader/water-shader.cc: -------------------------------------------------------------------------------- 1 | #include "water-shader.h" 2 | 3 | WaterShader::WaterShader(): Shader("res/shaders/water.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | WaterShader::~WaterShader(){ 9 | LogTrace("Destructing WaterShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/world/block/block-type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum BlockType{ 4 | Air = 0, 5 | Grass, 6 | Dirt, 7 | Water, 8 | Stone, 9 | Wood, 10 | Sand, 11 | Leaf, 12 | Plant, 13 | FlowerYellow, 14 | Cloud, 15 | Sun, 16 | Moon, 17 | 18 | SIZE 19 | }; -------------------------------------------------------------------------------- /src/maths/general.h: -------------------------------------------------------------------------------- 1 | float smoothstep(float edge0, float edge1, float x); 2 | float smoothInterpolation(float bottomLeft, float topLeft, float bottomRight, float topRight, 3 | float xMin, float xMax, 4 | float zMin, float zMax, 5 | float x, float z); -------------------------------------------------------------------------------- /src/shader/skyboxtex-shader.cc: -------------------------------------------------------------------------------- 1 | #include "skyboxtex-shader.h" 2 | 3 | SkyBoxTexShader::SkyBoxTexShader(): Shader("res/shaders/skyboxtex.shader"){ 4 | Bind(); 5 | SetUniform1i("uTexture", 0); 6 | } 7 | 8 | SkyBoxTexShader::~SkyBoxTexShader(){ 9 | LogTrace("Destructing SkyBoxTexShader %d...\n", u_ID); 10 | } -------------------------------------------------------------------------------- /src/events/keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Keyboard{ 6 | 7 | public: 8 | Keyboard() = default; 9 | bool IsKeyPressed(int key); 10 | void SetKeyPressed(int key); 11 | void SetKeyReleased(int key); 12 | private: 13 | std::vector m_Keys; 14 | }; -------------------------------------------------------------------------------- /src/vertex/vertex-buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils/log.h" 4 | #include 5 | 6 | class VertexBuffer{ 7 | 8 | unsigned int u_ID; 9 | 10 | public: 11 | VertexBuffer(const void* data, unsigned int size); 12 | ~VertexBuffer(); 13 | 14 | void Bind() const; 15 | void Unbind() const; 16 | }; -------------------------------------------------------------------------------- /src/world/block/block-base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "block-type.h" 3 | #include "block-props.h" 4 | 5 | class BlockBase{ 6 | public: 7 | static BlockBase* Get(); 8 | BlockProps GetBlockProps(BlockType type); 9 | private: 10 | BlockBase(); 11 | std::array m_Blocks; 12 | static BlockBase* m_Instance; 13 | }; -------------------------------------------------------------------------------- /src/events/events-pool.cc: -------------------------------------------------------------------------------- 1 | #include "events-pool.h" 2 | 3 | EventsPool::EventsPool(){} 4 | 5 | void EventsPool::Push(Event* event){ 6 | events.push(event); 7 | } 8 | 9 | Event* EventsPool::PollEvent(){ 10 | if(!events.empty()){ 11 | Event* event = events.front(); 12 | events.pop(); 13 | return event; 14 | } 15 | return nullptr; 16 | } -------------------------------------------------------------------------------- /src/events/event.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "event-keyboard.h" 4 | #include "event-mousemotion.h" 5 | 6 | enum EventType{ 7 | NONE = 0, 8 | EVENT_QUIT, 9 | EVENT_KEYDOWN, EVENT_KEYUP, 10 | EVENT_MOUSEMOTION, EVENT_MOUSEDOWN, EVENT_MOUSEUP 11 | }; 12 | 13 | struct Event{ 14 | EventType type; 15 | EventKeyboard key; 16 | EventMouseMotion motion; 17 | }; -------------------------------------------------------------------------------- /src/vertex/index-buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils/log.h" 4 | 5 | class IndexBuffer{ 6 | 7 | unsigned int u_ID; 8 | unsigned int m_Count; 9 | 10 | public: 11 | IndexBuffer(const unsigned int* data, unsigned int count); 12 | ~IndexBuffer(); 13 | 14 | void Bind() const; 15 | void Unbind() const; 16 | unsigned int GetCount() const; 17 | }; -------------------------------------------------------------------------------- /src/events/mouse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | enum MouseButton{ 6 | LEFT, 7 | RIGHT 8 | }; 9 | 10 | class Mouse{ 11 | 12 | public: 13 | Mouse() = default; 14 | bool IsButtonPressed(MouseButton key); 15 | void SetButtonPressed(MouseButton key); 16 | void SetButtonReleased(MouseButton key); 17 | private: 18 | std::vector m_Keys; 19 | }; -------------------------------------------------------------------------------- /src/utils/log.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define IsTrace 0 6 | #define ASSERT(x) if(!(x)) __builtin_trap(); 7 | #define CallGL(x) ClearLogs();\ 8 | x;\ 9 | ASSERT(LogCall(#x, __FILE__, __LINE__)) 10 | 11 | void ClearLogs(); 12 | 13 | bool LogCall(std::string function, std::string file, int line); 14 | 15 | #define LogTrace(...) if(IsTrace) printf(__VA_ARGS__) -------------------------------------------------------------------------------- /src/texture/sky-texture.cc: -------------------------------------------------------------------------------- 1 | #include "sky-texture.h" 2 | 3 | SkyTexture::SkyTexture(): TextureCube(new std::string[6]{ 4 | "res/textures/sky/sky_side.png", //front 5 | "res/textures/sky/sky_side.png", //back 6 | "res/textures/sky/sky_top.png", //top 7 | "res/textures/sky/sky_bottom.png", //bottom 8 | "res/textures/sky/sky_side.png", //right 9 | "res/textures/sky/sky_side.png", //left 10 | }){ 11 | } -------------------------------------------------------------------------------- /src/utils/random.cc: -------------------------------------------------------------------------------- 1 | #include "random.h" 2 | 3 | Random& Random::Get(){ 4 | static Random r; 5 | return r; 6 | } 7 | 8 | void Random::SetSeed(int seed){ 9 | m_Random.seed(seed); 10 | } 11 | 12 | Random::Random(){ 13 | m_Random.seed(time(NULL)); 14 | } 15 | 16 | int Random::GetIntInRange(int min, int max){ 17 | auto dist = std::uniform_int_distribution(min,max); 18 | return dist(m_Random); 19 | } -------------------------------------------------------------------------------- /src/world/block/block.cc: -------------------------------------------------------------------------------- 1 | #include "block.h" 2 | 3 | void Block::SetActive(bool active){ 4 | m_Active = active; 5 | } 6 | 7 | void Block::SetBlockType(BlockType type){ 8 | m_Type = type; 9 | } 10 | 11 | void Block::SetFocus(bool focus){ 12 | m_Focus = focus; 13 | } 14 | 15 | BlockProps Block::GetProps(){ 16 | BlockBase* blockBase = BlockBase::Get(); 17 | return blockBase->GetBlockProps(m_Type); 18 | } -------------------------------------------------------------------------------- /src/texture/stars-texture.cc: -------------------------------------------------------------------------------- 1 | #include "stars-texture.h" 2 | 3 | StarsTexture::StarsTexture(): TextureCube(new std::string[6]{ 4 | "res/textures/stars/stars_side.png", //front 5 | "res/textures/stars/stars_side.png", //back 6 | "res/textures/stars/stars_side.png", //top 7 | "res/textures/stars/stars_bottom.png", //bottom 8 | "res/textures/stars/stars_side.png", //right 9 | "res/textures/stars/stars_side.png", //left 10 | }){ 11 | } -------------------------------------------------------------------------------- /src/vertex/vertex-array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils/log.h" 4 | #include "vertex-buffer-layout.h" 5 | #include "vertex-buffer.h" 6 | 7 | class VertexArray{ 8 | unsigned int u_ID; 9 | public: 10 | 11 | VertexArray(); 12 | ~VertexArray(); 13 | 14 | unsigned int getId(){ return u_ID; } 15 | 16 | void AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout); 17 | void Bind() const; 18 | void Unbind() const; 19 | 20 | }; -------------------------------------------------------------------------------- /src/world/biome/biome.cc: -------------------------------------------------------------------------------- 1 | #include "biome.h" 2 | 3 | Biome::Biome(NoiseParameters noiseParam, int treeFreq, int plantFreq, int seed) 4 | : m_TreeFreq(treeFreq) 5 | , m_PlantFreq(plantFreq) 6 | , m_NoiseGenerator(noiseParam, seed){ 7 | } 8 | 9 | int Biome::GetHeight(int x, int z){ 10 | return m_NoiseGenerator.PerlinNoise(x, z); 11 | } 12 | 13 | int Biome::GetTreeFreq(){ 14 | return m_TreeFreq; 15 | } 16 | 17 | int Biome::GetPlantFreq(){ 18 | return m_PlantFreq; 19 | } -------------------------------------------------------------------------------- /src/events/keyboard.cc: -------------------------------------------------------------------------------- 1 | #include "keyboard.h" 2 | 3 | bool Keyboard::IsKeyPressed(int key){ 4 | std::vector::iterator it = std::find(m_Keys.begin(), m_Keys.end(), key); 5 | return it != m_Keys.end(); 6 | } 7 | 8 | void Keyboard::SetKeyPressed(int key){ 9 | if(!IsKeyPressed(key)){ 10 | m_Keys.push_back(key); 11 | } 12 | } 13 | 14 | void Keyboard::SetKeyReleased(int key){ 15 | if(IsKeyPressed(key)){ 16 | std::vector::iterator it = std::find(m_Keys.begin(), m_Keys.end(), key); 17 | m_Keys.erase(it); 18 | } 19 | } -------------------------------------------------------------------------------- /src/texture/texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils/log.h" 4 | 5 | class Texture{ 6 | protected: 7 | unsigned int u_ID; 8 | std::string m_Filepath; 9 | unsigned char* m_LocalBuffer; 10 | int m_Width, m_Height, m_BPP; 11 | 12 | public: 13 | Texture(); 14 | ~Texture(); 15 | 16 | void Load(std::string filepath, bool flip = false); 17 | void Unload(); 18 | virtual void Bind(unsigned int slot = 0) const = 0; 19 | virtual void Unbind() const = 0; 20 | 21 | int GetWidth() const; 22 | int GetHeight() const; 23 | }; -------------------------------------------------------------------------------- /src/world/biome/mountain-biome.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "biome.h" 3 | #include "world/environnement/tree.h" 4 | 5 | class MountainBiome : public Biome{ 6 | public: 7 | MountainBiome(int seed); 8 | void MakeTree(SuperChunk& chunk, glm::vec3 tree) override; 9 | BlockType GetTopBlock() override; 10 | BlockType GetUnderWaterBlock() override; 11 | BlockType GetNearWaterBlock() override; 12 | BlockType GetPlant() override; 13 | BlockType GetBlockInY(int y) override; 14 | private: 15 | NoiseParameters GetNoiseParameters() override; 16 | }; -------------------------------------------------------------------------------- /src/world/biome/grassland-biome.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "biome.h" 3 | #include "world/environnement/tree.h" 4 | 5 | class GrassLandBiome : public Biome{ 6 | public: 7 | GrassLandBiome(int seed); 8 | void MakeTree(SuperChunk& chunk, glm::vec3 tree) override; 9 | BlockType GetTopBlock() override; 10 | BlockType GetUnderWaterBlock() override; 11 | BlockType GetNearWaterBlock() override; 12 | BlockType GetPlant() override; 13 | BlockType GetBlockInY(int y) override; 14 | private: 15 | NoiseParameters GetNoiseParameters() override; 16 | }; -------------------------------------------------------------------------------- /src/core/view-frustum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "maths/glm.h" 3 | #include 4 | 5 | class Entity; 6 | 7 | enum Planes{ 8 | Near, 9 | Far, 10 | Left, 11 | Right, 12 | Top, 13 | Bottom 14 | }; 15 | 16 | struct Plane{ 17 | glm::vec3 normal; 18 | float DistanceToPoint(const glm::vec3& point) const; 19 | float m_DistanceToOrigin; 20 | }; 21 | 22 | class ViewFrustum{ 23 | public: 24 | void Update(const glm::mat4& mat); 25 | bool IsInFrustum(const Entity& element) const; 26 | private: 27 | std::array m_Planes; 28 | }; -------------------------------------------------------------------------------- /src/events/mouse.cc: -------------------------------------------------------------------------------- 1 | #include "mouse.h" 2 | 3 | bool Mouse::IsButtonPressed(MouseButton key){ 4 | std::vector::iterator it = std::find(m_Keys.begin(), m_Keys.end(), key); 5 | return it != m_Keys.end(); 6 | } 7 | 8 | void Mouse::SetButtonPressed(MouseButton key){ 9 | if(!IsButtonPressed(key)){ 10 | m_Keys.push_back(key); 11 | } 12 | } 13 | 14 | void Mouse::SetButtonReleased(MouseButton key){ 15 | if(IsButtonPressed(key)){ 16 | std::vector::iterator it = std::find(m_Keys.begin(), m_Keys.end(), key); 17 | m_Keys.erase(it); 18 | } 19 | } -------------------------------------------------------------------------------- /src/renderer/underwater-renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vertex/vertex-array.h" 3 | #include "vertex/index-buffer.h" 4 | #include "shader/underwater-shader.h" 5 | #include 6 | #include "core/camera.h" 7 | #include "core/model.h" 8 | #include 9 | 10 | class UnderWaterRenderer{ 11 | public: 12 | UnderWaterRenderer(); 13 | ~UnderWaterRenderer(); 14 | void Render(Camera &camera, float time); 15 | private: 16 | std::vector GetRectVertices(const float SIZE); 17 | std::vector GetRectIndices(); 18 | UnderWaterShader m_Shader; 19 | Model m_Model; 20 | }; -------------------------------------------------------------------------------- /src/world/player.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/entity.h" 4 | 5 | class World; 6 | class Window; 7 | 8 | class Player : public Entity { 9 | public: 10 | Player(); 11 | ~Player(); 12 | void Collide(World& world, glm::vec3 velocity); 13 | void Update(World& world); 14 | void Move(glm::vec3 direction); 15 | void Jump(); 16 | void HandleInput(Window& window); 17 | bool IsUnderWater(); 18 | void SetUnderWater(bool underwater); 19 | private: 20 | glm::vec3 m_Acceleration; 21 | bool m_OnGround = true; 22 | bool m_IsFly = false; 23 | bool m_IsUnderWater = false; 24 | }; -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRC_DIR := ./src 2 | OBJ_DIR := ./obj 3 | LIB_DIR := ./lib 4 | TEST_DIR := ./test 5 | SRC_FILES := $(filter-out $(SRC_DIR)/main.cc, $(shell find $(SRC_DIR) -name "*.cc")) 6 | OBJ_FILES := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/%.o,$(SRC_FILES)) 7 | LFLAGS := -lglfw3 -ldl -lGL -lGLU -lGLEW -lX11 -lpthread 8 | SLFLAGS = $(LIB_DIR)/stb_image.a 9 | INCFLAGS = -I./include -I./src 10 | 11 | main: $(SRC_DIR)/main.cc $(OBJ_FILES) 12 | g++ -g $(INCFLAGS) $< -o $@ $(OBJ_FILES) $(LFLAGS) $(SLFLAGS) 13 | 14 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc $(SRC_DIR)/%.h 15 | @mkdir -p $(@D) 16 | g++ -g $(INCFLAGS) -c -o $@ $< 17 | 18 | .PHONY : all 19 | all: main -------------------------------------------------------------------------------- /src/vertex/vertex-buffer.cc: -------------------------------------------------------------------------------- 1 | #include "vertex-buffer.h" 2 | 3 | VertexBuffer::VertexBuffer(const void* data, unsigned int size){ 4 | CallGL(glGenBuffers(1, &u_ID)); 5 | CallGL(glBindBuffer(GL_ARRAY_BUFFER, u_ID)); 6 | CallGL(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); 7 | } 8 | 9 | void VertexBuffer::Bind() const { 10 | CallGL(glBindBuffer(GL_ARRAY_BUFFER, u_ID)); 11 | } 12 | 13 | void VertexBuffer::Unbind() const { 14 | CallGL(glBindBuffer(GL_ARRAY_BUFFER, 0)); 15 | } 16 | 17 | VertexBuffer::~VertexBuffer(){ 18 | LogTrace("Destructing VertexBuffer %d...\n", u_ID); 19 | CallGL(glDeleteBuffers(1, &u_ID)); 20 | } -------------------------------------------------------------------------------- /src/world/block/block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "block-base.h" 3 | 4 | class Block{ 5 | public: 6 | Block(): m_Active(true), m_Focus(false), m_Type(BlockType::Air){} 7 | Block(BlockType type): m_Active(true), m_Focus(false), m_Type(type){} 8 | ~Block(){} 9 | 10 | bool IsActive() { return m_Active; } 11 | bool IsFocus() { return m_Focus; } 12 | void SetActive(bool active); 13 | void SetBlockType(BlockType type); 14 | void SetFocus(bool focus); 15 | BlockType GetType() {return m_Type;} 16 | BlockProps GetProps(); 17 | 18 | private: 19 | bool m_Active; 20 | bool m_Focus; 21 | BlockType m_Type; 22 | }; -------------------------------------------------------------------------------- /src/world/block/block-props.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "maths/vector.h" 3 | #include 4 | #include "block-type.h" 5 | 6 | struct BlockTex{ 7 | std::array front; 8 | std::array back; 9 | std::array left; 10 | std::array right; 11 | std::array bottom; 12 | std::array top; 13 | }; 14 | 15 | enum BlockMeshType{ 16 | Cube, 17 | X, 18 | Star 19 | }; 20 | 21 | struct BlockProps{ 22 | BlockProps(const std::string block); 23 | BlockTex m_TexCoords; 24 | bool m_IsCollidable = false; 25 | bool m_IsOpaque = true; 26 | BlockMeshType m_MeshType; 27 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **PS : The game works only in Linux OS for the moment.** 2 | 3 | Mincraft clone game made from scratch using C++ and Opengl, In ~30 hours challenge. 4 | 5 | ![Image1](https://i.postimg.cc/SKDq8Tyt/minecraft-image-1.png) 6 | ![Image2](https://i.postimg.cc/MT9yCSzb/minecraft-image-2.png) 7 | ![Image3](https://i.postimg.cc/bYbn0kt9/minecraft-image-4.png) 8 | ![Image4](https://i.postimg.cc/Kjcbx1t0/minecraft-image-5.png) 9 | 10 | For Linux : 11 | 12 | 1. Install GLM (download source code and copy it to /usr/include) 13 | 2. Install Glew (Follow steps in https://github.com/nigels-com/glew) 14 | 3. Install Glut (sudo apt-get install freeglut3-dev) 15 | 4. Install GLFW : 16 | 5. Install xorg-dev for X11 -------------------------------------------------------------------------------- /src/renderer/chunk-renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/camera.h" 3 | #include "vertex/vertex-array.h" 4 | #include "vertex/index-buffer.h" 5 | #include "shader/basic-shader.h" 6 | #include "texture/atlas-texture.h" 7 | #include "world/chunk/mesh.h" 8 | 9 | class Chunk; 10 | 11 | class ChunkRenderer{ 12 | public: 13 | ChunkRenderer(); 14 | ~ChunkRenderer(); 15 | void Add(Chunk* chunk); 16 | void Render(Camera &camera, float time); 17 | void RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh); 18 | void Draw(const VertexArray &va, const IndexBuffer &ib) const; 19 | private: 20 | std::vector m_Chunks; 21 | BasicShader m_Shader; 22 | AtlasTexture m_Texture; 23 | }; -------------------------------------------------------------------------------- /src/renderer/cloud-renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/camera.h" 3 | #include "vertex/vertex-array.h" 4 | #include "vertex/index-buffer.h" 5 | #include "shader/cloud-shader.h" 6 | #include "texture/atlas-texture.h" 7 | #include "world/chunk/mesh.h" 8 | 9 | class Chunk; 10 | 11 | class CloudRenderer{ 12 | public: 13 | CloudRenderer(); 14 | ~CloudRenderer(); 15 | void Add(Chunk* chunk); 16 | void Render(Camera &camera, float time); 17 | void RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh); 18 | void Draw(const VertexArray &va, const IndexBuffer &ib) const; 19 | private: 20 | std::vector m_Chunks; 21 | CloudShader m_Shader; 22 | AtlasTexture m_Texture; 23 | }; -------------------------------------------------------------------------------- /src/renderer/water-renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/camera.h" 3 | #include "vertex/vertex-array.h" 4 | #include "vertex/index-buffer.h" 5 | #include "shader/water-shader.h" 6 | #include "texture/atlas-texture.h" 7 | #include "world/chunk/mesh.h" 8 | 9 | class Chunk; 10 | 11 | class WaterRenderer{ 12 | public: 13 | WaterRenderer(); 14 | ~WaterRenderer(); 15 | void Add(Chunk* chunk); 16 | void Render(Camera &camera, float time); 17 | void RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh); 18 | void Draw(const VertexArray &va, const IndexBuffer &ib) const; 19 | private: 20 | std::vector m_Chunks; 21 | WaterShader m_Shader; 22 | AtlasTexture m_Texture; 23 | }; -------------------------------------------------------------------------------- /src/core/camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "entity.h" 3 | #include "world/player.h" 4 | #include "utils/constants.h" 5 | #include "utils/log.h" 6 | #include 7 | #include 8 | #include "view-frustum.h" 9 | 10 | class Player; 11 | 12 | class Camera : public Entity 13 | { 14 | public: 15 | Camera(float fov, float znear, float zfar); 16 | glm::mat4 GetViewMatrix(); 17 | glm::mat4 GetViewMatrixRotation(); 18 | glm::mat4 GetProjectionMatrix(); 19 | glm::vec3 GetRay(); 20 | void Update(Player &player); 21 | void UpdateGeoInfo(Player &player); 22 | const ViewFrustum& GetViewFrustum() const; 23 | ~Camera(); 24 | 25 | private: 26 | float m_Fov, m_Znear, m_Zfar; 27 | Player *m_Player; 28 | ViewFrustum m_ViewFrustum; 29 | }; 30 | -------------------------------------------------------------------------------- /src/core/window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "utils/log.h" 7 | #include 8 | #include 9 | #include "events/keyboard.h" 10 | #include "events/mouse.h" 11 | 12 | class Window{ 13 | public: 14 | static Window* Create(std::string title, int width, int height); 15 | GLFWwindow* GetNativeWindow(); 16 | std::unique_ptr events; 17 | Keyboard m_Keyboard; 18 | Mouse m_Mouse; 19 | void InitEvents(); 20 | void CenterCursor(); 21 | ~Window(); 22 | int GetWidth(); 23 | int GetHeight(); 24 | void SetTitle(std::string title); 25 | private: 26 | int m_Width, m_Height; 27 | std::string m_Title; 28 | GLFWwindow* m_Window; 29 | Window(); 30 | }; -------------------------------------------------------------------------------- /src/texture/texture.cc: -------------------------------------------------------------------------------- 1 | #include "texture.h" 2 | #include "stb_image/stb_image.h" 3 | 4 | Texture::Texture(): u_ID(0), m_LocalBuffer(nullptr), m_Width(0), m_Height(0){ 5 | } 6 | 7 | Texture::~Texture(){ 8 | LogTrace("Destructing Texture %d...\n", u_ID); 9 | CallGL(glDeleteTextures(1, &u_ID)); 10 | } 11 | 12 | void Texture::Load(std::string filepath, bool flip){ 13 | if(flip){ 14 | stbi_set_flip_vertically_on_load(1); 15 | } 16 | m_LocalBuffer = stbi_load(filepath.c_str(), &m_Width, &m_Height, &m_BPP, 4); 17 | 18 | if(!m_LocalBuffer){ 19 | printf("ERROR while reading image %s\n", filepath.c_str()); 20 | exit(EXIT_FAILURE); 21 | } 22 | } 23 | 24 | void Texture::Unload(){ 25 | if(m_LocalBuffer){ 26 | stbi_image_free(m_LocalBuffer); 27 | } 28 | } -------------------------------------------------------------------------------- /src/renderer/renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "maths/glm.h" 7 | #include 8 | #include "world/chunk/chunk.h" 9 | #include "chunk-renderer.h" 10 | #include "water-renderer.h" 11 | #include "cloud-renderer.h" 12 | #include "sky-renderer.h" 13 | #include "underwater-renderer.h" 14 | 15 | class Chunk; 16 | 17 | class Renderer{ 18 | public: 19 | Renderer() = default; 20 | ~Renderer(); 21 | void Render(Camera &camera, float time, bool isUnderWater); 22 | void Clear() const; 23 | void DrawChunk(Chunk* chunk); 24 | private: 25 | SkyRenderer m_SkyRenderer; 26 | ChunkRenderer m_ChunkRenderer; 27 | WaterRenderer m_WaterRenderer; 28 | CloudRenderer m_CloudRenderer; 29 | UnderWaterRenderer m_UnderWaterRenderer; 30 | }; 31 | -------------------------------------------------------------------------------- /src/world/chunk/chunk-manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "maths/vector.h" 5 | #include "superchunk.h" 6 | #include "world/world-generator.h" 7 | 8 | class World; 9 | 10 | using ChunkMap = std::unordered_map; 11 | 12 | class ChunkManager 13 | { 14 | public: 15 | ChunkManager(World *world); 16 | ~ChunkManager(); 17 | ChunkMap &GetChunks(); 18 | SuperChunk& GetChunk(int x, int z); 19 | SuperChunk* GetChunkIfExists(int x, int z); 20 | bool MakeMesh(Camera& camera, int x, int z); 21 | bool LoadMesh(int x, int z); 22 | bool ChunkExistsAt(int x, int z); 23 | void DeleteMeshes(); 24 | void UnLoadChunk(int x, int z); 25 | 26 | private: 27 | ChunkMap m_Chunks; 28 | World* m_World; 29 | WorldGenerator m_WorldGenerator; 30 | }; -------------------------------------------------------------------------------- /src/maths/general.cc: -------------------------------------------------------------------------------- 1 | float smoothstep(float edge0, float edge1, float x) 2 | { 3 | // Scale, bias and saturate x to 0..1 range 4 | x = x * x * (3 - 2 * x); 5 | // Evaluate polynomial 6 | return (edge0 * x) + (edge1 * (1 - x)); 7 | } 8 | 9 | float smoothInterpolation(float bottomLeft, float topLeft, float bottomRight, float topRight, 10 | float xMin, float xMax, 11 | float zMin, float zMax, 12 | float x, float z) 13 | { 14 | float width = xMax - xMin, 15 | height = zMax - zMin; 16 | float xValue = 1 - (x - xMin) / width; 17 | float zValue = 1 - (z - zMin) / height; 18 | float a = smoothstep(bottomLeft, bottomRight, xValue); 19 | float b = smoothstep(topLeft, topRight, xValue); 20 | return smoothstep(a, b, zValue); 21 | } -------------------------------------------------------------------------------- /src/world/noise-generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "utils/constants.h" 5 | #include 6 | 7 | struct NoiseParameters{ 8 | int m_Octaves, m_HeightOffset; 9 | double m_Frequency, m_Amplitude, m_Persistance, m_Smoothness, m_Roughness, m_Scale; 10 | }; 11 | 12 | class NoiseGenerator{ 13 | public: 14 | NoiseGenerator(int seed); 15 | NoiseGenerator(NoiseParameters& noiseParam, int seed); 16 | double Noise(double x, double z); 17 | double GetNoise(int t); 18 | double GetNoise(double x, double z); 19 | double CosineInterpolate(double a, double b, double t); 20 | double PerlinNoise(double x, double z); 21 | void SetParameters(NoiseParameters& noiseParam); 22 | NoiseParameters GetNoiseParameters(); 23 | private: 24 | int m_Seed; 25 | NoiseParameters m_NoiseParameters; 26 | }; -------------------------------------------------------------------------------- /src/world/biome/biome.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../noise-generator.h" 3 | #include "maths/glm.h" 4 | #include "../block/block-type.h" 5 | #include "utils/random.h" 6 | 7 | class SuperChunk; 8 | 9 | class Biome{ 10 | public: 11 | Biome(NoiseParameters noiseParam, int treeFreq, int plantFreq, int seed); 12 | int GetHeight(int x, int z); 13 | int GetTreeFreq(); 14 | int GetPlantFreq(); 15 | virtual void MakeTree(SuperChunk& chunk, glm::vec3 tree) = 0; 16 | virtual BlockType GetTopBlock() = 0; 17 | virtual BlockType GetUnderWaterBlock() = 0; 18 | virtual BlockType GetNearWaterBlock() = 0; 19 | virtual BlockType GetPlant() = 0; 20 | virtual BlockType GetBlockInY(int y) = 0; 21 | protected: 22 | virtual NoiseParameters GetNoiseParameters() = 0; 23 | private: 24 | NoiseGenerator m_NoiseGenerator; 25 | int m_TreeFreq; 26 | int m_PlantFreq; 27 | }; -------------------------------------------------------------------------------- /src/vertex/index-buffer.cc: -------------------------------------------------------------------------------- 1 | #include "index-buffer.h" 2 | #include "renderer/renderer.h" 3 | 4 | IndexBuffer::IndexBuffer(const unsigned int* data, unsigned int count) : m_Count(count){ 5 | ASSERT(sizeof(unsigned int) == sizeof(GLuint)); 6 | CallGL(glGenBuffers(1, &u_ID)); 7 | CallGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, u_ID)); 8 | CallGL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW)); 9 | } 10 | 11 | void IndexBuffer::Bind() const { 12 | CallGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, u_ID)); 13 | } 14 | 15 | void IndexBuffer::Unbind() const { 16 | CallGL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); 17 | } 18 | 19 | IndexBuffer::~IndexBuffer(){ 20 | LogTrace("Destructing IndexBuffer %d...\n", u_ID); 21 | CallGL(glDeleteBuffers(1, &u_ID)); 22 | } 23 | 24 | unsigned int IndexBuffer::GetCount() const{ 25 | return m_Count; 26 | } -------------------------------------------------------------------------------- /src/vertex/vertex-buffer-layout.cc: -------------------------------------------------------------------------------- 1 | #include "vertex-buffer-layout.h" 2 | 3 | VertexBufferLayout::VertexBufferLayout() : m_Stride(0) {} 4 | 5 | VertexBufferLayout::~VertexBufferLayout(){ 6 | LogTrace("Destructing VertexBufferLayout...\n"); 7 | } 8 | 9 | template <> 10 | void VertexBufferLayout::AddAttribute(unsigned int count) 11 | { 12 | m_Elements.push_back({GL_FLOAT, count, GL_FALSE}); 13 | m_Stride += VertextBufferLayoutElement::GetSize(GL_FLOAT) * count; 14 | } 15 | 16 | template <> 17 | void VertexBufferLayout::AddAttribute(unsigned int count) 18 | { 19 | m_Elements.push_back({GL_UNSIGNED_INT, count, GL_FALSE}); 20 | m_Stride += VertextBufferLayoutElement::GetSize(GL_UNSIGNED_INT) * count; 21 | } 22 | 23 | std::vector VertexBufferLayout::GetElements() const{ 24 | return m_Elements; 25 | } 26 | 27 | unsigned int VertexBufferLayout::GetStride() const{ 28 | return m_Stride; 29 | } -------------------------------------------------------------------------------- /src/world/world-generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "noise-generator.h" 4 | #include "maths/glm.h" 5 | #include "maths/general.h" 6 | #include "biome/grassland-biome.h" 7 | #include "biome/mountain-biome.h" 8 | #include "utils/random.h" 9 | 10 | class SuperChunk; 11 | 12 | class WorldGenerator{ 13 | public: 14 | WorldGenerator(); 15 | void GenerateTerrain(SuperChunk& chunk); 16 | void GenerateClouds(SuperChunk& chunk); 17 | private: 18 | SuperChunk* m_Chunk = nullptr; 19 | MountainBiome m_MountainBiome; 20 | GrassLandBiome m_GrassLandBiome; 21 | NoiseGenerator m_BiomeNoise; 22 | NoiseGenerator m_CloudNoise; 23 | void SetBiomeNoiseParams(); 24 | void SetCloudNoiseParams(); 25 | int m_HeightMap[CHUNK_SIZE][CHUNK_SIZE]; 26 | Biome& GetBiome(int x, int z); 27 | int GetHeightIn(int xMin, int zMin, int xMax, int zMax); 28 | int GetHeight(int x, int z); 29 | void GenerateHeightMap(); 30 | }; -------------------------------------------------------------------------------- /src/core/model.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "vertex/vertex-array.h" 4 | #include "vertex/index-buffer.h" 5 | #include "core/entity.h" 6 | #include "core/camera.h" 7 | #include "shader/shader.h" 8 | #include "texture/texture.h" 9 | 10 | class Model : public Entity{ 11 | public: 12 | Model(glm::vec3 position, glm::vec3 rotation, glm::vec3 velocity, std::vector vertices, std::vector indices); 13 | Model(); 14 | ~Model(); 15 | VertexBuffer& GetVBO(); 16 | IndexBuffer& GetIBO(); 17 | VertexArray& GetVAO(); 18 | VertexBufferLayout& GetLayout(); 19 | void Render(Camera& camera, float time, Shader& shader, Texture& texture, const bool blend); 20 | void Render(Camera& camera, float time, Shader& shader, const bool blend); 21 | void Draw(const VertexArray &va, const IndexBuffer &ib); 22 | private: 23 | VertexBuffer m_Vb; 24 | IndexBuffer m_Ib; 25 | VertexArray m_Va; 26 | VertexBufferLayout m_Layout; 27 | }; -------------------------------------------------------------------------------- /src/core/application.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "utils/log.h" 5 | #include "window.h" 6 | #include "renderer/renderer.h" 7 | #include "model.h" 8 | #include "texture/texture.h" 9 | #include "core/camera.h" 10 | #include "world/world.h" 11 | #include "utils/time.h" 12 | 13 | class Application{ 14 | public: 15 | static void Run(); 16 | ~Application(); 17 | private: 18 | static std::unique_ptr m_Instance; 19 | bool m_Running; 20 | Window *m_Window; 21 | World *m_World; 22 | Camera m_Camera; 23 | std::unique_ptr m_Renderer; 24 | bool Init(); 25 | Application(); 26 | static std::unique_ptr& GetInstance(); 27 | static void OnEvent(); 28 | void handleKeyDownEvent(EventKeyboard &key); 29 | void handleMouseMotion(EventMouseMotion &motion); 30 | void handleMouseDown(); 31 | void UpdateTime(); 32 | std::chrono::milliseconds m_StartTime; 33 | int m_OneDayTime; 34 | float m_AppTime; 35 | }; 36 | -------------------------------------------------------------------------------- /src/texture/texture-2d.cc: -------------------------------------------------------------------------------- 1 | #include "texture-2d.h" 2 | 3 | Texture2d::Texture2d(std::string filepath){ 4 | Load(filepath, true); 5 | 6 | CallGL(glGenTextures(1, &u_ID)); 7 | CallGL(glBindTexture(GL_TEXTURE_2D, u_ID)); 8 | 9 | CallGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 10 | CallGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 11 | CallGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 12 | CallGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 13 | 14 | CallGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_LocalBuffer)); 15 | CallGL(glBindTexture(GL_TEXTURE_2D, 0)); 16 | 17 | Unload(); 18 | } 19 | 20 | void Texture2d::Bind(unsigned int slot) const{ 21 | CallGL(glActiveTexture(GL_TEXTURE0 + slot)); 22 | CallGL(glBindTexture(GL_TEXTURE_2D, u_ID)); 23 | } 24 | 25 | void Texture2d::Unbind() const{ 26 | CallGL(glBindTexture(GL_TEXTURE_2D, 0)); 27 | } -------------------------------------------------------------------------------- /src/world/chunk/mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "vertex/vertex-array.h" 6 | #include "vertex/index-buffer.h" 7 | #include "maths/vector.h" 8 | #include "maths/glm.h" 9 | #include 10 | #include "core/entity.h" 11 | 12 | class Mesh{ 13 | public: 14 | Mesh(Entity& model); 15 | ~Mesh(); 16 | std::vector GetIndices(); 17 | std::vector GetVertices(); 18 | VertexBuffer* GetVBO(); 19 | IndexBuffer* GetIBO(); 20 | VertexArray* GetVAO(); 21 | VertexBufferLayout* GetLayout(); 22 | void AddFace(std::array& blockFace, std::array& texCoords, glm::vec3& position, float light); 23 | void UpdateVBO(); 24 | void DeleteMeshes(); 25 | private: 26 | Entity& m_Model; 27 | std::vector m_Vertices; 28 | std::vector m_Indices; 29 | VertexBuffer* m_Vb = nullptr; 30 | IndexBuffer* m_Ib = nullptr; 31 | VertexArray* m_Va = nullptr; 32 | VertexBufferLayout* m_Layout = nullptr; 33 | }; -------------------------------------------------------------------------------- /res/shaders/underwater.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | 9 | out vec2 v_Uv; 10 | 11 | void main(){ 12 | gl_Position = position; 13 | v_Uv = (vec2(position.x, position.y) + 1.0) / 2.0; 14 | }; 15 | 16 | #shader fragment 17 | 18 | #version 130 19 | #extension GL_ARB_explicit_attrib_location : require 20 | #extension GL_ARB_explicit_uniform_location : require 21 | 22 | layout(location = 0) out vec4 color; 23 | 24 | in vec2 v_Uv; 25 | 26 | void main(){ 27 | vec4 colorTop = vec4(0.3, 0.3, 0.7, 0.8); 28 | vec4 colorBottom = vec4(0.7, 0.7, 1.0, 0.3); 29 | float y = v_Uv.y; 30 | float minY = 0.0; 31 | float maxY = 1.0; 32 | y = (y - minY)/(maxY - minY); 33 | if(y > 1.0){ 34 | y = 1.0; 35 | } 36 | if(y < 0.0){ 37 | y = 0.0; 38 | } 39 | vec4 colorResult = colorBottom * (1.0 - y) + colorTop * y; 40 | color = colorResult; 41 | }; -------------------------------------------------------------------------------- /src/world/chunk/superchunk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../world-generator.h" 4 | #include "chunk.h" 5 | 6 | class SuperChunk : public Entity { 7 | public: 8 | SuperChunk() = default; 9 | SuperChunk(glm::vec3 position, World& world): m_World(&world), Entity(position) {} 10 | ~SuperChunk() = default; 11 | bool MakeMesh(Camera& camera); 12 | void SetBlock(int x, int y, int z, BlockType type, bool focus = false); 13 | Block GetBlock(int x, int y, int z); 14 | bool OutOfBounds(int x, int y, int z); 15 | void Draw(Renderer &renderer, Camera& camera); 16 | bool IsLoaded(); 17 | void Load(WorldGenerator& generator); 18 | Chunk& GetChunk(int index); 19 | void AddChunk(); 20 | void AddChunkIndex(int index); 21 | void DeleteMeshes(); 22 | void UpdateVBO(); 23 | int GetTopBlockAt(int x, int z); 24 | private: 25 | std::vector m_Chunks; 26 | bool m_Loaded = false; 27 | World* m_World; 28 | std::array, CHUNK_SIZE> m_TopBlocks = {}; 29 | }; -------------------------------------------------------------------------------- /res/shaders/cloud.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 1) in vec2 texCoord; 9 | layout(location = 2) in float texLight; 10 | 11 | out vec2 v_TexCoord; 12 | uniform mat4 m_MVP; 13 | uniform float uTime; 14 | out vec4 v_texLight; 15 | 16 | void main(){ 17 | vec4 pos = position; 18 | //pos.z += uTime * 100; 19 | gl_Position = m_MVP * pos; 20 | v_TexCoord = texCoord; 21 | v_texLight = vec4(texLight, texLight, texLight, 1.0); 22 | }; 23 | 24 | #shader fragment 25 | 26 | #version 130 27 | #extension GL_ARB_explicit_attrib_location : require 28 | #extension GL_ARB_explicit_uniform_location : require 29 | 30 | layout(location = 0) out vec4 color; 31 | 32 | in vec2 v_TexCoord; 33 | in vec4 v_texLight; 34 | 35 | uniform sampler2D uTexture; 36 | uniform float uTime; 37 | 38 | void main(){ 39 | vec4 texColor = texture(uTexture, v_TexCoord); 40 | color = texColor * v_texLight; 41 | }; -------------------------------------------------------------------------------- /src/renderer/underwater-renderer.cc: -------------------------------------------------------------------------------- 1 | #include "underwater-renderer.h" 2 | 3 | UnderWaterRenderer::UnderWaterRenderer() 4 | : m_Model(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), GetRectVertices(1.0), GetRectIndices()) 5 | {} 6 | 7 | UnderWaterRenderer::~UnderWaterRenderer(){ 8 | LogTrace("Destructing UnderWaterRenderer...\n"); 9 | } 10 | 11 | std::vector UnderWaterRenderer::GetRectIndices(){ 12 | std::vector indices = { 13 | 0, 1, 2, 14 | 2, 3, 0 15 | }; 16 | return indices; 17 | } 18 | 19 | //@TODO : improve getting texCoords from BlockBase 20 | std::vector UnderWaterRenderer::GetRectVertices(const float SIZE){ 21 | std::vector vertices = { 22 | -SIZE, -SIZE, 0.0f, 0.0f, 0.0f, 1.0f, 23 | SIZE, -SIZE, 0.0f, 0.0f, 0.0f, 1.0f, 24 | SIZE, SIZE, 0.0f, 0.0f, 0.0f, 1.0f, 25 | -SIZE, SIZE, 0.0f, 0.0f, 0.0f, 1.0f 26 | }; 27 | return vertices; 28 | } 29 | 30 | void UnderWaterRenderer::Render(Camera &camera, float time){ 31 | m_Model.Render(camera, time, m_Shader, true); 32 | } -------------------------------------------------------------------------------- /src/vertex/vertex-buffer-layout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "utils/log.h" 3 | #include 4 | #include 5 | 6 | struct VertextBufferLayoutElement 7 | { 8 | unsigned int type; 9 | unsigned int count; 10 | GLuint normalized; 11 | 12 | static unsigned int GetSize(unsigned int type){ 13 | switch (type) 14 | { 15 | case GL_FLOAT: 16 | return 4; 17 | break; 18 | case GL_UNSIGNED_INT: 19 | return 4; 20 | break; 21 | case GL_UNSIGNED_BYTE: 22 | return 1; 23 | break; 24 | } 25 | ASSERT(false); 26 | return 0; 27 | } 28 | }; 29 | 30 | class VertexBufferLayout 31 | { 32 | std::vector m_Elements; 33 | unsigned int m_Stride; 34 | 35 | public: 36 | VertexBufferLayout(); 37 | ~VertexBufferLayout(); 38 | 39 | template 40 | void AddAttribute(unsigned int count); 41 | 42 | std::vector GetElements() const; 43 | unsigned int GetStride() const; 44 | }; -------------------------------------------------------------------------------- /src/texture/texture-cube.cc: -------------------------------------------------------------------------------- 1 | #include "texture-cube.h" 2 | 3 | TextureCube::TextureCube(std::string filepath[6]){ 4 | CallGL(glGenTextures(1, &u_ID)); 5 | CallGL(glBindTexture(GL_TEXTURE_CUBE_MAP, u_ID)); 6 | 7 | CallGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 8 | CallGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 9 | CallGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 10 | CallGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 11 | 12 | for (unsigned int i = 0; i < 6; i++) 13 | { 14 | Load(filepath[i]); 15 | CallGL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_LocalBuffer)); 16 | Unload(); 17 | } 18 | } 19 | 20 | void TextureCube::Bind(unsigned int slot) const{ 21 | CallGL(glActiveTexture(GL_TEXTURE0 + slot)); 22 | CallGL(glBindTexture(GL_TEXTURE_CUBE_MAP, u_ID)); 23 | } 24 | 25 | void TextureCube::Unbind() const{ 26 | CallGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0)); 27 | } -------------------------------------------------------------------------------- /src/core/entity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "maths/glm.h" 3 | #include "utils/constants.h" 4 | 5 | struct Entity 6 | { 7 | glm::vec3 m_Position, m_Rotation, m_Velocity; 8 | float m_Speed; 9 | 10 | glm::mat4 GetModelMatrix(); 11 | Entity() 12 | : m_Position(0.0f, 0.0f, 0.0f), m_Rotation(0.0f, 0.0f, 0.0f), m_Velocity(0.0f, 0.0f, 0.0f) 13 | { 14 | } 15 | Entity(glm::vec3 position) 16 | : m_Position(position), m_Rotation(0.0f, 0.0f, 0.0f), m_Velocity(0.0f, 0.0f, 0.0f) 17 | { 18 | } 19 | Entity(glm::vec3 position, glm::vec3 rotation, glm::vec3 velocity) 20 | : m_Position(position), m_Rotation(rotation), m_Velocity(velocity) 21 | { 22 | } 23 | Entity(glm::vec3 position, glm::vec3 rotation, glm::vec3 velocity, float speed) 24 | : m_Position(position), m_Rotation(rotation), m_Velocity(velocity), m_Speed(speed) 25 | { 26 | } 27 | void Move(); 28 | glm::vec3 GetNewPosition(); 29 | glm::vec3 GetAcceleration(glm::vec3 direction); 30 | void Rotate(float angle, glm::vec3 direction); 31 | glm::vec3 GetVP(const glm::vec3& normal) const; 32 | }; -------------------------------------------------------------------------------- /res/shaders/sun.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 1) in vec2 texCoord; 9 | 10 | out vec2 v_TexCoord; 11 | uniform mat4 m_MVP; 12 | uniform float uTime; 13 | 14 | mat4 rotationX(float time){ 15 | float angle = ((time * 360.0) * 3.14159265 / 180.0) * -1; 16 | return mat4( 1.0, 0, 0, 0, 17 | 0, cos(angle), -sin(angle), 0, 18 | 0, sin(angle), cos(angle), 0, 19 | 0, 0, 0, 1); 20 | } 21 | 22 | void main(){ 23 | gl_Position = m_MVP * rotationX(uTime) * position; 24 | v_TexCoord = texCoord; 25 | }; 26 | 27 | #shader fragment 28 | 29 | #version 130 30 | #extension GL_ARB_explicit_attrib_location : require 31 | #extension GL_ARB_explicit_uniform_location : require 32 | 33 | layout(location = 0) out vec4 color; 34 | 35 | in vec2 v_TexCoord; 36 | 37 | uniform sampler2D uTexture; 38 | uniform float uTime; 39 | 40 | void main(){ 41 | vec4 texColor = texture(uTexture, v_TexCoord); 42 | color = texColor; 43 | }; -------------------------------------------------------------------------------- /src/vertex/vertex-array.cc: -------------------------------------------------------------------------------- 1 | #include "vertex-array.h" 2 | 3 | VertexArray::VertexArray(){ 4 | CallGL(glGenVertexArrays(1, &u_ID)); 5 | CallGL(glBindVertexArray(u_ID)); 6 | } 7 | 8 | VertexArray::~VertexArray(){ 9 | LogTrace("Destructing VertexArray %d...\n", u_ID); 10 | CallGL(glDeleteVertexArrays(1, &u_ID)); 11 | } 12 | 13 | void VertexArray::AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout){ 14 | Bind(); 15 | vb.Bind(); 16 | std::vector elements = layout.GetElements(); 17 | unsigned int offset = 0; 18 | for(int i = 0; i < elements.size(); i++){ 19 | const VertextBufferLayoutElement element = elements[i]; 20 | CallGL(glEnableVertexAttribArray(i)); 21 | CallGL(glVertexAttribPointer(i, element.count, element.type, element.normalized, layout.GetStride(), (const void*)offset)); 22 | offset += element.count * VertextBufferLayoutElement::GetSize(element.type); 23 | } 24 | } 25 | 26 | void VertexArray::Bind() const { 27 | CallGL(glBindVertexArray(u_ID)); 28 | } 29 | 30 | void VertexArray::Unbind() const { 31 | CallGL(glBindVertexArray(0)); 32 | } -------------------------------------------------------------------------------- /src/shader/shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "utils/log.h" 8 | #include 9 | #include "maths/glm.h" 10 | 11 | struct ShaderSources{ 12 | std::string Vertex; 13 | std::string Fragment; 14 | }; 15 | 16 | class Shader{ 17 | protected: 18 | unsigned int u_ID; 19 | std::string m_Filepath; 20 | std::unordered_map m_UnformLocation; 21 | 22 | public: 23 | Shader(std::string filepath); 24 | ~Shader(); 25 | 26 | void Bind() const; 27 | void Unbind() const; 28 | void SetUniform4f(std::string name, float v1, float v2, float v3, float v4); 29 | void SetUniform1i(std::string name, int value); 30 | void SetUniform1f(std::string name, float value); 31 | void SetUniformMat4(std::string name, glm::mat4 value); 32 | int GetLocation(std::string name); 33 | 34 | ShaderSources ParseShader(const std::string &filepath); 35 | unsigned int CompileShader(unsigned int type, std::string &source); 36 | unsigned int CreateShader(std::string &vertex_source, std::string &fragmement_source); 37 | }; 38 | -------------------------------------------------------------------------------- /src/world/biome/grassland-biome.cc: -------------------------------------------------------------------------------- 1 | #include "grassland-biome.h" 2 | #include "../chunk/superchunk.h" 3 | 4 | GrassLandBiome::GrassLandBiome(int seed): Biome(GetNoiseParameters(), 100, 2, seed){ 5 | } 6 | 7 | NoiseParameters GrassLandBiome::GetNoiseParameters(){ 8 | NoiseParameters params; 9 | params.m_Octaves = 7; 10 | params.m_Amplitude = 40.0; 11 | params.m_Persistance = 0.50; 12 | params.m_Smoothness = 60; 13 | return params; 14 | } 15 | 16 | void GrassLandBiome::MakeTree(SuperChunk& chunk, glm::vec3 tree){ 17 | Tree::GenerateOak(chunk, tree); 18 | } 19 | 20 | BlockType GrassLandBiome::GetTopBlock(){ 21 | return BlockType::Grass; 22 | } 23 | 24 | BlockType GrassLandBiome::GetPlant(){ 25 | return Random::Get().GetIntInRange(0,10) > 1 ? BlockType::Plant : BlockType::FlowerYellow; 26 | } 27 | 28 | BlockType GrassLandBiome::GetUnderWaterBlock(){ 29 | return Random::Get().GetIntInRange(0,10) > 2 ? BlockType::Sand : BlockType::Stone; 30 | } 31 | 32 | BlockType GrassLandBiome::GetNearWaterBlock(){ 33 | return BlockType::Sand; 34 | } 35 | 36 | BlockType GrassLandBiome::GetBlockInY(int y){ 37 | return BlockType::Dirt; 38 | } -------------------------------------------------------------------------------- /res/shaders/moon.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 1) in vec2 texCoord; 9 | 10 | out vec2 v_TexCoord; 11 | uniform mat4 m_MVP; 12 | uniform float uTime; 13 | 14 | mat4 rotationX(float time){ 15 | float angle = ((time * 360.0 + 180.0) * 3.14159265 / 180.0) * -1; 16 | return mat4( 1.0, 0, 0, 0, 17 | 0, cos(angle), -sin(angle), 0, 18 | 0, sin(angle), cos(angle), 0, 19 | 0, 0, 0, 1); 20 | } 21 | 22 | void main(){ 23 | gl_Position = m_MVP * rotationX(uTime) * position; 24 | v_TexCoord = texCoord; 25 | }; 26 | 27 | #shader fragment 28 | 29 | #version 130 30 | #extension GL_ARB_explicit_attrib_location : require 31 | #extension GL_ARB_explicit_uniform_location : require 32 | 33 | layout(location = 0) out vec4 color; 34 | 35 | in vec2 v_TexCoord; 36 | 37 | uniform sampler2D uTexture; 38 | uniform float uTime; 39 | 40 | void main(){ 41 | vec4 texColor = texture(uTexture, v_TexCoord); 42 | color = texColor * vec4(0.5, 0.5, 0.8, 1.0); 43 | }; -------------------------------------------------------------------------------- /src/world/block/block-base.cc: -------------------------------------------------------------------------------- 1 | #include "block-base.h" 2 | 3 | BlockBase* BlockBase::m_Instance = nullptr; 4 | 5 | BlockBase::BlockBase(){ 6 | m_Blocks[BlockType::Grass] = new BlockProps("grass"); 7 | m_Blocks[BlockType::Water] = new BlockProps("water"); 8 | m_Blocks[BlockType::Dirt] = new BlockProps("dirt"); 9 | m_Blocks[BlockType::Stone] = new BlockProps("stone"); 10 | m_Blocks[BlockType::Wood] = new BlockProps("wood"); 11 | m_Blocks[BlockType::Leaf] = new BlockProps("leaf"); 12 | m_Blocks[BlockType::Plant] = new BlockProps("plant"); 13 | m_Blocks[BlockType::Sand] = new BlockProps("sand"); 14 | m_Blocks[BlockType::FlowerYellow] = new BlockProps("flower-yellow"); 15 | m_Blocks[BlockType::Cloud] = new BlockProps("cloud"); 16 | m_Blocks[BlockType::Sun] = new BlockProps("sun"); 17 | m_Blocks[BlockType::Moon] = new BlockProps("moon"); 18 | } 19 | 20 | BlockBase* BlockBase::Get(){ 21 | if(BlockBase::m_Instance == nullptr){ 22 | BlockBase::m_Instance = new BlockBase(); 23 | } 24 | return BlockBase::m_Instance; 25 | } 26 | 27 | BlockProps BlockBase::GetBlockProps(BlockType type){ 28 | return *m_Blocks[(int)type]; 29 | } -------------------------------------------------------------------------------- /src/renderer/sky-renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vertex/vertex-array.h" 3 | #include "vertex/index-buffer.h" 4 | #include "shader/skyboxtex-shader.h" 5 | #include "shader/stars-shader.h" 6 | #include "shader/sun-shader.h" 7 | #include "shader/moon-shader.h" 8 | #include "texture/sky-texture.h" 9 | #include "texture/stars-texture.h" 10 | #include "texture/atlas-texture.h" 11 | #include "world/block/block-base.h" 12 | #include 13 | #include "core/camera.h" 14 | #include "core/model.h" 15 | #include 16 | 17 | class SkyRenderer{ 18 | public: 19 | SkyRenderer(); 20 | ~SkyRenderer(); 21 | void Render(Camera &camera, float time); 22 | private: 23 | std::vector GetCubeVertices(const float SIZE); 24 | std::vector GetCubeIndices(); 25 | std::vector GetRectVerticesByBlock(const float SIZE, const float DEPTHZ, const BlockType TYPE); 26 | std::vector GetRectIndices(); 27 | SkyTexture m_Texture; 28 | StarsTexture m_StarsTexture; 29 | AtlasTexture m_AtlasTexture; 30 | SkyBoxTexShader m_Shader; 31 | StarsShader m_StarsShader; 32 | SunShader m_SunShader; 33 | MoonShader m_MoonShader; 34 | Model m_Stars; 35 | Model m_Skybox; 36 | Model m_Sun; 37 | Model m_Moon; 38 | }; -------------------------------------------------------------------------------- /src/world/environnement/tree.cc: -------------------------------------------------------------------------------- 1 | #include "tree.h" 2 | #include "world/chunk/superchunk.h" 3 | 4 | void Tree::GenerateOak(SuperChunk& chunk, glm::vec3 tree){ 5 | Random rand = Random::Get(); 6 | int height = rand.GetIntInRange(4, 8); 7 | 8 | for(int y = 0; y <= height; y++){ 9 | chunk.SetBlock(tree.x, tree.y + y, tree.z, BlockType::Wood); 10 | } 11 | 12 | rand.SetSeed(tree.x + tree.z); 13 | int heightLeaf = rand.GetIntInRange(4, 6); 14 | for(int iHeightLeaf = 0; iHeightLeaf < heightLeaf; iHeightLeaf++){ 15 | rand.SetSeed(tree.x + tree.z + iHeightLeaf); 16 | int leafSize; 17 | if(iHeightLeaf < heightLeaf / 2){ 18 | leafSize = iHeightLeaf + 1; 19 | }else{ 20 | leafSize = heightLeaf - iHeightLeaf; 21 | } 22 | for(int zleaf = -leafSize; zleaf < leafSize; zleaf++){ 23 | for(int xleaf = -leafSize; xleaf < leafSize; xleaf++){ 24 | chunk.SetBlock( 25 | tree.x + xleaf, 26 | tree.y + height + iHeightLeaf, 27 | tree.z + zleaf, 28 | xleaf == 0 && zleaf == 0 && iHeightLeaf < heightLeaf - 1 ? BlockType::Wood : BlockType::Leaf 29 | ); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /res/shaders/skybox.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | 9 | out vec2 v_Uv; 10 | uniform mat4 m_MVP; 11 | 12 | void main(){ 13 | gl_Position = m_MVP * position; 14 | v_Uv = (normalize(vec2(position.x, position.y)) + 1.0) / 2.0; 15 | }; 16 | 17 | #shader fragment 18 | 19 | #version 130 20 | #extension GL_ARB_explicit_attrib_location : require 21 | #extension GL_ARB_explicit_uniform_location : require 22 | 23 | layout(location = 0) out vec4 color; 24 | 25 | in vec2 v_Uv; 26 | uniform float uTime; 27 | 28 | vec4 getLight(float time){ 29 | vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); 30 | vec4 darkColor = vec4(0.05, 0.05, 0.05, 1.0); 31 | return lightColor * (1 - time) + darkColor * time; 32 | } 33 | 34 | void main(){ 35 | vec4 colorTop = vec4(0.2, 0.67, 1.0, 1.0); 36 | vec4 colorBottom = vec4(0.65, 0.85, 1.0, 1.0); 37 | float y = v_Uv.y; 38 | float minY = 0.5; 39 | float maxY = 0.6; 40 | y = (y - minY)/(maxY - minY); 41 | if(y > 1.0){ 42 | y = 1.0; 43 | } 44 | if(y < 0.0){ 45 | y = 0.0; 46 | } 47 | vec4 colorResult = colorBottom * (1.0 - y) + colorTop * y; 48 | color = colorResult * getLight(uTime); 49 | }; -------------------------------------------------------------------------------- /src/maths/vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct VectorXY 6 | { 7 | float x, y; 8 | }; 9 | 10 | struct Vector3i 11 | { 12 | int x, y, z; 13 | Vector3i(int x_, int y_, int z_) : x(x_), y(y_), z(z_) 14 | { 15 | } 16 | bool operator==(const Vector3i &v) const 17 | { 18 | return v.x == x && v.y == y && v.z == z; 19 | } 20 | }; 21 | 22 | struct Vector2i 23 | { 24 | int x, z; 25 | Vector2i(int x_, int z_) : x(x_), z(z_) 26 | { 27 | } 28 | bool operator==(const Vector2i &v) const noexcept 29 | { 30 | return v.x == x && v.z == z; 31 | } 32 | }; 33 | 34 | namespace std 35 | { 36 | template <> 37 | struct hash 38 | { 39 | std::size_t operator()(const Vector2i &v) const 40 | { 41 | std::size_t h1 = std::hash()(v.x); 42 | std::size_t h2 = std::hash()(v.z); 43 | 44 | return hash{}((h1 ^ h2) >> 2); 45 | } 46 | }; 47 | 48 | template <> 49 | struct hash 50 | { 51 | std::size_t operator()(const Vector3i &node) const 52 | { 53 | std::size_t h1 = std::hash()(node.x); 54 | std::size_t h2 = std::hash()(node.y); 55 | std::size_t h3 = std::hash()(node.z); 56 | 57 | return h1 ^ h2 ^ h3; 58 | } 59 | }; 60 | }; // namespace std -------------------------------------------------------------------------------- /src/world/biome/mountain-biome.cc: -------------------------------------------------------------------------------- 1 | #include "mountain-biome.h" 2 | #include "../chunk/superchunk.h" 3 | 4 | MountainBiome::MountainBiome(int seed): Biome(GetNoiseParameters(), 300, 5, seed){ 5 | } 6 | 7 | NoiseParameters MountainBiome::GetNoiseParameters(){ 8 | NoiseParameters params; 9 | params.m_Octaves = 9; 10 | params.m_Amplitude = 83.0; 11 | params.m_Persistance = 0.51; 12 | params.m_Smoothness = 235; 13 | return params; 14 | } 15 | 16 | void MountainBiome::MakeTree(SuperChunk& chunk, glm::vec3 tree){ 17 | Tree::GenerateOak(chunk, tree); 18 | } 19 | 20 | BlockType MountainBiome::GetTopBlock(){ 21 | return BlockType::Grass; 22 | } 23 | 24 | BlockType MountainBiome::GetPlant(){ 25 | return Random::Get().GetIntInRange(0,10) > 2 ? BlockType::Plant : BlockType::FlowerYellow; 26 | } 27 | 28 | BlockType MountainBiome::GetUnderWaterBlock(){ 29 | return Random::Get().GetIntInRange(0,10) > 2 ? BlockType::Sand : BlockType::Stone; 30 | } 31 | 32 | BlockType MountainBiome::GetNearWaterBlock(){ 33 | return Random::Get().GetIntInRange(0,10) > 5 ? BlockType::Dirt : BlockType::Sand; 34 | } 35 | 36 | BlockType MountainBiome::GetBlockInY(int y){ 37 | int maxRange = 10; 38 | int conditionRange = 100 - y; 39 | return Random::Get().GetIntInRange(0,maxRange) > conditionRange ? BlockType::Dirt : BlockType::Stone; 40 | } -------------------------------------------------------------------------------- /src/renderer/cloud-renderer.cc: -------------------------------------------------------------------------------- 1 | #include "cloud-renderer.h" 2 | #include "world/chunk/chunk.h" 3 | 4 | CloudRenderer::CloudRenderer(){} 5 | 6 | void CloudRenderer::Draw(const VertexArray &va, const IndexBuffer &ib) const{ 7 | va.Bind(); 8 | ib.Bind(); 9 | CallGL(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr)); 10 | } 11 | 12 | void CloudRenderer::Render(Camera &camera, float time){ 13 | if(m_Chunks.empty()){ 14 | return; 15 | } 16 | CallGL(glEnable(GL_BLEND)); 17 | m_Shader.Bind(); 18 | m_Shader.SetUniform1f("uTime", time); 19 | m_Texture.Bind(); 20 | for(Chunk* chunk : m_Chunks){ 21 | RenderChunk(camera, chunk, chunk->GetMeshes().m_Cloud); 22 | } 23 | m_Chunks.clear(); 24 | } 25 | 26 | void CloudRenderer::RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh){ 27 | chunk->UpdateVBO(); 28 | glm::mat4 viewMatrix = camera.GetViewMatrix(); 29 | glm::mat4 projMatrix = camera.GetProjectionMatrix(); 30 | glm::mat4 modelMatrix = chunk->GetModelMatrix(); 31 | glm::mat4 MVP = projMatrix * viewMatrix * modelMatrix; 32 | m_Shader.SetUniformMat4("m_MVP", MVP); 33 | Draw(*(mesh.GetVAO()), *(mesh.GetIBO())); 34 | } 35 | 36 | void CloudRenderer::Add(Chunk* chunk){ 37 | m_Chunks.push_back(chunk); 38 | } 39 | 40 | CloudRenderer::~CloudRenderer(){ 41 | LogTrace("Destructing CloudRenderer...\n"); 42 | } -------------------------------------------------------------------------------- /src/renderer/water-renderer.cc: -------------------------------------------------------------------------------- 1 | #include "water-renderer.h" 2 | #include "world/chunk/chunk.h" 3 | 4 | WaterRenderer::WaterRenderer(){} 5 | 6 | void WaterRenderer::Draw(const VertexArray &va, const IndexBuffer &ib) const{ 7 | va.Bind(); 8 | ib.Bind(); 9 | CallGL(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr)); 10 | } 11 | 12 | void WaterRenderer::Render(Camera &camera, float time){ 13 | if(m_Chunks.empty()){ 14 | return; 15 | } 16 | CallGL(glEnable(GL_BLEND)); 17 | m_Shader.Bind(); 18 | m_Shader.SetUniform1f("uTime", time); 19 | m_Texture.Bind(); 20 | for(Chunk* chunk : m_Chunks){ 21 | RenderChunk(camera, chunk, chunk->GetMeshes().m_Water); 22 | } 23 | m_Chunks.clear(); 24 | } 25 | 26 | void WaterRenderer::RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh){ 27 | chunk->UpdateVBO(); 28 | glm::mat4 viewMatrix = camera.GetViewMatrix(); 29 | glm::mat4 projMatrix = camera.GetProjectionMatrix(); 30 | glm::mat4 modelMatrix = chunk->GetModelMatrix(); 31 | glm::mat4 MVP = projMatrix * viewMatrix * modelMatrix; 32 | m_Shader.SetUniformMat4("m_MVP", MVP); 33 | Draw(*(mesh.GetVAO()), *(mesh.GetIBO())); 34 | } 35 | 36 | void WaterRenderer::Add(Chunk* chunk){ 37 | m_Chunks.push_back(chunk); 38 | } 39 | 40 | WaterRenderer::~WaterRenderer(){ 41 | LogTrace("Destructing WaterRenderer...\n"); 42 | } -------------------------------------------------------------------------------- /src/renderer/chunk-renderer.cc: -------------------------------------------------------------------------------- 1 | #include "chunk-renderer.h" 2 | #include "world/chunk/chunk.h" 3 | 4 | ChunkRenderer::ChunkRenderer(){} 5 | 6 | void ChunkRenderer::Draw(const VertexArray &va, const IndexBuffer &ib) const{ 7 | va.Bind(); 8 | ib.Bind(); 9 | CallGL(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr)); 10 | } 11 | 12 | void ChunkRenderer::Render(Camera &camera, float time){ 13 | if(m_Chunks.empty()){ 14 | return; 15 | } 16 | CallGL(glDisable(GL_BLEND)); 17 | m_Shader.Bind(); 18 | m_Shader.SetUniform1f("uTime", time); 19 | m_Texture.Bind(); 20 | for(Chunk* chunk : m_Chunks){ 21 | RenderChunk(camera, chunk, chunk->GetMeshes().m_Solid); 22 | } 23 | m_Chunks.clear(); 24 | } 25 | 26 | void ChunkRenderer::RenderChunk(Camera &camera, Chunk* chunk, Mesh& mesh){ 27 | chunk->UpdateVBO(); 28 | glm::mat4 viewMatrix = camera.GetViewMatrix(); 29 | glm::mat4 projMatrix = camera.GetProjectionMatrix(); 30 | glm::mat4 modelMatrix = chunk->GetModelMatrix(); 31 | glm::mat4 MVP = projMatrix * viewMatrix * modelMatrix; 32 | m_Shader.SetUniformMat4("m_MVP", MVP); 33 | m_Shader.SetUniformMat4("m_M", modelMatrix); 34 | Draw(*(mesh.GetVAO()), *(mesh.GetIBO())); 35 | } 36 | 37 | void ChunkRenderer::Add(Chunk* chunk){ 38 | m_Chunks.push_back(chunk); 39 | } 40 | 41 | ChunkRenderer::~ChunkRenderer(){ 42 | LogTrace("Destructing ChunkRenderer...\n"); 43 | } -------------------------------------------------------------------------------- /src/world/chunk/chunk-manager.cc: -------------------------------------------------------------------------------- 1 | #include "chunk-manager.h" 2 | 3 | ChunkManager::ChunkManager(World* world): m_World(world){ 4 | } 5 | 6 | ChunkManager::~ChunkManager(){ 7 | } 8 | 9 | ChunkMap& ChunkManager::GetChunks(){ 10 | return m_Chunks; 11 | } 12 | 13 | bool ChunkManager::MakeMesh(Camera& camera, int x, int z){ 14 | SuperChunk& chunk = GetChunk(x, z); 15 | return chunk.MakeMesh(camera); 16 | } 17 | 18 | bool ChunkManager::LoadMesh(int x, int z){ 19 | SuperChunk& chunk = GetChunk(x, z); 20 | chunk.Load(m_WorldGenerator); 21 | return true; 22 | } 23 | 24 | void ChunkManager::DeleteMeshes(){ 25 | for(auto& chunk : m_Chunks){ 26 | chunk.second.DeleteMeshes(); 27 | } 28 | } 29 | 30 | SuperChunk& ChunkManager::GetChunk(int x, int z){ 31 | Vector2i key {x, z}; 32 | if(!ChunkExistsAt(x, z)){ 33 | LogTrace("Creating mesh (%d, %d)...\n", x, z); 34 | SuperChunk chunk(glm::vec3(x, 0, z), *m_World); 35 | m_Chunks.emplace(key, std::move(chunk)); 36 | } 37 | 38 | return m_Chunks[key]; 39 | } 40 | 41 | SuperChunk* ChunkManager::GetChunkIfExists(int x, int z){ 42 | Vector2i key {x, z}; 43 | if(!ChunkExistsAt(x, z)){ 44 | return nullptr; 45 | } 46 | return &m_Chunks[key]; 47 | } 48 | 49 | bool ChunkManager::ChunkExistsAt(int x, int z){ 50 | Vector2i key {x, z}; 51 | return m_Chunks.find(key) != m_Chunks.end(); 52 | } 53 | 54 | void ChunkManager::UnLoadChunk(int x, int z){ 55 | if(ChunkExistsAt(x, z)) 56 | m_Chunks.erase({x, z}); 57 | } -------------------------------------------------------------------------------- /src/renderer/renderer.cc: -------------------------------------------------------------------------------- 1 | #include "renderer.h" 2 | 3 | void ClearLogs(){ 4 | while(glGetError()); 5 | } 6 | 7 | bool LogCall(std::string function, std::string file, int line){ 8 | if(unsigned int error = glGetError()){ 9 | printf("[OpenGL Error] : (%d, %s), Call : %s in %s:%d\n", error, gluErrorString(error), function.c_str(), file.c_str(), line); 10 | //std::cout << "[OpenGL Error] : (" << error << "), Call : " << function << " in " << file << ":" << line << std::endl; 11 | return false; 12 | } 13 | return true; 14 | } 15 | 16 | void Renderer::Clear() const{ 17 | CallGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); 18 | } 19 | 20 | 21 | void Renderer::Render(Camera &camera, float time, bool isUnderWater){ 22 | m_ChunkRenderer.Render(camera, time); 23 | m_SkyRenderer.Render(camera, time); 24 | m_WaterRenderer.Render(camera, time); 25 | m_CloudRenderer.Render(camera, time); 26 | if(isUnderWater){ 27 | m_UnderWaterRenderer.Render(camera, time); 28 | } 29 | } 30 | 31 | //@TODO : Optimize switching between renderers 32 | void Renderer::DrawChunk(Chunk* chunk){ 33 | if(chunk->GetMeshes().m_Solid.GetVertices().size() > 0){ 34 | m_ChunkRenderer.Add(chunk); 35 | } 36 | if(chunk->GetMeshes().m_Water.GetVertices().size() > 0){ 37 | m_WaterRenderer.Add(chunk); 38 | } 39 | if(chunk->GetMeshes().m_Cloud.GetVertices().size() > 0){ 40 | m_CloudRenderer.Add(chunk); 41 | } 42 | } 43 | 44 | Renderer::~Renderer(){ 45 | LogTrace("Destructing renderer...\n"); 46 | } 47 | -------------------------------------------------------------------------------- /src/world/world.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "maths/vector.h" 5 | #include "renderer/renderer.h" 6 | #include "chunk/superchunk.h" 7 | #include "chunk/chunk-manager.h" 8 | #include "world/player.h" 9 | #include 10 | #include 11 | 12 | class World{ 13 | public: 14 | static void Generate(Renderer &renderer, Camera &camera); 15 | static World* GetInstance(Camera &camera); 16 | void Render(Renderer& renderer, Camera &camera); 17 | void LoadChunks(Camera &camera); 18 | void Update(Camera& camera); 19 | Block GetBlock(int x, int y, int z); 20 | void SetBlock(int x, int y, int z, BlockType type, bool focus = false); 21 | void FocusBlock(int x, int y, int z, BlockType type); 22 | Vector2i GetBlockXZ(int x, int z); 23 | Vector2i GetChunkXZ(int x, int z); 24 | SuperChunk& GetChunkByBlock(int x, int y, int z); 25 | void SetSpawnPoint(); 26 | void UpdateChunk(int blockX, int blockY, int blockZ); 27 | void UnFocusBlock(); 28 | void UpdateFocusBlock(Camera& camera); 29 | Vector3i GetProjPoint(Camera& camera); 30 | void Mine(Camera& camera); 31 | Player m_Player; 32 | ~World(); 33 | private: 34 | static World* m_Instance; 35 | World(Camera &camera); 36 | void UpdateChunks(); 37 | void UpdatePlayer(); 38 | ChunkManager m_ChunkManager; 39 | int m_LoadDistance = 2; 40 | const int m_RenderDistance; 41 | bool m_Running; 42 | pthread_t m_LoadChunksThread; 43 | pthread_mutex_t m_Lock; 44 | std::unordered_map m_UpdateChunks; 45 | Vector3i m_FocusBlock; 46 | }; -------------------------------------------------------------------------------- /res/shaders/water.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 1) in vec2 texCoord; 9 | 10 | out vec2 v_TexCoord; 11 | uniform mat4 m_MVP; 12 | 13 | void main(){ 14 | gl_Position = m_MVP * position; 15 | v_TexCoord = texCoord; 16 | }; 17 | 18 | #shader fragment 19 | 20 | #version 130 21 | #extension GL_ARB_explicit_attrib_location : require 22 | #extension GL_ARB_explicit_uniform_location : require 23 | 24 | layout(location = 0) out vec4 color; 25 | 26 | in vec2 v_TexCoord; 27 | 28 | uniform sampler2D uTexture; 29 | uniform float uTime; 30 | 31 | vec4 getLight(float time){ 32 | vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); 33 | vec4 darkColor = vec4(0.2, 0.2, 0.2, 1.0); 34 | vec4 sunriseColor = vec4(1.0, 0.8, 0.8, 1.0); 35 | vec4 startColor; 36 | vec4 endColor; 37 | vec4 lightResult; 38 | 39 | if(time <= 0.25){ 40 | float bias = time * 4; 41 | lightResult = sunriseColor * (1.0 - bias) + lightColor * bias; 42 | }else if(time <= 0.35){ 43 | lightResult = lightColor; 44 | }else if(time <= 0.5){ 45 | float bias = (time - 0.35)/(0.5 - 0.35); 46 | lightResult = lightColor * (1.0 - bias) + sunriseColor * bias; 47 | }else if(time <= 0.6){ 48 | float bias = (time - 0.5)/(0.6 - 0.5); 49 | lightResult = sunriseColor * (1.0 - bias) + darkColor * bias; 50 | }else if(time <= 0.75){ 51 | lightResult = darkColor; 52 | }else{ 53 | float bias = (time - 0.75)/(1.0 - 0.75); 54 | lightResult = darkColor * (1.0 - bias) + sunriseColor * bias; 55 | } 56 | 57 | return lightResult; 58 | } 59 | 60 | void main(){ 61 | vec4 texColor = texture(uTexture, v_TexCoord); 62 | color = texColor * getLight(uTime); 63 | }; -------------------------------------------------------------------------------- /src/world/chunk/chunk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "world/block/block.h" 3 | #include "vertex/vertex-array.h" 4 | #include "vertex/index-buffer.h" 5 | #include "core/entity.h" 6 | #include "renderer/renderer.h" 7 | #include "utils/constants.h" 8 | #include 9 | #include "maths/vector.h" 10 | #include "mesh.h" 11 | 12 | class World; 13 | class Renderer; 14 | class Camera; 15 | 16 | struct MeshCollection{ 17 | MeshCollection(Entity& entity): m_Solid(entity), m_Water(entity), m_Cloud(entity){} 18 | Mesh m_Solid; 19 | Mesh m_Water; 20 | Mesh m_Cloud; 21 | }; 22 | 23 | class Chunk : public Entity{ 24 | public: 25 | Chunk(World& world); 26 | Chunk(glm::vec3 position, World& world); 27 | Chunk() = default; 28 | ~Chunk(); 29 | 30 | Block GetBlock(int x, int y, int z) const; 31 | Block GetChunkBlock(int x, int y, int z) const; 32 | bool MakeMesh(); 33 | void TryAddBlock(int x, int y, int z); 34 | void TryAddFace(std::array& blockFace, std::array& texCoords, glm::vec3& position, glm::vec3 AdjacentBlock, float light); 35 | bool ShouldAddFace(glm::vec3 adjBlockPosition, glm::vec3 blockPosition); 36 | 37 | void UpdateVBO(); 38 | bool HasMesh(); 39 | bool HasBuffer(); 40 | void SetBlock(int x, int y, int z, BlockType type, bool focus = false); 41 | bool OutOfBounds(int value) const; 42 | bool OutOfBounds(int x, int y, int z) const; 43 | void Draw(Renderer& renderer); 44 | int GetBlockIndex(int x, int y, int z) const; 45 | glm::vec3 ToWorldPosition(int x, int y, int z) const; 46 | void DeleteMeshes(); 47 | MeshCollection& GetMeshes(); 48 | 49 | private: 50 | Block m_Blocks[CHUNK_SIZE*CHUNK_SIZE*CHUNK_SIZE]; 51 | bool m_Loaded = false; 52 | bool m_hasMesh = false; 53 | bool m_hasBuffer = false; 54 | World *m_World; 55 | MeshCollection m_Meshes; 56 | }; -------------------------------------------------------------------------------- /res/shaders/stars.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 2) in float texLight; 9 | 10 | out vec3 v_TexCoord; 11 | uniform mat4 m_MVP; 12 | 13 | void main(){ 14 | gl_Position = m_MVP * position; 15 | v_TexCoord = vec3(position.x * -1, position.y, position.z); 16 | }; 17 | 18 | #shader fragment 19 | 20 | #version 130 21 | #extension GL_ARB_explicit_attrib_location : require 22 | #extension GL_ARB_explicit_uniform_location : require 23 | 24 | layout(location = 0) out vec4 color; 25 | 26 | in vec3 v_TexCoord; 27 | 28 | uniform samplerCube uTexture; 29 | uniform float uTime; 30 | 31 | vec4 getLight(float time){ 32 | vec4 lightColor = vec4(1.0, 1.0, 1.0, 0.0); 33 | vec4 darkColor = vec4(1.0, 1.0, 1.0, 1.0); 34 | vec4 sunriseColor = vec4(1.0, 1.0, 1.0, 0.2); 35 | vec4 startColor; 36 | vec4 endColor; 37 | vec4 lightResult; 38 | 39 | if(time <= 0.25){ 40 | float bias = time * 4; 41 | lightResult = sunriseColor * (1.0 - bias) + lightColor * bias; 42 | }else if(time <= 0.35){ 43 | lightResult = lightColor; 44 | }else if(time <= 0.5){ 45 | float bias = (time - 0.35)/(0.5 - 0.35); 46 | lightResult = lightColor * (1.0 - bias) + sunriseColor * bias; 47 | }else if(time <= 0.6){ 48 | float bias = (time - 0.5)/(0.6 - 0.5); 49 | lightResult = sunriseColor * (1.0 - bias) + darkColor * bias; 50 | }else if(time <= 0.75){ 51 | lightResult = darkColor; 52 | }else{ 53 | float bias = (time - 0.75)/(1.0 - 0.75); 54 | lightResult = darkColor * (1.0 - bias) + sunriseColor * bias; 55 | } 56 | 57 | return lightResult; 58 | } 59 | 60 | void main(){ 61 | vec4 texColor = texture(uTexture, v_TexCoord); 62 | color = texColor * getLight(uTime); 63 | }; -------------------------------------------------------------------------------- /res/shaders/basic.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 1) in vec2 texCoord; 9 | layout(location = 2) in float texLight; 10 | 11 | out vec2 v_TexCoord; 12 | out vec4 v_texLight; 13 | out vec4 v_Position; 14 | uniform mat4 m_MVP; 15 | uniform mat4 m_M; 16 | 17 | void main(){ 18 | gl_Position = m_MVP * position; 19 | v_Position = m_M * position; 20 | v_TexCoord = texCoord; 21 | v_texLight = vec4(texLight, texLight, texLight, 1.0); 22 | }; 23 | 24 | #shader fragment 25 | 26 | #version 130 27 | #extension GL_ARB_explicit_attrib_location : require 28 | #extension GL_ARB_explicit_uniform_location : require 29 | 30 | layout(location = 0) out vec4 color; 31 | 32 | in vec2 v_TexCoord; 33 | in vec4 v_texLight; 34 | in vec4 v_Position; 35 | 36 | uniform sampler2D uTexture; 37 | uniform float uTime; 38 | 39 | vec4 getLight(float time){ 40 | vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); 41 | vec4 darkColor = vec4(0.2, 0.2, 0.2, 1.0); 42 | vec4 sunriseColor = vec4(1.0, 0.8, 0.8, 1.0); 43 | vec4 startColor; 44 | vec4 endColor; 45 | vec4 lightResult; 46 | 47 | if(time <= 0.25){ 48 | float bias = time * 4; 49 | lightResult = sunriseColor * (1.0 - bias) + lightColor * bias; 50 | }else if(time <= 0.35){ 51 | lightResult = lightColor; 52 | }else if(time <= 0.5){ 53 | float bias = (time - 0.35)/(0.5 - 0.35); 54 | lightResult = lightColor * (1.0 - bias) + sunriseColor * bias; 55 | }else if(time <= 0.6){ 56 | float bias = (time - 0.5)/(0.6 - 0.5); 57 | lightResult = sunriseColor * (1.0 - bias) + darkColor * bias; 58 | }else if(time <= 0.75){ 59 | lightResult = darkColor; 60 | }else{ 61 | float bias = (time - 0.75)/(1.0 - 0.75); 62 | lightResult = darkColor * (1.0 - bias) + sunriseColor * bias; 63 | } 64 | 65 | return lightResult; 66 | } 67 | 68 | void main(){ 69 | vec4 texColor = texture(uTexture, v_TexCoord); 70 | color = texColor * getLight(uTime) * v_texLight; 71 | if (color.a != 1) discard; 72 | }; -------------------------------------------------------------------------------- /src/core/camera.cc: -------------------------------------------------------------------------------- 1 | #include "camera.h" 2 | 3 | Camera::Camera(float fov, float znear, float zfar) 4 | : m_Fov(fov) 5 | , m_Znear(znear) 6 | , m_Zfar(zfar) 7 | { 8 | } 9 | 10 | Camera::~Camera() { 11 | LogTrace("Destructing camera...\n"); 12 | } 13 | 14 | glm::mat4 Camera::GetViewMatrix() 15 | { 16 | glm::mat4 matrix(1.f); 17 | 18 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.x), {1, 0, 0}); 19 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.y), {0, 1, 0}); 20 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.z), {0, 0, 1}); 21 | 22 | matrix = glm::translate(matrix, -m_Position); 23 | 24 | return matrix; 25 | } 26 | 27 | glm::mat4 Camera::GetViewMatrixRotation() 28 | { 29 | glm::mat4 matrix(1.f); 30 | 31 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.x), {1, 0, 0}); 32 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.y), {0, 1, 0}); 33 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.z), {0, 0, 1}); 34 | 35 | return matrix; 36 | } 37 | 38 | glm::mat4 Camera::GetProjectionMatrix() 39 | { 40 | int windowX = SCREEN_WIDTH; 41 | int windowY = SCREEN_HEIGHT; 42 | float screenWidth = (float)windowX; 43 | float screenHeight = (float)windowY; 44 | glm::mat4 projection; 45 | projection = glm::perspective(glm::radians(m_Fov), screenWidth / screenHeight, m_Znear, m_Zfar); 46 | 47 | return projection; 48 | } 49 | 50 | void Camera::Update(Player &player){ 51 | Camera::UpdateGeoInfo(player); 52 | m_ViewFrustum.Update(GetProjectionMatrix() * GetViewMatrix()); 53 | } 54 | 55 | glm::vec3 Camera::GetRay(){ 56 | glm::mat4 proj = GetProjectionMatrix(); 57 | glm::mat4 view = GetViewMatrixRotation(); 58 | 59 | glm::mat4 inVP = glm::inverse(proj * view); 60 | glm::vec4 screenPos = glm::vec4(0.f, 0.0f, 0.0f, 1.0f); 61 | glm::vec4 worldPos = inVP * screenPos; 62 | 63 | glm::vec3 dir = glm::normalize(glm::vec3(worldPos)); 64 | 65 | return dir; 66 | } 67 | 68 | void Camera::UpdateGeoInfo(Player &player){ 69 | m_Position = player.m_Position; 70 | m_Rotation = player.m_Rotation; 71 | m_Velocity = player.m_Velocity; 72 | } 73 | 74 | const ViewFrustum& Camera::GetViewFrustum() const { 75 | return m_ViewFrustum; 76 | } -------------------------------------------------------------------------------- /src/world/noise-generator.cc: -------------------------------------------------------------------------------- 1 | #include "noise-generator.h" 2 | 3 | NoiseGenerator::NoiseGenerator(int seed): m_Seed(seed){ 4 | m_NoiseParameters.m_Octaves = 8; 5 | m_NoiseParameters.m_Amplitude = 20.0; 6 | m_NoiseParameters.m_Persistance = 0.77; 7 | m_NoiseParameters.m_Smoothness = 100.0; 8 | }; 9 | 10 | NoiseGenerator::NoiseGenerator(NoiseParameters& noiseParam, int seed): m_Seed(seed), m_NoiseParameters(noiseParam){ 11 | }; 12 | 13 | void NoiseGenerator::SetParameters(NoiseParameters& noiseParam){ 14 | m_NoiseParameters = noiseParam; 15 | } 16 | 17 | NoiseParameters NoiseGenerator::GetNoiseParameters(){ 18 | return m_NoiseParameters; 19 | } 20 | 21 | double NoiseGenerator::Noise(double x, double z) 22 | { 23 | int integerX = (int)x; 24 | int integerZ = (int)z; 25 | 26 | double fractionalX = x - integerX; 27 | double fractionalZ = z - integerZ; 28 | 29 | double a = GetNoise(integerX, integerZ); 30 | double b = GetNoise(integerX + 1, integerZ); 31 | 32 | double c = GetNoise(integerX, integerZ + 1); 33 | double d = GetNoise(integerX + 1, integerZ + 1); 34 | 35 | double f = CosineInterpolate(a, b, fractionalX); 36 | double g = CosineInterpolate(c, d, fractionalX); 37 | 38 | double result = CosineInterpolate(f, g, fractionalZ); 39 | return result; 40 | } 41 | 42 | double NoiseGenerator::GetNoise(int t) 43 | { 44 | t += m_Seed; 45 | t = (t << 13) ^ t; 46 | t = (t * (t * t * 15731 + 789221) + 1376312589); 47 | return 1.0 - (t & 0x7fffffff) / 1073741824.0; 48 | } 49 | 50 | double NoiseGenerator::GetNoise(double x, double z) 51 | { 52 | return GetNoise(x + z * CHUNK_SIZE); 53 | } 54 | 55 | double NoiseGenerator::CosineInterpolate(double a, double b, double t) 56 | { 57 | double c = (1 - std::cos(t * 3.1415927)) * .5; 58 | 59 | return (1. - c) * a + c * b; 60 | } 61 | 62 | double NoiseGenerator::PerlinNoise(double x, double z){ 63 | double r = 0.0; 64 | for(int i = 0; i < m_NoiseParameters.m_Octaves; i++){ 65 | auto frequency = pow(2.0, i); 66 | auto amplitude = pow(m_NoiseParameters.m_Persistance, i); 67 | r += Noise(x*frequency/m_NoiseParameters.m_Smoothness, z*frequency/m_NoiseParameters.m_Smoothness) * amplitude; 68 | } 69 | auto result = 70 | (((r / 2.1) + 1.2) * m_NoiseParameters.m_Amplitude); 71 | return result > 0 ? result : 1; 72 | } -------------------------------------------------------------------------------- /res/shaders/skyboxtex.shader: -------------------------------------------------------------------------------- 1 | #shader vertex 2 | 3 | #version 130 4 | #extension GL_ARB_explicit_attrib_location : require 5 | #extension GL_ARB_explicit_uniform_location : require 6 | 7 | layout(location = 0) in vec4 position; 8 | layout(location = 2) in float texLight; 9 | 10 | out vec3 v_TexCoord; 11 | uniform mat4 m_MVP; 12 | 13 | void main(){ 14 | gl_Position = m_MVP * position; 15 | v_TexCoord = vec3(position.x * -1, position.y, position.z); 16 | }; 17 | 18 | #shader fragment 19 | 20 | #version 130 21 | #extension GL_ARB_explicit_attrib_location : require 22 | #extension GL_ARB_explicit_uniform_location : require 23 | 24 | layout(location = 0) out vec4 color; 25 | 26 | in vec3 v_TexCoord; 27 | 28 | uniform samplerCube uTexture; 29 | uniform float uTime; 30 | 31 | vec4 applySunrise(vec3 value, vec4 nightColor){ 32 | vec4 middleColor = vec4(1.0, 0.1, 0.1, 1.0); 33 | float minY = 0.4; 34 | float maxY = 0.6; 35 | float y = (normalize(value).y + 1) / 2; 36 | y = (y - minY)/(maxY - minY); 37 | if(y > 1.0){ 38 | y = 1.0; 39 | } 40 | if(y < 0.0){ 41 | y = 0.0; 42 | } 43 | vec4 colorResult = middleColor * (1.0 - y) + nightColor * y; 44 | return colorResult; 45 | } 46 | 47 | vec4 applyLight(vec3 value, float time){ 48 | vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); 49 | vec4 darkColor = vec4(0.2, 0.2, 0.2, 1.0); 50 | vec4 sunriseColor = applySunrise(value, darkColor); 51 | vec4 startColor; 52 | vec4 endColor; 53 | vec4 lightResult; 54 | 55 | if(time <= 0.25){ 56 | float bias = time * 4; 57 | lightResult = sunriseColor * (1.0 - bias) + lightColor * bias; 58 | }else if(time <= 0.35){ 59 | lightResult = lightColor; 60 | }else if(time <= 0.5){ 61 | float bias = (time - 0.35)/(0.5 - 0.35); 62 | lightResult = lightColor * (1.0 - bias) + sunriseColor * bias; 63 | }else if(time <= 0.6){ 64 | float bias = (time - 0.5)/(0.6 - 0.5); 65 | lightResult = sunriseColor * (1.0 - bias) + darkColor * bias; 66 | }else if(time <= 0.75){ 67 | lightResult = darkColor; 68 | }else{ 69 | float bias = (time - 0.75)/(1.0 - 0.75); 70 | lightResult = darkColor * (1.0 - bias) + sunriseColor * bias; 71 | } 72 | 73 | return lightResult; 74 | } 75 | 76 | void main(){ 77 | vec4 texColor = texture(uTexture, v_TexCoord); 78 | texColor = texColor * applyLight(v_TexCoord, uTime); 79 | color = texColor; 80 | }; -------------------------------------------------------------------------------- /src/core/model.cc: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | 3 | Model::Model( 4 | glm::vec3 position, 5 | glm::vec3 rotation, 6 | glm::vec3 velocity, 7 | std::vector vertices, 8 | std::vector indices 9 | ) 10 | : Entity(position, rotation, velocity) 11 | , m_Ib(indices.data(), indices.size()) 12 | , m_Vb(vertices.data(), sizeof(float) * vertices.size()) 13 | { 14 | m_Layout.AddAttribute(3); 15 | m_Layout.AddAttribute(2); 16 | m_Layout.AddAttribute(1); 17 | m_Va.AddBuffer(m_Vb, m_Layout); 18 | } 19 | 20 | Model::Model(): Model(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), {}, {}){} 21 | 22 | Model::~Model(){ 23 | LogTrace("Destructing Model...\n"); 24 | } 25 | 26 | VertexBuffer& Model::GetVBO(){ 27 | return m_Vb; 28 | } 29 | 30 | IndexBuffer& Model::GetIBO(){ 31 | return m_Ib; 32 | } 33 | 34 | VertexBufferLayout& Model::GetLayout(){ 35 | return m_Layout; 36 | } 37 | 38 | VertexArray& Model::GetVAO(){ 39 | return m_Va; 40 | } 41 | 42 | void Model::Render(Camera& camera, float time, Shader& shader, Texture& texture, const bool blend){ 43 | if(blend){ 44 | CallGL(glEnable(GL_BLEND)); 45 | }else{ 46 | CallGL(glDisable(GL_BLEND)); 47 | } 48 | shader.Bind(); 49 | glm::mat4 viewMatrixRotation = camera.GetViewMatrixRotation(); 50 | glm::mat4 projMatrix = camera.GetProjectionMatrix(); 51 | glm::mat4 modelMatrix = camera.GetModelMatrix(); 52 | glm::mat4 MVP = projMatrix * viewMatrixRotation; 53 | shader.SetUniformMat4("m_MVP", MVP); 54 | shader.SetUniform1f("uTime", time); 55 | texture.Bind(); 56 | Draw(GetVAO(), GetIBO()); 57 | } 58 | 59 | void Model::Render(Camera& camera, float time, Shader& shader, const bool blend){ 60 | if(blend){ 61 | CallGL(glEnable(GL_BLEND)); 62 | }else{ 63 | CallGL(glDisable(GL_BLEND)); 64 | } 65 | shader.Bind(); 66 | glm::mat4 viewMatrixRotation = camera.GetViewMatrixRotation(); 67 | glm::mat4 projMatrix = camera.GetProjectionMatrix(); 68 | glm::mat4 modelMatrix = camera.GetModelMatrix(); 69 | glm::mat4 MVP = projMatrix * viewMatrixRotation; 70 | shader.SetUniformMat4("m_MVP", MVP); 71 | shader.SetUniform1f("uTime", time); 72 | Draw(GetVAO(), GetIBO()); 73 | } 74 | 75 | void Model::Draw(const VertexArray &va, const IndexBuffer &ib){ 76 | va.Bind(); 77 | ib.Bind(); 78 | CallGL(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr)); 79 | } -------------------------------------------------------------------------------- /src/core/view-frustum.cc: -------------------------------------------------------------------------------- 1 | #include "view-frustum.h" 2 | #include "entity.h" 3 | 4 | float Plane::DistanceToPoint(const glm::vec3& point) const { 5 | return glm::dot(point, normal) + m_DistanceToOrigin; 6 | } 7 | 8 | void ViewFrustum::Update(const glm::mat4& mat){ 9 | 10 | // left 11 | m_Planes[Planes::Left].normal.x = mat[0][3] + mat[0][0]; 12 | m_Planes[Planes::Left].normal.y = mat[1][3] + mat[1][0]; 13 | m_Planes[Planes::Left].normal.z = mat[2][3] + mat[2][0]; 14 | m_Planes[Planes::Left].m_DistanceToOrigin = mat[3][3] + mat[3][0]; 15 | 16 | // right 17 | m_Planes[Planes::Right].normal.x = mat[0][3] - mat[0][0]; 18 | m_Planes[Planes::Right].normal.y = mat[1][3] - mat[1][0]; 19 | m_Planes[Planes::Right].normal.z = mat[2][3] - mat[2][0]; 20 | m_Planes[Planes::Right].m_DistanceToOrigin = mat[3][3] - mat[3][0]; 21 | 22 | // bottom 23 | m_Planes[Planes::Bottom].normal.x = mat[0][3] + mat[0][1]; 24 | m_Planes[Planes::Bottom].normal.y = mat[1][3] + mat[1][1]; 25 | m_Planes[Planes::Bottom].normal.z = mat[2][3] + mat[2][1]; 26 | m_Planes[Planes::Bottom].m_DistanceToOrigin = mat[3][3] + mat[3][1]; 27 | 28 | // top 29 | m_Planes[Planes::Top].normal.x = mat[0][3] - mat[0][1]; 30 | m_Planes[Planes::Top].normal.y = mat[1][3] - mat[1][1]; 31 | m_Planes[Planes::Top].normal.z = mat[2][3] - mat[2][1]; 32 | m_Planes[Planes::Top].m_DistanceToOrigin = mat[3][3] - mat[3][1]; 33 | 34 | // near 35 | m_Planes[Planes::Near].normal.x = mat[0][3] + mat[0][2]; 36 | m_Planes[Planes::Near].normal.y = mat[1][3] + mat[1][2]; 37 | m_Planes[Planes::Near].normal.z = mat[2][3] + mat[2][2]; 38 | m_Planes[Planes::Near].m_DistanceToOrigin = mat[3][3] + mat[3][2]; 39 | 40 | // far 41 | m_Planes[Planes::Far].normal.x = mat[0][3] - mat[0][2]; 42 | m_Planes[Planes::Far].normal.y = mat[1][3] - mat[1][2]; 43 | m_Planes[Planes::Far].normal.z = mat[2][3] - mat[2][2]; 44 | m_Planes[Planes::Far].m_DistanceToOrigin = mat[3][3] - mat[3][2]; 45 | 46 | for (auto& plane : m_Planes) 47 | { 48 | float length = glm::length(plane.normal); 49 | plane.normal /= length; 50 | plane.m_DistanceToOrigin /= length; 51 | } 52 | } 53 | 54 | bool ViewFrustum::IsInFrustum(const Entity& element) const{ 55 | for(Plane plane: m_Planes){ 56 | if(plane.DistanceToPoint(element.GetVP(plane.normal)) < 0){ 57 | return false; 58 | } 59 | } 60 | return true; 61 | } -------------------------------------------------------------------------------- /src/maths/type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace gm{ 7 | struct mat4; 8 | const float PI = 3.14159265f; 9 | struct vec4 10 | { 11 | float values[4]; 12 | 13 | vec4(float value) 14 | { 15 | values[0] = values[1] = values[2] = values[3] = value; 16 | } 17 | 18 | vec4() 19 | { 20 | values[0] = values[1] = values[2] = values[3] = 0; 21 | } 22 | 23 | vec4( float x, float y, float z, float w ) 24 | { 25 | values[0] = x; 26 | values[1] = y; 27 | values[2] = z; 28 | values[3] = w; 29 | } 30 | 31 | const float& operator[] ( int index ) const 32 | { 33 | return values[index]; 34 | } 35 | float& operator[] ( int index ) 36 | { 37 | return values[index]; 38 | } 39 | float Mag(){ 40 | return sqrt(values[0]*values[0] + values[1]*values[1] + values[2]*values[2]); 41 | } 42 | vec4 Normal(){ 43 | float mag = Mag(); 44 | return *(this)/mag; 45 | } 46 | 47 | float Dot( const vec4& v ); 48 | vec4 Cross( const vec4& v ); 49 | 50 | vec4 operator*( const mat4& m ); 51 | vec4 operator-( const vec4& v ); 52 | float operator*( const vec4& v ); 53 | vec4 operator*( const float value ); 54 | vec4 operator%( const float value ); 55 | vec4 operator/( const float value ); 56 | bool operator==( const vec4& v ); 57 | }; 58 | 59 | struct vec3 : public vec4{ 60 | vec3(): vec4(0,0,0,0){ 61 | } 62 | vec3(float x, float y, float z): vec4(x,y,z,1){} 63 | }; 64 | 65 | struct mat4 66 | { 67 | vec4 columns[4]; 68 | 69 | mat4(float value){ 70 | columns[0] = vec4( value, 0, 0, 0 ); 71 | columns[1] = vec4( 0, value, 0, 0 ); 72 | columns[2] = vec4( 0, 0, value, 0 ); 73 | columns[3] = vec4( 0, 0, 0, value ); 74 | } 75 | 76 | mat4() 77 | { 78 | columns[0] = vec4( 1, 0, 0, 0 ); 79 | columns[1] = vec4( 0, 1, 0, 0 ); 80 | columns[2] = vec4( 0, 0, 1, 0 ); 81 | columns[3] = vec4( 0, 0, 0, 1 ); 82 | } 83 | 84 | mat4( vec4 x, vec4 y, vec4 z, vec4 w ) 85 | { 86 | columns[0] = x; 87 | columns[1] = y; 88 | columns[2] = z; 89 | columns[3] = w; 90 | } 91 | 92 | const vec4& operator[]( int index ) const 93 | { 94 | return columns[index]; 95 | } 96 | vec4& operator[]( int index ) 97 | { 98 | return columns[index]; 99 | } 100 | vec4 operator*( const vec4& v ); 101 | mat4 operator*( const mat4& m2 ); 102 | bool operator==( const mat4& m ); 103 | }; 104 | 105 | mat4 translate(mat4 matrix, vec4 vector); 106 | mat4 scale(vec4 vector); 107 | mat4 rotate(mat4 matrix, float angle, vec4 vector); 108 | mat4 diag(vec4 vector); 109 | } 110 | 111 | 112 | std::ostream & operator << (std::ostream &out, gm::vec4 &v); -------------------------------------------------------------------------------- /src/world/chunk/mesh.cc: -------------------------------------------------------------------------------- 1 | #include "mesh.h" 2 | 3 | Mesh::Mesh(Entity& model): m_Model(model){ 4 | m_Vb = nullptr; 5 | m_Layout = nullptr; 6 | m_Ib = nullptr; 7 | m_Va = nullptr; 8 | } 9 | 10 | Mesh::~Mesh(){ 11 | if(m_Vb != nullptr){ 12 | delete m_Vb; 13 | } 14 | if(m_Layout != nullptr){ 15 | delete m_Layout; 16 | } 17 | if(m_Ib != nullptr){ 18 | delete m_Ib; 19 | } 20 | if(m_Va != nullptr){ 21 | delete m_Va; 22 | } 23 | } 24 | 25 | void Mesh::UpdateVBO(){ 26 | LogTrace("Updating Mesh VBO ...\n"); 27 | if(m_Vb != nullptr){ 28 | delete m_Vb; 29 | } 30 | if(m_Layout != nullptr){ 31 | delete m_Layout; 32 | } 33 | if(m_Ib != nullptr){ 34 | delete m_Ib; 35 | } 36 | if(m_Va != nullptr){ 37 | delete m_Va; 38 | } 39 | if(m_Vertices.size() > 0){ 40 | m_Ib = new IndexBuffer(m_Indices.data(), m_Indices.size()); 41 | m_Vb = new VertexBuffer(m_Vertices.data(), sizeof(float) * m_Vertices.size()); 42 | m_Layout = new VertexBufferLayout(); 43 | m_Layout->AddAttribute(3); 44 | m_Layout->AddAttribute(2); 45 | m_Layout->AddAttribute(1); 46 | m_Va = new VertexArray(); 47 | m_Va->AddBuffer(*(m_Vb), *(m_Layout)); 48 | } 49 | } 50 | 51 | void Mesh::AddFace(std::array& blockFace, std::array& texCoords, glm::vec3& position, float light){ 52 | int nbElementPerLayout = 6; 53 | int countVertices = m_Vertices.size()/nbElementPerLayout; 54 | for(int i = 0; i < blockFace.size(); i+=3){ 55 | m_Vertices.push_back((float)position.x + blockFace[i]); 56 | m_Vertices.push_back((float)position.y + blockFace[i+1]); 57 | m_Vertices.push_back((float)position.z + blockFace[i+2]); 58 | m_Vertices.push_back(texCoords[i/3].x); 59 | m_Vertices.push_back(texCoords[i/3].y); 60 | m_Vertices.push_back(light); 61 | } 62 | m_Indices.push_back(countVertices); 63 | m_Indices.push_back(countVertices + 1); 64 | m_Indices.push_back(countVertices + 2); 65 | m_Indices.push_back(countVertices + 2); 66 | m_Indices.push_back(countVertices + 3); 67 | m_Indices.push_back(countVertices); 68 | } 69 | 70 | void Mesh::DeleteMeshes(){ 71 | m_Vertices.clear(); 72 | m_Indices.clear(); 73 | } 74 | 75 | std::vector Mesh::GetIndices(){ 76 | return m_Indices; 77 | } 78 | 79 | std::vector Mesh::GetVertices(){ 80 | return m_Vertices; 81 | } 82 | 83 | VertexBuffer* Mesh::GetVBO(){ 84 | return m_Vb; 85 | } 86 | 87 | IndexBuffer* Mesh::GetIBO(){ 88 | return m_Ib; 89 | } 90 | 91 | VertexArray* Mesh::GetVAO(){ 92 | return m_Va; 93 | } 94 | 95 | VertexBufferLayout* Mesh::GetLayout(){ 96 | return m_Layout; 97 | } -------------------------------------------------------------------------------- /src/core/entity.cc: -------------------------------------------------------------------------------- 1 | #include "entity.h" 2 | 3 | glm::mat4 Entity::GetModelMatrix() 4 | { 5 | glm::mat4 matrix(1.0f); 6 | 7 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.x), {1, 0, 0}); 8 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.y), {0, 1, 0}); 9 | matrix = glm::rotate(matrix, glm::radians(m_Rotation.z), {0, 0, 1}); 10 | 11 | matrix = glm::translate(matrix, m_Position); 12 | 13 | return matrix; 14 | } 15 | 16 | void Entity::Move(){ 17 | m_Position = GetNewPosition(); 18 | } 19 | 20 | glm::vec3 Entity::GetNewPosition(){ 21 | glm::vec3 newPosition = m_Position; 22 | float yaw = m_Rotation.y; 23 | float pitch = m_Rotation.x; 24 | glm::vec3 front; 25 | front.x = cos(glm::radians(yaw)); 26 | front.y = 0; 27 | front.z = sin(glm::radians(yaw)); 28 | glm::vec3 cameraFront = glm::normalize(front); 29 | glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); 30 | if(m_Velocity.z != 0){ 31 | newPosition += glm::normalize(glm::cross(cameraFront, cameraUp)) * m_Velocity.z; 32 | } 33 | if(m_Velocity.x != 0){ 34 | newPosition += cameraFront * m_Velocity.x; 35 | } 36 | if(m_Velocity.y != 0){ 37 | newPosition += cameraUp * m_Velocity.y; 38 | } 39 | 40 | return newPosition; 41 | } 42 | 43 | glm::vec3 Entity::GetAcceleration(glm::vec3 direction){ 44 | glm::vec3 newAcceleration(0.f); 45 | float yaw = m_Rotation.y; 46 | float pitch = m_Rotation.x; 47 | glm::vec3 front; 48 | front.x = cos(glm::radians(yaw)); 49 | front.y = 0; 50 | front.z = sin(glm::radians(yaw)); 51 | glm::vec3 cameraFront = glm::normalize(front); 52 | glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); 53 | if(direction.z != 0){ 54 | newAcceleration += glm::normalize(glm::cross(cameraFront, cameraUp)) * (direction.z * m_Speed); 55 | } 56 | if(direction.x != 0){ 57 | newAcceleration += cameraFront * (direction.x * m_Speed); 58 | } 59 | if(direction.y != 0){ 60 | newAcceleration += cameraUp * (direction.y * m_Speed); 61 | } 62 | 63 | return newAcceleration; 64 | } 65 | 66 | void Entity::Rotate(float angle, glm::vec3 direction){ 67 | glm::mat4 matrix(1.0f); 68 | glm::vec4 rotation = glm::vec4(m_Rotation.x + direction.x * angle, m_Rotation.y + direction.y * angle, m_Rotation.z + direction.z * angle, 1.0f); 69 | if(rotation[0] <= 90.0f && rotation[0] >= -90.0f){ 70 | m_Rotation = rotation; 71 | } 72 | } 73 | 74 | glm::vec3 Entity::GetVP(const glm::vec3& normal) const 75 | { 76 | glm::vec3 res = m_Position; 77 | glm::vec3 dimensions = {CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE}; 78 | 79 | if (normal.x > 0) 80 | { 81 | res.x += dimensions.x; 82 | } 83 | if (normal.y > 0) 84 | { 85 | res.y += dimensions.y; 86 | } 87 | if (normal.z > 0) 88 | { 89 | res.z += dimensions.z; 90 | } 91 | 92 | return res; 93 | } -------------------------------------------------------------------------------- /src/world/chunk/superchunk.cc: -------------------------------------------------------------------------------- 1 | #include "superchunk.h" 2 | 3 | bool SuperChunk::MakeMesh(Camera& camera) 4 | { 5 | for (Chunk &chunk : m_Chunks) 6 | { 7 | if ( 8 | !chunk.HasMesh() 9 | && camera.GetViewFrustum().IsInFrustum(chunk) 10 | ) 11 | { 12 | chunk.MakeMesh(); 13 | return true; 14 | } 15 | } 16 | return false; 17 | } 18 | 19 | void SuperChunk::SetBlock(int x, int y, int z, BlockType type, bool focus) 20 | { 21 | int index = y / CHUNK_SIZE; 22 | AddChunkIndex(index); 23 | 24 | if(OutOfBounds(x,y,z)){ 25 | return; 26 | } 27 | 28 | m_Chunks[index].SetBlock(x,y % CHUNK_SIZE,z, type, focus); 29 | 30 | if(type != BlockType::Air){ 31 | BlockProps props = BlockBase::Get()->GetBlockProps(type); 32 | 33 | if(y > m_TopBlocks[x][z] && props.m_IsCollidable){ 34 | m_TopBlocks[x][z] = y; 35 | } 36 | } 37 | } 38 | 39 | int SuperChunk::GetTopBlockAt(int x, int z){ 40 | return m_TopBlocks[x][z]; 41 | } 42 | 43 | Block SuperChunk::GetBlock(int x, int y, int z){ 44 | if(OutOfBounds(x, y, z)){ 45 | return BlockType::Air; 46 | } 47 | 48 | return m_Chunks[y / CHUNK_SIZE].GetBlock(x, y % CHUNK_SIZE, z); 49 | } 50 | 51 | bool SuperChunk::OutOfBounds(int x, int y, int z){ 52 | if( 53 | x >= CHUNK_SIZE || 54 | z >= CHUNK_SIZE || 55 | x < 0 || 56 | y < 0 || 57 | z < 0 || 58 | y >= (int)m_Chunks.size() * CHUNK_SIZE 59 | ){ 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | void SuperChunk::Draw(Renderer &renderer, Camera& camera){ 66 | for(Chunk &chunk : m_Chunks){ 67 | if(camera.GetViewFrustum().IsInFrustum(chunk)) 68 | chunk.Draw(renderer); 69 | } 70 | } 71 | 72 | bool SuperChunk::IsLoaded(){ 73 | return m_Loaded; 74 | } 75 | 76 | void SuperChunk::Load(WorldGenerator& generator){ 77 | if(IsLoaded()){ 78 | return; 79 | } 80 | 81 | generator.GenerateTerrain(*this); 82 | 83 | m_Loaded = true; 84 | } 85 | 86 | Chunk& SuperChunk::GetChunk(int index){ 87 | if(index >= (int)m_Chunks.size() || index < 0){ 88 | printf("Error getting chunk outside range! (size : %d)\n", (int)m_Chunks.size()); 89 | exit(EXIT_FAILURE); 90 | } 91 | 92 | return m_Chunks[index]; 93 | } 94 | 95 | void SuperChunk::AddChunk(){ 96 | int y = (int)m_Chunks.size(); 97 | m_Chunks.emplace_back(glm::vec3(m_Position.x, y * CHUNK_SIZE, m_Position.z), *m_World); 98 | } 99 | 100 | void SuperChunk::AddChunkIndex(int index){ 101 | while ((int)m_Chunks.size() <= index) 102 | { 103 | AddChunk(); 104 | } 105 | } 106 | 107 | void SuperChunk::DeleteMeshes(){ 108 | for(Chunk& chunk : m_Chunks){ 109 | chunk.DeleteMeshes(); 110 | } 111 | } 112 | 113 | void SuperChunk::UpdateVBO(){ 114 | for(Chunk& chunk : m_Chunks){ 115 | chunk.UpdateVBO(); 116 | } 117 | } -------------------------------------------------------------------------------- /src/renderer/sky-renderer.cc: -------------------------------------------------------------------------------- 1 | #include "sky-renderer.h" 2 | 3 | SkyRenderer::SkyRenderer() 4 | : m_Skybox(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), GetCubeVertices(500.0), GetCubeIndices()) 5 | , m_Stars(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), GetCubeVertices(400.0), GetCubeIndices()) 6 | , m_Sun(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), GetRectVerticesByBlock(40.0, -390, BlockType::Sun), GetRectIndices()) 7 | , m_Moon(glm::vec3(0,0,0), glm::vec3(0,0,0), glm::vec3(0,0,0), GetRectVerticesByBlock(40.0, -390, BlockType::Moon), GetRectIndices()) 8 | {} 9 | 10 | SkyRenderer::~SkyRenderer(){ 11 | LogTrace("Destructing SkyRenderer...\n"); 12 | } 13 | 14 | std::vector SkyRenderer::GetCubeIndices(){ 15 | std::vector indices = { 16 | 0, 1, 2, 17 | 2, 3, 0, 18 | 19 | 4, 5, 6, 20 | 6, 7, 4, 21 | 22 | 8, 9, 10, 23 | 10, 11, 8, 24 | 25 | 12, 13, 14, 26 | 14, 15, 12, 27 | 28 | 16, 17, 18, 29 | 18, 19, 16, 30 | 31 | 20, 21, 22, 32 | 22, 23, 20 33 | }; 34 | return indices; 35 | } 36 | 37 | std::vector SkyRenderer::GetRectIndices(){ 38 | std::vector indices = { 39 | 0, 1, 2, 40 | 2, 3, 0 41 | }; 42 | return indices; 43 | } 44 | 45 | std::vector SkyRenderer::GetCubeVertices(const float SIZE){ 46 | std::vector vertices = { 47 | -SIZE, -SIZE, -SIZE, 0.0f, 0.0f, 1.0f, 48 | SIZE, -SIZE, -SIZE, 1.0f, 0.0f, 1.0f, 49 | SIZE, SIZE, -SIZE, 1.0f, 1.0f, 1.0f, 50 | -SIZE, SIZE, -SIZE, 0.0f, 1.0f, 1.0f, 51 | 52 | -SIZE, -SIZE, SIZE, 0.0f, 0.0f, 1.0f, 53 | SIZE, -SIZE, SIZE, 1.0f, 0.0f, 1.0f, 54 | SIZE, SIZE, SIZE, 1.0f, 1.0f, 1.0f, 55 | -SIZE, SIZE, SIZE, 0.0f, 1.0f, 1.0f, 56 | 57 | -SIZE, SIZE, SIZE, 1.0f, 1.0f, 1.0f, 58 | -SIZE, SIZE, -SIZE, 0.0f, 1.0f, 1.0f, 59 | -SIZE, -SIZE, -SIZE, 0.0f, 0.0f, 1.0f, 60 | -SIZE, -SIZE, SIZE, 1.0f, 0.0f, 1.0f, 61 | 62 | SIZE, SIZE, SIZE, 0.0f, 1.0f, 1.0f, 63 | SIZE, SIZE, -SIZE, 1.0f, 1.0f, 1.0f, 64 | SIZE, -SIZE, -SIZE, 1.0f, 0.0f, 1.0f, 65 | SIZE, -SIZE, SIZE, 0.0f, 0.0f, 1.0f, 66 | 67 | -SIZE, -SIZE, -SIZE, 0.0f, 1.0f, 1.0f, 68 | SIZE, -SIZE, -SIZE, 1.0f, 1.0f, 1.0f, 69 | SIZE, -SIZE, SIZE, 1.0f, 0.0f, 1.0f, 70 | -SIZE, -SIZE, SIZE, 0.0f, 0.0f, 1.0f, 71 | 72 | -SIZE, SIZE, -SIZE, 0.0f, 1.0f, 1.0f, 73 | SIZE, SIZE, -SIZE, 1.0f, 1.0f, 1.0f, 74 | SIZE, SIZE, SIZE, 1.0f, 0.0f, 1.0f, 75 | -SIZE, SIZE, SIZE, 0.0f, 0.0f, 1.0f 76 | }; 77 | return vertices; 78 | } 79 | 80 | //@TODO : improve getting texCoords from BlockBase 81 | std::vector SkyRenderer::GetRectVerticesByBlock(const float SIZE, const float DEPTHZ, const BlockType TYPE){ 82 | BlockProps SunProps = BlockBase::Get()->GetBlockProps(TYPE); 83 | BlockTex texCoords = SunProps.m_TexCoords; 84 | std::vector vertices = { 85 | -SIZE, -SIZE, DEPTHZ, texCoords.front[0].x, texCoords.front[0].y, 1.0f, 86 | SIZE, -SIZE, DEPTHZ, texCoords.front[1].x, texCoords.front[1].y, 1.0f, 87 | SIZE, SIZE, DEPTHZ, texCoords.front[2].x, texCoords.front[2].y, 1.0f, 88 | -SIZE, SIZE, DEPTHZ, texCoords.front[3].x, texCoords.front[3].y, 1.0f 89 | }; 90 | return vertices; 91 | } 92 | 93 | void SkyRenderer::Render(Camera &camera, float time){ 94 | m_Skybox.Render(camera, time, m_Shader, m_Texture, false); 95 | m_Sun.Render(camera, time, m_SunShader, m_AtlasTexture, true); 96 | m_Moon.Render(camera, time, m_MoonShader, m_AtlasTexture, true); 97 | m_Stars.Render(camera, time, m_StarsShader, m_StarsTexture, true); 98 | } -------------------------------------------------------------------------------- /src/world/player.cc: -------------------------------------------------------------------------------- 1 | #include "player.h" 2 | #include "world.h" 3 | #include "core/window.h" 4 | 5 | Player::Player() 6 | : Entity(glm::vec3(2100.0f, 100.0f, 2100.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 0.02f) 7 | , m_Acceleration(glm::vec3(0)){ 8 | } 9 | 10 | void Player::Update(World& world){ 11 | m_Velocity += m_Acceleration; 12 | m_Acceleration = {0,0,0}; 13 | float gravity; 14 | 15 | if(m_IsUnderWater){ 16 | gravity = 0.0001f; 17 | m_Speed = 0.005f; 18 | }else{ 19 | gravity = 0.02f; 20 | m_Speed = 0.02f; 21 | } 22 | 23 | if(!m_IsFly){ 24 | if(!m_OnGround){ 25 | m_Velocity.y -= gravity * 1; 26 | } 27 | m_OnGround = false; 28 | } 29 | 30 | if(!m_IsFly){ 31 | Collide(world, {m_Velocity.x, 0, 0}); 32 | Collide(world, {0, m_Velocity.y, 0}); 33 | Collide(world, {0, 0, m_Velocity.z}); 34 | } 35 | 36 | m_Position += m_Velocity; 37 | m_Velocity.x *= 0.65f; 38 | m_Velocity.z *= 0.65f; 39 | if(m_IsFly){ 40 | m_Velocity.y *= 0.65f; 41 | } 42 | 43 | if(m_OnGround){ 44 | m_Position.y = floor(m_Position.y); 45 | } 46 | } 47 | 48 | bool Player::IsUnderWater(){ 49 | return m_IsUnderWater; 50 | } 51 | 52 | void Player::SetUnderWater(bool underwater){ 53 | m_IsUnderWater = underwater; 54 | } 55 | 56 | void Player::Collide(World& world, glm::vec3 velocity){ 57 | glm::vec3 dimensions = {0.7f, 0.8f, 0.7f}; 58 | glm::vec3 newPosition = m_Position + velocity; 59 | for(int x = newPosition.x; x <= newPosition.x + dimensions.x; x++) 60 | for(int y = newPosition.y - 1.0f; y <= newPosition.y + dimensions.y; y++) 61 | for(int z = newPosition.z; z <= newPosition.z + dimensions.z; z++) 62 | { 63 | Block block = world.GetBlock(x, y, z); 64 | if(block.GetType() != BlockType::Air && block.GetProps().m_IsCollidable){ 65 | if(velocity.y > 0){ 66 | m_Velocity.y = 0; 67 | }else if(velocity.y < 0){ 68 | m_Velocity.y = 0; 69 | m_OnGround = true; 70 | } 71 | if(velocity.x != 0){ 72 | m_Velocity.x = 0; 73 | } 74 | if(velocity.z != 0){ 75 | m_Velocity.z = 0; 76 | } 77 | } 78 | } 79 | } 80 | 81 | void Player::Jump(){ 82 | if(m_IsUnderWater){ 83 | m_Acceleration.y += 0.001f; 84 | } 85 | else if(m_OnGround){ 86 | m_OnGround = false; 87 | m_Acceleration.y += (m_Speed*1.5f) * 10; 88 | } 89 | } 90 | 91 | void Player::Move(glm::vec3 direction){ 92 | m_Acceleration = GetAcceleration(direction); 93 | } 94 | 95 | void Player::HandleInput(Window& window){ 96 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_W)){ 97 | Move({0.f, 0.f, -1.f}); 98 | } 99 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_S)){ 100 | if(m_IsUnderWater) Move({0.f, -1.f, 0.f}); 101 | else Move({0.f, 0.f, 1.f}); 102 | } 103 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_A)){ 104 | Move({-1.f, 0.f, 0.f}); 105 | } 106 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_D)){ 107 | Move({1.f, 0.f, 0.f}); 108 | } 109 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_SPACE)){ 110 | Jump(); 111 | } 112 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_LEFT_CONTROL)){ 113 | if(!m_IsFly){ 114 | m_IsFly = true; 115 | m_Speed *= 4; 116 | } 117 | } 118 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_RIGHT_CONTROL)){ 119 | if(m_IsFly){ 120 | m_IsFly = false; 121 | m_Speed /= 4; 122 | } 123 | } 124 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_LEFT_SHIFT)){ 125 | m_Acceleration.y += m_Speed; 126 | } 127 | if(window.m_Keyboard.IsKeyPressed(GLFW_KEY_RIGHT_SHIFT)){ 128 | m_Acceleration.y -= m_Speed; 129 | } 130 | } 131 | 132 | Player::~Player(){ 133 | LogTrace("Destructing player...\n"); 134 | } -------------------------------------------------------------------------------- /src/shader/shader.cc: -------------------------------------------------------------------------------- 1 | #include "shader.h" 2 | 3 | Shader::Shader(std::string filepath): m_Filepath(filepath){ 4 | ShaderSources shaders = ParseShader(filepath); 5 | u_ID = CreateShader(shaders.Vertex, shaders.Fragment); 6 | } 7 | 8 | ShaderSources Shader::ParseShader(const std::string &filepath){ 9 | 10 | std::ifstream stream(filepath); 11 | 12 | enum ShaderType{ 13 | NONE = -1, VERTEX = 0, FRAGMENT = 1 14 | }; 15 | 16 | std::string line; 17 | std::stringstream ss[2]; 18 | ShaderType type = ShaderType::NONE; 19 | while(getline(stream, line)){ 20 | if(line.find("#shader") != std::string::npos){ 21 | if(line.find("vertex") != std::string::npos){ 22 | type = ShaderType::VERTEX; 23 | }else if(line.find("fragment") != std::string::npos){ 24 | type = ShaderType::FRAGMENT; 25 | } 26 | }else{ 27 | ss[(int)type] << line << "\n"; 28 | } 29 | } 30 | 31 | return { 32 | ss[(int)ShaderType::VERTEX].str(), 33 | ss[(int)ShaderType::FRAGMENT].str() 34 | }; 35 | } 36 | 37 | unsigned int Shader::CompileShader(unsigned int type, std::string &source){ 38 | unsigned int id = glCreateShader(type); 39 | const char * sourceStr = source.c_str(); 40 | CallGL(glShaderSource(id, 1, &sourceStr, nullptr)); 41 | CallGL(glCompileShader(id)); 42 | 43 | int result; 44 | CallGL(glGetShaderiv(id, GL_COMPILE_STATUS, &result)); 45 | if(result == GL_FALSE){ 46 | int length; 47 | CallGL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length)); 48 | char msg[length]; 49 | CallGL(glGetShaderInfoLog(id, length, &length, msg)); 50 | std::cout << "Failed to compile shader " << (type == GL_VERTEX_SHADER ? "vertex" : "fragmenet") << std::endl; 51 | std::cout << msg << std::endl; 52 | CallGL(glDeleteShader(id)); 53 | return 0; 54 | } 55 | 56 | return id; 57 | } 58 | 59 | unsigned int Shader::CreateShader(std::string &vertex_source, std::string &fragmement_source){ 60 | 61 | unsigned int program = glCreateProgram(); 62 | unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertex_source); 63 | unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmement_source); 64 | 65 | CallGL(glAttachShader(program, vs)); 66 | CallGL(glAttachShader(program, fs)); 67 | 68 | CallGL(glLinkProgram(program)); 69 | CallGL(glValidateProgram(program)); 70 | 71 | CallGL(glDeleteShader(vs)); 72 | CallGL(glDeleteShader(fs)); 73 | 74 | return program; 75 | } 76 | 77 | void Shader::Bind() const{ 78 | CallGL(glUseProgram(u_ID)); 79 | } 80 | 81 | void Shader::Unbind() const{ 82 | CallGL(glUseProgram(0)); 83 | } 84 | 85 | int Shader::GetLocation(std::string name){ 86 | if(m_UnformLocation.find(name) != m_UnformLocation.end()){ 87 | return m_UnformLocation[name]; 88 | } 89 | CallGL(int location = glGetUniformLocation(u_ID, name.c_str())); 90 | if(location == -1){ 91 | std::cout << "Warning : Location of " << name << " not founded !" << std::endl; 92 | } 93 | m_UnformLocation[name] = location; 94 | return location; 95 | } 96 | 97 | void Shader::SetUniform4f(std::string name, float v1, float v2, float v3, float v4){ 98 | int location = GetLocation(name); 99 | if(location != -1){ 100 | CallGL(glUniform4f(location,v1, v2, v3, v4)); 101 | } 102 | } 103 | 104 | void Shader::SetUniform1i(std::string name, int value){ 105 | int location = GetLocation(name); 106 | CallGL(glUniform1i(location,value)); 107 | } 108 | 109 | void Shader::SetUniform1f(std::string name, float value){ 110 | int location = GetLocation(name); 111 | CallGL(glUniform1f(location,value)); 112 | } 113 | 114 | void Shader::SetUniformMat4(std::string name, glm::mat4 value){ 115 | int location = GetLocation(name); 116 | CallGL(glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)&value)); 117 | } 118 | 119 | Shader::~Shader(){ 120 | LogTrace("Destructing Shader %d...\n", u_ID); 121 | glDeleteProgram(u_ID); 122 | } 123 | -------------------------------------------------------------------------------- /src/maths/type.cc: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | 3 | namespace gm{ 4 | 5 | vec4 mat4::operator*( const vec4& v ) 6 | { 7 | vec4 result; 8 | for(int i = 0; i < 4; i++){ 9 | for(int j = 0; j < 1; j++){ 10 | for(int k = 0; k < 4; k ++){ 11 | result[i] += (columns[i][k] * v[k]); 12 | } 13 | } 14 | } 15 | return result; 16 | } 17 | 18 | vec4 vec4::operator*( const mat4& m ) 19 | { 20 | vec4 result; 21 | for(int i = 0; i < 1; i++){ 22 | for(int j = 0; j < 4; j++){ 23 | for(int k = 0; k < 4; k ++){ 24 | result[j] += (values[k] * m[k][j]); 25 | } 26 | } 27 | } 28 | return result; 29 | } 30 | 31 | vec4 vec4::operator*( const float value ) 32 | { 33 | return vec4( 34 | values[0] * value, 35 | values[1] * value, 36 | values[2] * value, 37 | values[3] 38 | ); 39 | } 40 | 41 | vec4 vec4::operator/( const float value ) 42 | { 43 | return vec4( 44 | values[0] / value, 45 | values[1] / value, 46 | values[2] / value, 47 | values[3] 48 | ); 49 | } 50 | 51 | float vec4::Dot( const vec4 &v ) 52 | { 53 | return values[0]*v[0] + values[1]*v[1] + values[2]*v[2]; 54 | } 55 | 56 | vec4 vec4::Cross( const vec4 &v ) 57 | { 58 | return gm::vec3( 59 | values[1]*v[2] - values[2]*v[1], 60 | values[2]*v[0] - values[0]*v[2], 61 | values[0]*v[1] - values[1]*v[0] 62 | ); 63 | } 64 | 65 | vec4 vec4::operator-( const vec4 &v ) 66 | { 67 | return vec3(values[0]-v[0],values[1]-v[1],values[2]-v[2]); 68 | } 69 | 70 | bool vec4::operator==( const vec4 &v ) 71 | { 72 | return values[0] == v[0] && values[1] == v[1] && values[2] == v[2]; 73 | } 74 | 75 | vec4 vec4::operator%( const float value ) 76 | { 77 | return vec4( 78 | fmod(values[0],value), 79 | fmod(values[1],value), 80 | fmod(values[2],value), 81 | fmod(values[3],value) 82 | ); 83 | } 84 | 85 | mat4 mat4::operator*( const mat4& m2 ) 86 | { 87 | mat4 result(0.0f); 88 | for(int i = 0; i < 4; i++){ 89 | for(int j = 0; j < 4; j++){ 90 | for(int k = 0; k < 4; k ++){ 91 | result[i][j] += (columns[i][k] * m2[k][j]); 92 | } 93 | } 94 | } 95 | return result; 96 | } 97 | 98 | bool mat4::operator==( const mat4& m ) 99 | { 100 | return columns[0] == m[0] && columns[1] == m[1] && columns[2] == m[2]; 101 | } 102 | 103 | mat4 translate(mat4 matrix, vec4 vector){ 104 | matrix[0][3] += vector[0]; 105 | matrix[1][3] += vector[1]; 106 | matrix[2][3] += vector[2]; 107 | return matrix; 108 | } 109 | 110 | mat4 scale(vec4 vector){ 111 | mat4 matrix; 112 | matrix[0][0] = vector[0]; 113 | matrix[1][1] = vector[1]; 114 | matrix[2][2] = vector[2]; 115 | return matrix; 116 | } 117 | 118 | mat4 rotate(mat4 matrix, float angle, vec4 vector){ 119 | float angleRadian = angle * PI / 180; 120 | if(vector[0] == 1){ 121 | mat4 matrixRX( 122 | vec4(1.0f, 0.0f, 0.0f, 0.0f), 123 | vec4(0.0f, cos(angleRadian), -1*sin(angleRadian), 0.0f), 124 | vec4(0.0f, sin(angleRadian), cos(angleRadian), 0.0f), 125 | vec4(0.0f, 0.0f, 0.0f, 1.0f) 126 | ); 127 | matrix = matrix * matrixRX; 128 | } 129 | if(vector[1] == 1){ 130 | mat4 matrixRY( 131 | vec4(cos(angleRadian), 0.0f, sin(angleRadian), 0.0f), 132 | vec4(0.0f, 1.0f, 0.0f, 0.0f), 133 | vec4(-1*sin(angleRadian), 0.0f, cos(angleRadian), 0.0f), 134 | vec4(0.0f, 0.0f, 0.0f, 1.0f) 135 | ); 136 | matrix = matrix * matrixRY; 137 | } 138 | if(vector[2] == 1){ 139 | mat4 matrixRZ( 140 | vec4(cos(angleRadian), -1*sin(angleRadian), 0.0f, 0.0f), 141 | vec4(sin(angleRadian), cos(angleRadian), 0.0f, 0.0f), 142 | vec4(0.0f, 0.0f, 1.0f, 0.0f), 143 | vec4(0.0f, 0.0f, 0.0f, 1.0f) 144 | ); 145 | matrix = matrix * matrixRZ; 146 | } 147 | return matrix; 148 | } 149 | 150 | mat4 diag(vec4 vector){ 151 | return mat4( 152 | vec4(vector[0], 0, 0, 0), 153 | vec4(0, vector[1], 0, 0), 154 | vec4(0, 0, vector[2], 0), 155 | vec4(0, 0, 0, vector[3]) 156 | ); 157 | } 158 | 159 | } 160 | 161 | std::ostream & operator << (std::ostream &out, gm::vec4 &v) 162 | { 163 | out << "(" << v.values[0] << "," << v.values[1] << "," << v.values[2] << "," << v.values[3] << ")" << std::endl; 164 | return out; 165 | } -------------------------------------------------------------------------------- /src/core/application.cc: -------------------------------------------------------------------------------- 1 | #include "application.h" 2 | #include "world/block/block-base.h" 3 | 4 | std::unique_ptr Application::m_Instance = nullptr; 5 | 6 | Application::Application() 7 | : m_Window(nullptr) 8 | , m_Running(false) 9 | , m_Camera(100.0f, 0.1f, 1000.0f) 10 | , m_StartTime(Time::GetMTime()) 11 | , m_OneDayTime(600) 12 | { 13 | BlockBase::Get(); 14 | } 15 | 16 | std::unique_ptr& Application::GetInstance(){ 17 | if(Application::m_Instance == nullptr){ 18 | Application::m_Instance = std::unique_ptr(new Application); 19 | } 20 | return Application::m_Instance; 21 | } 22 | 23 | void Application::Run(){ 24 | auto& instance = GetInstance(); 25 | instance->m_Running = true; 26 | instance->Init(); 27 | 28 | instance->m_World = World::GetInstance(instance->m_Camera); 29 | instance->m_Renderer = std::make_unique(); 30 | 31 | double lastTime = glfwGetTime(); 32 | int nbFrames = 0; 33 | while (instance->m_Running) 34 | { 35 | double currentTime = glfwGetTime(); 36 | nbFrames++; 37 | if ( currentTime - lastTime >= 1.0 ){ 38 | instance->m_Window->SetTitle("Voxel Game (" + std::to_string(double(nbFrames)) + ")"); 39 | nbFrames = 0; 40 | lastTime += 1.0; 41 | } 42 | instance->m_Renderer->Clear(); 43 | 44 | instance->UpdateTime(); 45 | instance->m_World->m_Player.Update(*instance->m_World); 46 | instance->m_World->Update(instance->m_Camera); 47 | instance->m_Camera.Update(instance->m_World->m_Player); 48 | instance->m_World->Render(*instance->m_Renderer, instance->m_Camera); 49 | instance->m_Renderer->Render(instance->m_Camera, instance->m_AppTime, instance->m_World->m_Player.IsUnderWater()); 50 | 51 | glfwSwapBuffers(instance->m_Window->GetNativeWindow()); 52 | OnEvent(); 53 | glfwPollEvents(); 54 | } 55 | } 56 | 57 | void Application::handleKeyDownEvent(EventKeyboard &key){ 58 | if(key.m_Key == GLFW_KEY_ESCAPE){ 59 | m_Running = false; 60 | } 61 | } 62 | 63 | void Application::handleMouseMotion(EventMouseMotion &motion){ 64 | m_Window->CenterCursor(); 65 | float xMove = motion.m_Xpos - (m_Window->GetWidth()/2); 66 | float yMove = motion.m_Ypos - (m_Window->GetHeight()/2); 67 | m_World->m_Player.Rotate(xMove/2.0f, glm::vec3(0.0f, 1.0f, 0.0f)); 68 | m_World->m_Player.Rotate(yMove/2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 69 | } 70 | 71 | void Application::OnEvent(){ 72 | auto& instance = GetInstance(); 73 | EventsPool *eventsPool = instance->m_Window->events.get(); 74 | Event* ev; 75 | while (ev = eventsPool->PollEvent()) 76 | { 77 | switch(ev->type){ 78 | case EVENT_QUIT: 79 | instance->m_Running = false; 80 | break; 81 | case EVENT_KEYDOWN: 82 | instance->handleKeyDownEvent(ev->key); 83 | break; 84 | case EVENT_MOUSEMOTION: 85 | instance->handleMouseMotion(ev->motion); 86 | break; 87 | } 88 | delete ev; 89 | } 90 | instance->m_World->m_Player.HandleInput(*instance->m_Window); 91 | instance->handleMouseDown(); 92 | } 93 | 94 | void Application::handleMouseDown(){ 95 | if(m_Window->m_Mouse.IsButtonPressed(MouseButton::LEFT)){ 96 | m_World->Mine(m_Camera); 97 | } 98 | } 99 | 100 | bool Application::Init(){ 101 | GetInstance()->m_Window = Window::Create("Voxel Game", SCREEN_WIDTH, SCREEN_HEIGHT); 102 | GetInstance()->m_Window->InitEvents(); 103 | if(glewInit() != GLEW_OK){ 104 | std::cout << "Error !" << std::endl; 105 | exit(EXIT_FAILURE); 106 | } 107 | 108 | CallGL(glEnable(GL_DEPTH_TEST)); 109 | CallGL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); 110 | return true; 111 | } 112 | 113 | void Application::UpdateTime(){ 114 | std::chrono::milliseconds timeNow = Time::GetMTime(); 115 | float timeRel = ((timeNow.count() - m_StartTime.count())%(m_OneDayTime*1000))/((float)m_OneDayTime*1000/2); 116 | m_AppTime = timeRel/2; 117 | } 118 | 119 | Application::~Application(){ 120 | LogTrace("Destructing application...\n"); 121 | } -------------------------------------------------------------------------------- /src/core/window.cc: -------------------------------------------------------------------------------- 1 | #include "window.h" 2 | 3 | Window::Window(){} 4 | 5 | Window* Window::Create(std::string title, int width, int height){ 6 | Window *instance = new Window; 7 | instance->m_Width = width; 8 | instance->m_Height = height; 9 | instance->m_Title = title; 10 | instance->events = std::make_unique(); 11 | 12 | if (!glfwInit()) 13 | return nullptr; 14 | CallGL(glfwInitHint(GLFW_CONTEXT_VERSION_MAJOR, 3)); 15 | CallGL(glfwInitHint(GLFW_CONTEXT_VERSION_MINOR, 3)); 16 | CallGL(glfwInitHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)); 17 | instance->m_Window = glfwCreateWindow(instance->m_Width, instance->m_Height, title.c_str(), NULL, NULL); 18 | if(!instance->m_Window){ 19 | CallGL(glfwTerminate()); 20 | }else{ 21 | glfwSetWindowUserPointer(instance->m_Window, instance); 22 | CallGL(glfwMakeContextCurrent(instance->m_Window)); 23 | CallGL(glfwSwapInterval(1)); 24 | } 25 | return instance; 26 | } 27 | 28 | void Window::SetTitle(std::string title){ 29 | glfwSetWindowTitle(m_Window, title.c_str()); 30 | } 31 | 32 | GLFWwindow* Window::GetNativeWindow(){ 33 | return m_Window; 34 | } 35 | 36 | Window::~Window(){ 37 | LogTrace("Destructing window...\n"); 38 | glfwTerminate(); 39 | } 40 | 41 | void Window::CenterCursor(){ 42 | glfwSetCursorPos(m_Window, m_Width/2, m_Height/2); 43 | } 44 | 45 | int Window::GetWidth(){ 46 | return m_Width; 47 | } 48 | 49 | int Window::GetHeight(){ 50 | return m_Height; 51 | } 52 | 53 | void Window::InitEvents(){ 54 | 55 | CenterCursor(); 56 | //glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 57 | 58 | glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* nativeWindow){ 59 | Event* event = new Event(); 60 | event->type = EVENT_QUIT; 61 | 62 | Window *window = reinterpret_cast(glfwGetWindowUserPointer(nativeWindow)); 63 | EventsPool *events = window->events.get(); 64 | events->Push(event); 65 | }); 66 | 67 | glfwSetKeyCallback(m_Window, [](GLFWwindow* nativeWindow, int key, int scancode, int action, int mods){ 68 | Window *window = reinterpret_cast(glfwGetWindowUserPointer(nativeWindow)); 69 | Event* event = new Event(); 70 | switch (action) 71 | { 72 | case GLFW_REPEAT: 73 | case GLFW_PRESS: 74 | event->type = EVENT_KEYDOWN; 75 | event->key = EventKeyboard(key, scancode); 76 | window->m_Keyboard.SetKeyPressed(key); 77 | break; 78 | case GLFW_RELEASE: 79 | event->type = EVENT_KEYUP; 80 | event->key = EventKeyboard(key, scancode); 81 | window->m_Keyboard.SetKeyReleased(key); 82 | break; 83 | 84 | default: 85 | break; 86 | } 87 | 88 | EventsPool *events = window->events.get(); 89 | events->Push(event); 90 | }); 91 | 92 | glfwSetCursorPos(m_Window, m_Width/2, m_Height/2); 93 | 94 | glfwSetCursorPosCallback(m_Window, [](GLFWwindow* nativeWindow, double xpos, double ypos){ 95 | Event* event = new Event(); 96 | event->type = EVENT_MOUSEMOTION; 97 | event->motion = EventMouseMotion(xpos, ypos); 98 | 99 | Window *window = reinterpret_cast(glfwGetWindowUserPointer(nativeWindow)); 100 | EventsPool *events = window->events.get(); 101 | events->Push(event); 102 | }); 103 | 104 | glfwSetMouseButtonCallback(m_Window, [](GLFWwindow* nativeWindow, int button, int action, int mods){ 105 | Window *window = reinterpret_cast(glfwGetWindowUserPointer(nativeWindow)); 106 | switch (button) 107 | { 108 | case GLFW_MOUSE_BUTTON_RIGHT: 109 | if(action == GLFW_PRESS) 110 | window->m_Mouse.SetButtonPressed(MouseButton::RIGHT); 111 | else if(action == GLFW_RELEASE) 112 | window->m_Mouse.SetButtonReleased(MouseButton::RIGHT); 113 | break; 114 | case GLFW_MOUSE_BUTTON_LEFT: 115 | if(action == GLFW_PRESS) 116 | window->m_Mouse.SetButtonPressed(MouseButton::LEFT); 117 | else if(action == GLFW_RELEASE) 118 | window->m_Mouse.SetButtonReleased(MouseButton::LEFT); 119 | break; 120 | 121 | default: 122 | break; 123 | } 124 | }); 125 | 126 | } -------------------------------------------------------------------------------- /src/world/block/block-props.cc: -------------------------------------------------------------------------------- 1 | #include "block-props.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace{ 7 | struct AttributeBlockFile 8 | { 9 | static std::string Id; 10 | static std::string TexTop; 11 | static std::string TexBottom; 12 | static std::string TexSide; 13 | static std::string TexAll; 14 | static std::string Type; 15 | static std::string Collidable; 16 | static std::string Opaque; 17 | }; 18 | std::string AttributeBlockFile::Id = "Id"; 19 | std::string AttributeBlockFile::TexTop = "TexTop"; 20 | std::string AttributeBlockFile::TexBottom = "TexBottom"; 21 | std::string AttributeBlockFile::TexSide = "TexSide"; 22 | std::string AttributeBlockFile::TexAll = "TexAll"; 23 | std::string AttributeBlockFile::Type = "Type"; 24 | std::string AttributeBlockFile::Collidable = "Collidable"; 25 | std::string AttributeBlockFile::Opaque = "Opaque"; 26 | }; 27 | 28 | //@TODO : Optimize function 29 | BlockProps::BlockProps(const std::string block){ 30 | std::ifstream stream("res/blocks/" + block + ".block"); 31 | int atlasNumEl = 10; 32 | 33 | if(!stream.is_open()){ 34 | std::cout << "Unable to open file " << block.c_str() << std::endl; 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | float minX = 0.001f; 39 | float maxX = 0.099f; 40 | float minY = 0.001f; 41 | float maxY = 0.099f; 42 | 43 | std::string line; 44 | while(getline(stream, line)){ 45 | std::stringstream ss; 46 | if(line.find(AttributeBlockFile::Id + ":") == 0){ 47 | int id; 48 | line.replace(0, AttributeBlockFile::Id.size() + 1, ""); 49 | ss << line; 50 | ss >> id; 51 | //m_Id = static_cast(id); 52 | }else if(line.find(AttributeBlockFile::TexTop + ":") == 0){ 53 | int x, y; 54 | line.replace(0, AttributeBlockFile::TexTop.size() + 1, ""); 55 | ss << line; 56 | ss >> y >> x; 57 | float indexX = ((float)x)/atlasNumEl; 58 | float indexY = ((float)y)/atlasNumEl; 59 | m_TexCoords.top = { 60 | indexX + minX, indexY + minY, 61 | indexX + maxX, indexY + minY, 62 | indexX + maxX, indexY + maxY, 63 | indexX + minX, indexY + maxY 64 | }; 65 | }else if(line.find(AttributeBlockFile::TexBottom + ":") == 0){ 66 | int x, y; 67 | line.replace(0, AttributeBlockFile::TexBottom.size() + 1, ""); 68 | ss << line; 69 | ss >> y >> x; 70 | float indexX = ((float)x)/atlasNumEl; 71 | float indexY = ((float)y)/atlasNumEl; 72 | m_TexCoords.bottom = { 73 | indexX + minX, indexY + maxY, 74 | indexX + maxX, indexY + maxY, 75 | indexX + maxX, indexY + minY, 76 | indexX + minX, indexY + minY 77 | }; 78 | }else if(line.find(AttributeBlockFile::TexSide + ":") == 0){ 79 | int x, y; 80 | line.replace(0, AttributeBlockFile::TexSide.size() + 1, ""); 81 | ss << line; 82 | ss >> y >> x; 83 | float indexX = ((float)x)/atlasNumEl; 84 | float indexY = ((float)y)/atlasNumEl; 85 | m_TexCoords.front = m_TexCoords.back = { 86 | indexX + minX, indexY + minY, 87 | indexX + maxX, indexY + minY, 88 | indexX + maxX, indexY + maxY, 89 | indexX + minX, indexY + maxY 90 | }; 91 | m_TexCoords.left = { 92 | indexX + maxX, indexY + maxY, 93 | indexX + minX, indexY + maxY, 94 | indexX + minX, indexY + minY, 95 | indexX + maxX, indexY + minY 96 | }; 97 | m_TexCoords.right = { 98 | indexX + minX, indexY + maxY, 99 | indexX + maxX, indexY + maxY, 100 | indexX + maxX, indexY + minY, 101 | indexX + minX, indexY + minY 102 | }; 103 | }else if(line.find(AttributeBlockFile::TexAll + ":") == 0){ 104 | int x, y; 105 | line.replace(0, AttributeBlockFile::TexAll.size() + 1, ""); 106 | ss << line; 107 | ss >> y >> x; 108 | float indexX = ((float)x)/atlasNumEl; 109 | float indexY = ((float)y)/atlasNumEl; 110 | m_TexCoords.front = m_TexCoords.back = m_TexCoords.left = m_TexCoords.right = m_TexCoords.top = m_TexCoords.bottom = { 111 | indexX + minX, indexY + minY, 112 | indexX + maxX, indexY + minY, 113 | indexX + maxX, indexY + maxY, 114 | indexX + minX, indexY + maxY 115 | }; 116 | }else if(line.find(AttributeBlockFile::Type + ":") == 0){ 117 | int type; 118 | line.replace(0, AttributeBlockFile::Type.size() + 1, ""); 119 | ss << line; 120 | ss >> type; 121 | m_MeshType = static_cast(type); 122 | }else if(line.find(AttributeBlockFile::Collidable + ":") == 0){ 123 | bool collidable; 124 | line.replace(0, AttributeBlockFile::Collidable.size() + 1, ""); 125 | ss << line; 126 | ss >> collidable; 127 | m_IsCollidable = collidable; 128 | }else if(line.find(AttributeBlockFile::Opaque + ":") == 0){ 129 | bool opaque; 130 | line.replace(0, AttributeBlockFile::Opaque.size() + 1, ""); 131 | ss << line; 132 | ss >> opaque; 133 | m_IsOpaque = opaque; 134 | } 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /src/world/world-generator.cc: -------------------------------------------------------------------------------- 1 | #include "world-generator.h" 2 | #include "chunk/superchunk.h" 3 | 4 | namespace 5 | { 6 | const int seed = Random::Get().GetIntInRange(500, 500000); 7 | } 8 | 9 | WorldGenerator::WorldGenerator() 10 | : m_MountainBiome(seed), m_BiomeNoise(seed), m_GrassLandBiome(seed), m_CloudNoise(seed) 11 | { 12 | SetBiomeNoiseParams(); 13 | SetCloudNoiseParams(); 14 | } 15 | 16 | void WorldGenerator::SetBiomeNoiseParams(){ 17 | NoiseParameters params; 18 | params.m_Octaves = 6; 19 | params.m_Amplitude = 120.0; 20 | params.m_Persistance = 0.75; 21 | params.m_Smoothness = 1000.0; 22 | m_BiomeNoise.SetParameters(params); 23 | } 24 | 25 | void WorldGenerator::SetCloudNoiseParams(){ 26 | NoiseParameters params; 27 | params.m_Octaves = 7; 28 | params.m_Amplitude = 40.0; 29 | params.m_Persistance = 0.50; 30 | params.m_Smoothness = 60; 31 | m_CloudNoise.SetParameters(params); 32 | } 33 | 34 | Biome &WorldGenerator::GetBiome(int x, int z) 35 | { 36 | double biomeValue = m_BiomeNoise.PerlinNoise(x, z); 37 | if(biomeValue > 100){ 38 | return m_GrassLandBiome; 39 | }else{ 40 | return m_MountainBiome; 41 | } 42 | } 43 | 44 | 45 | int WorldGenerator::GetHeight(int x, int z) 46 | { 47 | Biome &biome = GetBiome(x, z); 48 | int height = biome.GetHeight(x, z); 49 | return height; 50 | } 51 | 52 | 53 | 54 | int WorldGenerator::GetHeightIn(int xMin, int zMin, int xMax, int zMax) 55 | { 56 | int xChunk = m_Chunk->m_Position.x; 57 | int zChunk = m_Chunk->m_Position.z; 58 | 59 | float bottomLeft = static_cast(GetHeight(xChunk + xMin, zChunk + zMin)); 60 | float bottomRight = static_cast(GetHeight(xChunk + xMax, zChunk + zMin)); 61 | float topLeft = static_cast(GetHeight(xChunk + xMin, zChunk + zMax)); 62 | float topRight = static_cast(GetHeight(xChunk + xMax, zChunk + zMax)); 63 | 64 | for (int x = xMin; x < xMax; x++) 65 | for (int z = zMin; z < zMax; z++) 66 | { 67 | if (x == CHUNK_SIZE) 68 | continue; 69 | if (z == CHUNK_SIZE) 70 | continue; 71 | 72 | float h = smoothInterpolation( 73 | bottomLeft, topLeft, bottomRight, topRight, 74 | static_cast(xMin), static_cast(xMax), 75 | static_cast(zMin), static_cast(zMax), 76 | static_cast(x), static_cast(z)); 77 | 78 | m_HeightMap[x][z] = static_cast(h); 79 | } 80 | } 81 | 82 | void WorldGenerator::GenerateHeightMap() 83 | { 84 | const int part = 2; 85 | const int PART_SIZE = CHUNK_SIZE / part; 86 | for(int zPart = 0; zPart < part; zPart ++){ 87 | for(int xPart = 0; xPart < part; xPart ++){ 88 | GetHeightIn( 89 | xPart * PART_SIZE, 90 | zPart * PART_SIZE, 91 | (xPart + 1) * PART_SIZE, 92 | (zPart + 1) * PART_SIZE 93 | ); 94 | } 95 | } 96 | } 97 | 98 | void WorldGenerator::GenerateTerrain(SuperChunk &chunk) 99 | { 100 | m_Chunk = &chunk; 101 | 102 | GenerateHeightMap(); 103 | 104 | std::vector trees; 105 | std::vector plants; 106 | 107 | for (int x = 0; x < CHUNK_SIZE; x++) 108 | for (int z = 0; z < CHUNK_SIZE; z++) 109 | { 110 | int height = m_HeightMap[x][z]; 111 | Biome &biome = GetBiome(m_Chunk->m_Position.x + x, m_Chunk->m_Position.z + z); 112 | 113 | int h = std::max(WATER_LEVEL, height); 114 | for (int y = 0; y <= h; y++) 115 | { 116 | if (y <= height) 117 | { 118 | if (y == height) 119 | { 120 | if (y >= WATER_LEVEL) 121 | { 122 | if(y < WATER_LEVEL + 2){ 123 | m_Chunk->SetBlock(x, y, z, biome.GetNearWaterBlock()); 124 | continue; 125 | } 126 | if (Random::Get().GetIntInRange(0, biome.GetTreeFreq()) == 2) 127 | { 128 | trees.emplace_back(x, y + 1, z); 129 | } 130 | if (Random::Get().GetIntInRange(0, biome.GetPlantFreq()) == 2) 131 | { 132 | plants.emplace_back(x, y + 1, z); 133 | } 134 | m_Chunk->SetBlock(x, y, z, biome.GetTopBlock()); 135 | } 136 | else 137 | { 138 | m_Chunk->SetBlock(x, y, z, biome.GetUnderWaterBlock()); 139 | } 140 | } 141 | else 142 | { 143 | m_Chunk->SetBlock(x, y, z, biome.GetBlockInY(y)); 144 | } 145 | } 146 | else 147 | { 148 | if (y <= WATER_LEVEL) 149 | { 150 | m_Chunk->SetBlock(x, y, z, BlockType::Water); 151 | } 152 | else 153 | { 154 | m_Chunk->SetBlock(x, y, z, BlockType::Air); 155 | } 156 | } 157 | } 158 | } 159 | 160 | for (glm::vec3 &plant : plants) 161 | { 162 | Biome &biome = GetBiome(m_Chunk->m_Position.x + plant.x, m_Chunk->m_Position.z + plant.z); 163 | m_Chunk->SetBlock(plant.x, plant.y, plant.z, biome.GetPlant()); 164 | } 165 | for (glm::vec3 &tree : trees) 166 | { 167 | Biome &biome = GetBiome(m_Chunk->m_Position.x + tree.x, m_Chunk->m_Position.z + tree.z); 168 | biome.MakeTree(*m_Chunk, tree); 169 | } 170 | GenerateClouds(chunk); 171 | } 172 | 173 | void WorldGenerator::GenerateClouds(SuperChunk &chunk) 174 | { 175 | m_Chunk = &chunk; 176 | 177 | for (int x = 0; x < CHUNK_SIZE; x++) 178 | for (int z = 0; z < CHUNK_SIZE; z++) 179 | { 180 | double cloudValue = m_CloudNoise.PerlinNoise(m_Chunk->m_Position.x + x, m_Chunk->m_Position.z + z); 181 | if (cloudValue > 60) 182 | { 183 | m_Chunk->SetBlock(x, SKY_LEVEL, z, BlockType::Cloud); 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /src/world/chunk/chunk.cc: -------------------------------------------------------------------------------- 1 | #include "chunk.h" 2 | #include "../world.h" 3 | #include "../block/block-base.h" 4 | 5 | Chunk::Chunk(glm::vec3 position, World& world): m_World(&world), Entity(position), m_Meshes(*this){ 6 | } 7 | 8 | Chunk::Chunk(World& world): Chunk(glm::vec3(0,0,0), world){ 9 | } 10 | 11 | Chunk::~Chunk(){ 12 | } 13 | 14 | void Chunk::Draw(Renderer& renderer){ 15 | if(m_hasMesh){ 16 | renderer.DrawChunk(this); 17 | } 18 | } 19 | 20 | bool Chunk::MakeMesh(){ 21 | LogTrace("Making mesh (%d, %d) ...\n", (int)m_Position.x, (int)m_Position.z); 22 | m_Meshes.m_Solid.DeleteMeshes(); 23 | for(int x=0; x& blockFace, std::array& texCoords, glm::vec3& position, glm::vec3 AdjacentBlock, float light){ 51 | //@TODO : verify why position.y = 0 is showed (comment this condition to see the problem) 52 | if(m_Position.y == 0) return; 53 | ///////////////////////////////////////////////////////////////////////////////////////// 54 | if(ShouldAddFace(AdjacentBlock, position)){ 55 | Block block = GetBlock(position.x, position.y, position.z); 56 | if(block.GetType() == BlockType::Water){ 57 | m_Meshes.m_Water.AddFace(blockFace, texCoords, position, light); 58 | }else if(block.GetType() == BlockType::Cloud){ 59 | m_Meshes.m_Cloud.AddFace(blockFace, texCoords, position, light); 60 | }else{ 61 | m_Meshes.m_Solid.AddFace(blockFace, texCoords, position, light); 62 | } 63 | } 64 | } 65 | 66 | void Chunk::TryAddBlock(int x, int y, int z){ 67 | 68 | Block block = GetBlock(x, y, z); 69 | if(!block.IsActive() || block.GetType() == BlockType::Air){ 70 | return; 71 | } 72 | 73 | std::array frontFace = { 74 | -0.5f, -0.5f, -0.5f, 75 | 0.5f, -0.5f, -0.5f, 76 | 0.5f, 0.5f, -0.5f, 77 | -0.5f, 0.5f, -0.5f 78 | }; 79 | std::array backFace = { 80 | -0.5f, -0.5f, 0.5f, 81 | 0.5f, -0.5f, 0.5f, 82 | 0.5f, 0.5f, 0.5f, 83 | -0.5f, 0.5f, 0.5f 84 | }; 85 | std::array leftFace = { 86 | -0.5f, 0.5f, 0.5f, 87 | -0.5f, 0.5f, -0.5f, 88 | -0.5f, -0.5f, -0.5f, 89 | -0.5f, -0.5f, 0.5f 90 | }; 91 | std::array rightFace = { 92 | 0.5f, 0.5f, 0.5f, 93 | 0.5f, 0.5f, -0.5f, 94 | 0.5f, -0.5f, -0.5f, 95 | 0.5f, -0.5f, 0.5f 96 | }; 97 | std::array bottomFace = { 98 | -0.5f, -0.5f, -0.5f, 99 | 0.5f, -0.5f, -0.5f, 100 | 0.5f, -0.5f, 0.5f, 101 | -0.5f, -0.5f, 0.5f 102 | }; 103 | std::array topFace = { 104 | -0.5f, 0.5f, -0.5f, 105 | 0.5f, 0.5f, -0.5f, 106 | 0.5f, 0.5f, 0.5f, 107 | -0.5f, 0.5f, 0.5f 108 | }; 109 | std::array xFace1 = { 110 | -0.5f, -0.5f, -0.5f, 111 | 0.5f, -0.5f, 0.5f, 112 | 0.5f, 0.5f, 0.5f, 113 | -0.5f, 0.5f, -0.5f 114 | }; 115 | std::array xFace2 = { 116 | -0.5f, -0.5f, 0.5f, 117 | 0.5f, -0.5f, -0.5f, 118 | 0.5f, 0.5f, -0.5f, 119 | -0.5f, 0.5f, 0.5f 120 | }; 121 | std::array xFace3 = { 122 | 0.0f, -0.5f, -0.5f, 123 | 0.0f, -0.5f, 0.5f, 124 | 0.0f, 0.5f, 0.5f, 125 | 0.0f, 0.5f, -0.5f 126 | }; 127 | std::array xFace4 = { 128 | -0.5f, -0.5f, 0.0f, 129 | 0.5f, -0.5f, 0.0f, 130 | 0.5f, 0.5f, 0.0f, 131 | -0.5f, 0.5f, 0.0f 132 | }; 133 | 134 | float LIGHT_TOP = 1.0f; 135 | float LIGHT_X = 0.8f; 136 | float LIGHT_Z = 0.6f; 137 | float LIGHT_BOTTOM = 0.4f; 138 | 139 | //@TODO : this is temporary, improve selection blocks 140 | if(block.IsFocus()){ 141 | LIGHT_TOP = 1.2f; 142 | LIGHT_X = 1.2f; 143 | LIGHT_Z = 1.2f; 144 | LIGHT_BOTTOM = 1.2f; 145 | } 146 | 147 | glm::vec3 position = {x, y, z}; 148 | BlockTex texCoords = block.GetProps().m_TexCoords; 149 | 150 | if(block.GetProps().m_MeshType == BlockMeshType::X){ 151 | m_Meshes.m_Solid.AddFace(xFace1, texCoords.top, position, LIGHT_X); 152 | m_Meshes.m_Solid.AddFace(xFace2, texCoords.top, position, LIGHT_X); 153 | return; 154 | } 155 | 156 | if(block.GetProps().m_MeshType == BlockMeshType::Star){ 157 | m_Meshes.m_Solid.AddFace(xFace1, texCoords.top, position, LIGHT_X); 158 | m_Meshes.m_Solid.AddFace(xFace2, texCoords.top, position, LIGHT_X); 159 | m_Meshes.m_Solid.AddFace(xFace3, texCoords.top, position, LIGHT_X); 160 | m_Meshes.m_Solid.AddFace(xFace4, texCoords.top, position, LIGHT_X); 161 | return; 162 | } 163 | 164 | TryAddFace(frontFace, texCoords.front, position, {x, y, z-1}, LIGHT_Z); 165 | TryAddFace(backFace, texCoords.back, position, {x, y, z+1}, LIGHT_Z); 166 | TryAddFace(leftFace, texCoords.left, position, {x-1, y, z}, LIGHT_X); 167 | TryAddFace(rightFace, texCoords.right, position, {x+1, y, z}, LIGHT_X); 168 | if(m_Position.y != 0 || y != 0) 169 | TryAddFace(bottomFace, texCoords.bottom, position, {x, y-1, z}, LIGHT_BOTTOM); 170 | TryAddFace(topFace, texCoords.top, position, {x, y+1, z}, LIGHT_TOP); 171 | 172 | } 173 | 174 | void Chunk::UpdateVBO(){ 175 | if(m_hasBuffer) return; 176 | m_Meshes.m_Solid.UpdateVBO(); 177 | m_Meshes.m_Water.UpdateVBO(); 178 | m_Meshes.m_Cloud.UpdateVBO(); 179 | m_hasBuffer = true; 180 | } 181 | 182 | bool Chunk::HasMesh(){ 183 | return m_hasMesh; 184 | } 185 | 186 | bool Chunk::HasBuffer(){ 187 | return m_hasBuffer; 188 | } 189 | 190 | Block Chunk::GetBlock(int x, int y, int z) const{ 191 | if(OutOfBounds(x, y, z)){ 192 | glm::vec3 position = ToWorldPosition(x, y, z); 193 | Block block = m_World->GetBlock(position.x, position.y, position.z); 194 | return block; 195 | }else{ 196 | return m_Blocks[GetBlockIndex(x,y,z)]; 197 | } 198 | } 199 | 200 | Block Chunk::GetChunkBlock(int x, int y, int z) const{ 201 | if(OutOfBounds(x, y, z)){ 202 | return Block(BlockType::Air); 203 | }else{ 204 | return m_Blocks[GetBlockIndex(x,y,z)]; 205 | } 206 | } 207 | 208 | glm::vec3 Chunk::ToWorldPosition(int x, int y, int z) const{ 209 | return { 210 | m_Position.x + x, 211 | m_Position.y + y, 212 | m_Position.z + z 213 | }; 214 | } 215 | 216 | bool Chunk::OutOfBounds(int x, int y, int z) const{ 217 | return OutOfBounds(x) || OutOfBounds(y) || OutOfBounds(z); 218 | } 219 | 220 | bool Chunk::OutOfBounds(int value) const{ 221 | return value < 0 || value >= CHUNK_SIZE; 222 | } 223 | 224 | void Chunk::SetBlock(int x, int y, int z, BlockType type, bool focus){ 225 | if(OutOfBounds(x) || OutOfBounds(y) || OutOfBounds(z)){ 226 | return; 227 | } 228 | Block& b = m_Blocks[GetBlockIndex(x,y,z)]; 229 | b.SetBlockType(type); 230 | b.SetFocus(focus); 231 | } 232 | 233 | int Chunk::GetBlockIndex(int x, int y, int z) const{ 234 | return y * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + x; 235 | } 236 | 237 | void Chunk::DeleteMeshes(){ 238 | m_hasMesh = false; 239 | m_Meshes.m_Solid.DeleteMeshes(); 240 | } 241 | 242 | MeshCollection& Chunk::GetMeshes(){ 243 | return m_Meshes; 244 | } -------------------------------------------------------------------------------- /src/world/world.cc: -------------------------------------------------------------------------------- 1 | #include "world.h" 2 | 3 | World* World::m_Instance = nullptr; 4 | 5 | World* World::GetInstance(Camera &camera){ 6 | if(World::m_Instance == nullptr){ 7 | World::m_Instance = new World(camera); 8 | } 9 | return World::m_Instance; 10 | } 11 | 12 | void World::Render(Renderer& renderer, Camera& camera){ 13 | pthread_mutex_lock(&m_Lock); 14 | ChunkMap &chunks = m_ChunkManager.GetChunks(); 15 | //LogTrace("Rendering chunks (%lu)...\n", chunks.size()); 16 | for(auto it = chunks.begin(); it != chunks.end();){ 17 | SuperChunk& chunk = it->second; 18 | int cameraX = camera.m_Position.x; 19 | int cameraZ = camera.m_Position.z; 20 | 21 | int minX = cameraX - m_RenderDistance * CHUNK_SIZE; 22 | int maxX = cameraX + m_RenderDistance * CHUNK_SIZE; 23 | int minZ = cameraZ - m_RenderDistance * CHUNK_SIZE; 24 | int maxZ = cameraZ + m_RenderDistance * CHUNK_SIZE; 25 | 26 | auto position = chunk.m_Position; 27 | 28 | if(minX > position.x || maxX < position.x || minZ > position.z || maxZ < position.z){ 29 | it = chunks.erase(it); 30 | //it++; 31 | continue; 32 | }else{ 33 | chunk.Draw(renderer, camera); 34 | it++; 35 | } 36 | } 37 | pthread_mutex_unlock(&m_Lock); 38 | //LogTrace("Finish Rendering chunks...\n"); 39 | } 40 | 41 | void World::SetSpawnPoint(){ 42 | int tries = 0; 43 | int chunkX = -1; 44 | int chunkZ = -1; 45 | int blockX = 0; 46 | int blockY = 0; 47 | int blockZ = 0; 48 | 49 | LogTrace("Searching spawn point...\n"); 50 | 51 | while(blockY <= WATER_LEVEL){ 52 | m_ChunkManager.UnLoadChunk(chunkX, chunkZ); 53 | chunkX = Random::Get().GetIntInRange(200, 1000) * CHUNK_SIZE; 54 | chunkZ = Random::Get().GetIntInRange(200, 1000) * CHUNK_SIZE; 55 | blockX = Random::Get().GetIntInRange(0, 15); 56 | blockZ = Random::Get().GetIntInRange(0, 15); 57 | 58 | m_ChunkManager.LoadMesh(chunkX, chunkZ); 59 | 60 | blockY = m_ChunkManager.GetChunk(chunkX, chunkZ).GetTopBlockAt(blockX, blockZ); 61 | tries++; 62 | } 63 | 64 | int worldX = chunkX + blockX; 65 | int worldZ = chunkZ + blockZ; 66 | 67 | m_Player.m_Position = {worldX, blockY + 2, worldZ}; 68 | LogTrace("Spawn point founded at (%d, %d, %d) in %d tries...\n", worldX, blockY, worldZ, tries); 69 | } 70 | 71 | void World::SetBlock(int x, int y, int z, BlockType type, bool focus){ 72 | if(y >= 0){ 73 | Vector2i blockPosition = GetBlockXZ(x, z); 74 | Vector2i chunkPosition = GetChunkXZ(x, z); 75 | m_ChunkManager.GetChunk(chunkPosition.x * CHUNK_SIZE, chunkPosition.z * CHUNK_SIZE).SetBlock(blockPosition.x, y, blockPosition.z, type, focus); 76 | } 77 | } 78 | 79 | void World::FocusBlock(int x, int y, int z, BlockType type){ 80 | UnFocusBlock(); 81 | if(y >= 0){ 82 | SetBlock(x, y, z, type, true); 83 | m_FocusBlock = Vector3i(x, y, z); 84 | } 85 | } 86 | 87 | void World::UnFocusBlock(){ 88 | if(m_FocusBlock == Vector3i(0,0,0)) return; 89 | Block focusBlock = GetBlock(m_FocusBlock.x, m_FocusBlock.y, m_FocusBlock.z); 90 | SetBlock(m_FocusBlock.x, m_FocusBlock.y, m_FocusBlock.z, focusBlock.GetType(), false); 91 | UpdateChunk(m_FocusBlock.x, m_FocusBlock.y, m_FocusBlock.z); 92 | m_FocusBlock = Vector3i(0,0,0); 93 | } 94 | 95 | void World::Update(Camera& camera){ 96 | UpdateChunks(); 97 | UpdatePlayer(); 98 | UpdateFocusBlock(camera); 99 | } 100 | 101 | void World::UpdatePlayer(){ 102 | glm::vec3 position = m_Player.m_Position; 103 | Block block = GetBlock(position.x, position.y + 0.5f, position.z); 104 | if(block.GetType() == BlockType::Water){ 105 | m_Player.SetUnderWater(true); 106 | }else{ 107 | m_Player.SetUnderWater(false); 108 | } 109 | } 110 | 111 | void World::UpdateChunk(int blockX, int blockY, int blockZ){ 112 | pthread_mutex_lock(&m_Lock); 113 | Vector2i chunkPosition = GetChunkXZ(blockX, blockZ); 114 | int chunkY = blockY / CHUNK_SIZE; 115 | Vector3i key(chunkPosition.x * CHUNK_SIZE, chunkY, chunkPosition.z * CHUNK_SIZE); 116 | m_UpdateChunks.emplace(key, m_ChunkManager.GetChunk(key.x, key.z).GetChunk(key.y)); 117 | 118 | Vector2i chunkBlockPosition = GetBlockXZ(blockX, blockZ); 119 | int chunkBlockY = blockY % CHUNK_SIZE; 120 | 121 | if(chunkBlockPosition.x == 0){ 122 | Vector3i newKey((chunkPosition.x - 1) * CHUNK_SIZE, chunkY, chunkPosition.z * CHUNK_SIZE); 123 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(newKey.y)); 124 | } 125 | 126 | if(chunkBlockPosition.x == CHUNK_SIZE - 1){ 127 | Vector3i newKey((chunkPosition.x + 1) * CHUNK_SIZE, chunkY, chunkPosition.z * CHUNK_SIZE); 128 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(chunkY)); 129 | } 130 | 131 | if(chunkBlockPosition.z == 0){ 132 | Vector3i newKey(chunkPosition.x * CHUNK_SIZE, chunkY, (chunkPosition.z - 1) * CHUNK_SIZE); 133 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(newKey.y)); 134 | } 135 | 136 | if(chunkBlockPosition.z == CHUNK_SIZE - 1){ 137 | Vector3i newKey(chunkPosition.x * CHUNK_SIZE, chunkY, (chunkPosition.z + 1) * CHUNK_SIZE); 138 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(chunkY)); 139 | } 140 | 141 | if(chunkBlockY == 0){ 142 | Vector3i newKey(chunkPosition.x* CHUNK_SIZE, chunkY - 1, chunkPosition.z * CHUNK_SIZE); 143 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(newKey.y)); 144 | } 145 | 146 | if(chunkBlockY == CHUNK_SIZE - 1){ 147 | Vector3i newKey(chunkPosition.x * CHUNK_SIZE, chunkY + 1, chunkPosition.z * CHUNK_SIZE); 148 | m_UpdateChunks.emplace(newKey, m_ChunkManager.GetChunk(newKey.x, newKey.z).GetChunk(chunkY)); 149 | } 150 | 151 | pthread_mutex_unlock(&m_Lock); 152 | } 153 | 154 | void World::UpdateChunks(){ 155 | pthread_mutex_lock(&m_Lock); 156 | for(auto& updateChunk : m_UpdateChunks){ 157 | Chunk& chunk = updateChunk.second; 158 | chunk.MakeMesh(); 159 | } 160 | m_UpdateChunks.clear(); 161 | pthread_mutex_unlock(&m_Lock); 162 | } 163 | 164 | Block World::GetBlock(int x, int y, int z){ 165 | Vector2i blockPosition = GetBlockXZ(x, z); 166 | Vector2i chunkPosition = GetChunkXZ(x, z); 167 | Block block = m_ChunkManager.GetChunk(chunkPosition.x * CHUNK_SIZE, chunkPosition.z * CHUNK_SIZE).GetBlock(blockPosition.x, y, blockPosition.z); 168 | return block; 169 | } 170 | 171 | SuperChunk& World::GetChunkByBlock(int x, int y, int z){ 172 | Vector2i chunkPosition = GetChunkXZ(x, z); 173 | return m_ChunkManager.GetChunk(chunkPosition.x * CHUNK_SIZE, chunkPosition.z * CHUNK_SIZE); 174 | } 175 | 176 | Vector2i World::GetBlockXZ(int x, int z){ 177 | return { 178 | x % CHUNK_SIZE, 179 | z % CHUNK_SIZE 180 | }; 181 | } 182 | 183 | Vector2i World::GetChunkXZ(int x, int z){ 184 | return { 185 | x / CHUNK_SIZE, 186 | z / CHUNK_SIZE 187 | }; 188 | } 189 | 190 | 191 | Vector3i World::GetProjPoint(Camera& camera){ 192 | glm::vec3 rayStartPosition = camera.m_Position + glm::vec3(0.5f, 0.0f, 0.5f); 193 | glm::vec3 rayEndPosition = rayStartPosition; 194 | glm::vec3 ray = camera.GetRay(); 195 | float maxDistance = 2.0f; 196 | float step = 0.05f; 197 | float cStep = step; 198 | while(glm::distance(rayStartPosition, rayEndPosition) < maxDistance){ 199 | rayEndPosition = rayStartPosition + ray * cStep; 200 | int x = rayEndPosition.x; 201 | int y = rayEndPosition.y + 0.5f; 202 | int z = rayEndPosition.z; 203 | 204 | Block block = GetBlock(x, y, z); 205 | BlockType blockType = block.GetType(); 206 | if(blockType != BlockType::Air && blockType != BlockType::Water){ 207 | return Vector3i(x, y, z); 208 | } 209 | cStep += step; 210 | } 211 | return Vector3i(0,0,0); 212 | } 213 | 214 | void World::Mine(Camera& camera){ 215 | Vector3i point = GetProjPoint(camera); 216 | if(point == Vector3i(0,0,0)) return; 217 | UpdateChunk(point.x, point.y, point.z); 218 | SetBlock(point.x, point.y, point.z, BlockType::Air); 219 | } 220 | 221 | void World::UpdateFocusBlock(Camera& camera){ 222 | Vector3i point = GetProjPoint(camera); 223 | UnFocusBlock(); 224 | if(point == Vector3i(0,0,0)) return; 225 | BlockType blockType = GetBlock(point.x, point.y, point.z).GetType(); 226 | UpdateChunk(point.x, point.y, point.z); 227 | FocusBlock(point.x, point.y, point.z, blockType); 228 | } 229 | 230 | void World::LoadChunks(Camera& camera){ 231 | while(m_Running){ 232 | int cameraX = camera.m_Position.x/CHUNK_SIZE; 233 | int cameraZ = camera.m_Position.z/CHUNK_SIZE; 234 | //LogTrace("Load Chunks (%d, %d, %d)...\n", cameraX, cameraZ, m_LoadDistance); 235 | bool isMeshMade = false; 236 | for(int i=0; i < m_LoadDistance; i++){ 237 | int minX = std::max(cameraX - i, 0); 238 | int minZ = std::max(cameraZ - i, 0); 239 | int maxX = cameraX + i; 240 | int maxZ = cameraZ + i; 241 | for(int x = minX; x= m_RenderDistance){ 259 | m_LoadDistance = 2; 260 | } 261 | //LogTrace("Finish Load Chunks (%d, %d)...\n", cameraX, cameraZ); 262 | } 263 | } 264 | 265 | namespace{ 266 | struct ThreadData{ 267 | World* world; 268 | Camera& camera; 269 | ThreadData(World* _world, Camera& _camera): world(_world), camera(_camera){} 270 | }; 271 | 272 | void* LoadChunkThread(void *data){ 273 | ThreadData* dataThread = reinterpret_cast(data); 274 | dataThread->world->LoadChunks(dataThread->camera); 275 | } 276 | }; 277 | 278 | World::World(Camera& camera): m_RenderDistance(12), m_ChunkManager(this), m_FocusBlock(0,0,0){ 279 | m_Running = true; 280 | SetSpawnPoint(); 281 | camera.UpdateGeoInfo(m_Player); 282 | 283 | ThreadData* data = new ThreadData(this, camera); 284 | usleep(50); 285 | if(pthread_mutex_init(&m_Lock, NULL) != 0){ 286 | printf("Mutex init failed !\n"); 287 | exit(EXIT_FAILURE); 288 | } 289 | pthread_create(&m_LoadChunksThread, NULL, LoadChunkThread, data); 290 | } 291 | 292 | World::~World(){ 293 | m_Running = false; 294 | pthread_join(m_LoadChunksThread, NULL); 295 | pthread_mutex_destroy(&m_Lock); 296 | } --------------------------------------------------------------------------------