Merge pull request #7 from plane000/dev

Merge update #1 for version sub alpha
This commit is contained in:
Benjamin Kyd
2019-11-05 14:26:25 +00:00
committed by GitHub
14 changed files with 2937 additions and 73 deletions

View File

@@ -2,17 +2,19 @@
A Minecraft clone written in C++ with OpenGL
![](https://imgur.com/fUf4U4R.png)
![](https://i.imgur.com/UBiisxS.jpg)
### Development Checklist
### Trello coming soon
- [X] Block atlas
- [X] Texturing faces
- [X] Mesh chunks
- [X] Fog
- [ ] Fustrum culling
- [ ] Chunk generation around the player
- [ ] Threaded chunk generation
- [X] Threaded chunk generation
- [ ] Player collision
- [ ] Player cursor
- [ ] Procedural world generation

View File

@@ -17,8 +17,11 @@ void main() {
if (outColour.w == .0)
discard;
float fogMax = 20000;
float fogMax = 60000;
outColour = vec4(mix(outColour.xyz, SkyColour, min(1.0f, Distance / fogMax)), outColour.w);
vec3 colour = mix(outColour.xyz, SkyColour, min(1.0f, Distance / fogMax));
// Retain fragment transparency
outColour = vec4(colour, outColour.w);
}

View File

@@ -1,9 +1,10 @@
#ifndef MINECRAFT_COMMON_H_
#define MINECRAFT_COMMON_H_
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/hash.hpp>
#include <glm/glm.hpp>
#include <glad/glad.h>
#include <KHR/khrplatform.h>

View File

@@ -1,5 +1,8 @@
#include "game.hpp"
// For glm::vec2 as the key of a hashmap
#define GLM_ENABLE_EXPERIMENTAL
#define LOGGER_DEFINITION
#include <logger.h>
@@ -81,6 +84,8 @@ void Game::Setup(int w, int h) {
m_cameras["Default"] = std::make_shared<Camera>(w, h);
m_activeCamera = m_cameras["Default"];
m_activeCamera->Position = { 0, 70, 0 };
m_activeCamera->UpdateView();
std::shared_ptr<CBlockDictionary> BlockDictionary = CBlockDictionary::GetInstance();
@@ -92,10 +97,6 @@ void Game::Setup(int w, int h) {
m_world->SetTextureMap(texture.LoadTextures(BlockDictionary->Textures));
m_world->LoadWorld();
m_world->Shaders["Basic"] = std::make_shared<Shader>();
m_world->Shaders["Basic"]->Load(GameConfig.ResourceBase + "shaders/simple");
m_world->Shaders["Basic"]->Link();
}

View File

@@ -11,12 +11,6 @@ Renderer::Renderer() {
// Perform the render passes
void Renderer::Render(std::shared_ptr<World> world, std::shared_ptr<Camera> camera) {
glBindTexture(GL_TEXTURE_2D_ARRAY, world->TextureID);
for (int i = 0; i < world->Chunks.size(); i++) {
world->Chunks[i]->Render(camera, world->Shaders["Basic"]);
}
world->Render(camera);
}

2250
src/util/fastnoise.cpp Normal file

File diff suppressed because it is too large Load Diff

311
src/util/fastnoise.hpp Normal file
View File

@@ -0,0 +1,311 @@
// FastNoise.h
//
// MIT License
//
// Copyright(c) 2017 Jordan Peck
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// The developer's email is jorzixdan.me2@gzixmail.com (for great email, take
// off every 'zix'.)
//
// VERSION: 0.4.1
#ifndef FASTNOISE_H
#define FASTNOISE_H
// Uncomment the line below to use doubles throughout FastNoise instead of floats
//#define FN_USE_DOUBLES
#define FN_CELLULAR_INDEX_MAX 3
#ifdef FN_USE_DOUBLES
typedef double FN_DECIMAL;
#else
typedef float FN_DECIMAL;
#endif
class FastNoise
{
public:
explicit FastNoise(int seed = 1337) { SetSeed(seed); CalculateFractalBounding(); }
enum NoiseType { Value, ValueFractal, Perlin, PerlinFractal, Simplex, SimplexFractal, Cellular, WhiteNoise, Cubic, CubicFractal };
enum Interp { Linear, Hermite, Quintic };
enum FractalType { FBM, Billow, RigidMulti };
enum CellularDistanceFunction { Euclidean, Manhattan, Natural };
enum CellularReturnType { CellValue, NoiseLookup, Distance, Distance2, Distance2Add, Distance2Sub, Distance2Mul, Distance2Div };
// Sets seed used for all noise types
// Default: 1337
void SetSeed(int seed);
// Returns seed used for all noise types
int GetSeed() const { return m_seed; }
// Sets frequency for all noise types
// Default: 0.01
void SetFrequency(FN_DECIMAL frequency) { m_frequency = frequency; }
// Returns frequency used for all noise types
FN_DECIMAL GetFrequency() const { return m_frequency; }
// Changes the interpolation method used to smooth between noise values
// Possible interpolation methods (lowest to highest quality) :
// - Linear
// - Hermite
// - Quintic
// Used in Value, Perlin Noise and Position Warping
// Default: Quintic
void SetInterp(Interp interp) { m_interp = interp; }
// Returns interpolation method used for supported noise types
Interp GetInterp() const { return m_interp; }
// Sets noise return type of GetNoise(...)
// Default: Simplex
void SetNoiseType(NoiseType noiseType) { m_noiseType = noiseType; }
// Returns the noise type used by GetNoise
NoiseType GetNoiseType() const { return m_noiseType; }
// Sets octave count for all fractal noise types
// Default: 3
void SetFractalOctaves(int octaves) { m_octaves = octaves; CalculateFractalBounding(); }
// Returns octave count for all fractal noise types
int GetFractalOctaves() const { return m_octaves; }
// Sets octave lacunarity for all fractal noise types
// Default: 2.0
void SetFractalLacunarity(FN_DECIMAL lacunarity) { m_lacunarity = lacunarity; }
// Returns octave lacunarity for all fractal noise types
FN_DECIMAL GetFractalLacunarity() const { return m_lacunarity; }
// Sets octave gain for all fractal noise types
// Default: 0.5
void SetFractalGain(FN_DECIMAL gain) { m_gain = gain; CalculateFractalBounding(); }
// Returns octave gain for all fractal noise types
FN_DECIMAL GetFractalGain() const { return m_gain; }
// Sets method for combining octaves in all fractal noise types
// Default: FBM
void SetFractalType(FractalType fractalType) { m_fractalType = fractalType; }
// Returns method for combining octaves in all fractal noise types
FractalType GetFractalType() const { return m_fractalType; }
// Sets distance function used in cellular noise calculations
// Default: Euclidean
void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { m_cellularDistanceFunction = cellularDistanceFunction; }
// Returns the distance function used in cellular noise calculations
CellularDistanceFunction GetCellularDistanceFunction() const { return m_cellularDistanceFunction; }
// Sets return type from cellular noise calculations
// Note: NoiseLookup requires another FastNoise object be set with SetCellularNoiseLookup() to function
// Default: CellValue
void SetCellularReturnType(CellularReturnType cellularReturnType) { m_cellularReturnType = cellularReturnType; }
// Returns the return type from cellular noise calculations
CellularReturnType GetCellularReturnType() const { return m_cellularReturnType; }
// Noise used to calculate a cell value if cellular return type is NoiseLookup
// The lookup value is acquired through GetNoise() so ensure you SetNoiseType() on the noise lookup, value, Perlin or simplex is recommended
void SetCellularNoiseLookup(FastNoise* noise) { m_cellularNoiseLookup = noise; }
// Returns the noise used to calculate a cell value if the cellular return type is NoiseLookup
FastNoise* GetCellularNoiseLookup() const { return m_cellularNoiseLookup; }
// Sets the 2 distance indices used for distance2 return types
// Default: 0, 1
// Note: index0 should be lower than index1
// Both indices must be >= 0, index1 must be < 4
void SetCellularDistance2Indices(int cellularDistanceIndex0, int cellularDistanceIndex1);
// Returns the 2 distance indices used for distance2 return types
void GetCellularDistance2Indices(int& cellularDistanceIndex0, int& cellularDistanceIndex1) const;
// Sets the maximum distance a cellular point can move from its grid position
// Setting this high will make artifacts more common
// Default: 0.45
void SetCellularJitter(FN_DECIMAL cellularJitter) { m_cellularJitter = cellularJitter; }
// Returns the maximum distance a cellular point can move from its grid position
FN_DECIMAL GetCellularJitter() const { return m_cellularJitter; }
// Sets the maximum warp distance from original location when using GradientPerturb{Fractal}(...)
// Default: 1.0
void SetGradientPerturbAmp(FN_DECIMAL gradientPerturbAmp) { m_gradientPerturbAmp = gradientPerturbAmp; }
// Returns the maximum warp distance from original location when using GradientPerturb{Fractal}(...)
FN_DECIMAL GetGradientPerturbAmp() const { return m_gradientPerturbAmp; }
//2D
FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetWhiteNoiseInt(int x, int y) const;
FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y) const;
void GradientPerturb(FN_DECIMAL& x, FN_DECIMAL& y) const;
void GradientPerturbFractal(FN_DECIMAL& x, FN_DECIMAL& y) const;
//3D
FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z) const;
FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
void GradientPerturb(FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z) const;
void GradientPerturbFractal(FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z) const;
//4D
FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) const;
FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) const;
FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z, int w) const;
private:
unsigned char m_perm[512];
unsigned char m_perm12[512];
int m_seed = 1337;
FN_DECIMAL m_frequency = FN_DECIMAL(0.01);
Interp m_interp = Quintic;
NoiseType m_noiseType = Simplex;
int m_octaves = 3;
FN_DECIMAL m_lacunarity = FN_DECIMAL(2);
FN_DECIMAL m_gain = FN_DECIMAL(0.5);
FractalType m_fractalType = FBM;
FN_DECIMAL m_fractalBounding;
CellularDistanceFunction m_cellularDistanceFunction = Euclidean;
CellularReturnType m_cellularReturnType = CellValue;
FastNoise* m_cellularNoiseLookup = nullptr;
int m_cellularDistanceIndex0 = 0;
int m_cellularDistanceIndex1 = 1;
FN_DECIMAL m_cellularJitter = FN_DECIMAL(0.45);
FN_DECIMAL m_gradientPerturbAmp = FN_DECIMAL(1);
void CalculateFractalBounding();
//2D
FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SinglePerlin(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleSimplexFractalBlend(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCubic(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y) const;
FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y) const;
void SingleGradientPerturb(unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y) const;
//3D
FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SinglePerlin(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCubic(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const;
void SingleGradientPerturb(unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z) const;
//4D
FN_DECIMAL SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) const;
inline unsigned char Index2D_12(unsigned char offset, int x, int y) const;
inline unsigned char Index3D_12(unsigned char offset, int x, int y, int z) const;
inline unsigned char Index4D_32(unsigned char offset, int x, int y, int z, int w) const;
inline unsigned char Index2D_256(unsigned char offset, int x, int y) const;
inline unsigned char Index3D_256(unsigned char offset, int x, int y, int z) const;
inline unsigned char Index4D_256(unsigned char offset, int x, int y, int z, int w) const;
inline FN_DECIMAL ValCoord2DFast(unsigned char offset, int x, int y) const;
inline FN_DECIMAL ValCoord3DFast(unsigned char offset, int x, int y, int z) const;
inline FN_DECIMAL GradCoord2D(unsigned char offset, int x, int y, FN_DECIMAL xd, FN_DECIMAL yd) const;
inline FN_DECIMAL GradCoord3D(unsigned char offset, int x, int y, int z, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd) const;
inline FN_DECIMAL GradCoord4D(unsigned char offset, int x, int y, int z, int w, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd) const;
};
#endif

View File

@@ -1,40 +1,138 @@
#include "chunk.hpp"
#include "voxel.hpp"
#include "../../renderer/shader.hpp"
#include "../../renderer/camera.hpp"
#include "voxel.hpp"
#include "../block.hpp"
#include "../../util/fastnoise.hpp"
#include <random>
static std::default_random_engine generator;
Chunk::Chunk() {
}
Chunk::Chunk(int x, int z) {
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
X = x, Z = z;
Load();
}
Chunk::Chunk(int x, int z, std::vector<uint8_t> voxels) {
X = x, Z = z;
Voxels = voxels;
Load();
}
Chunk::Chunk(int x, int z, std::shared_ptr<FastNoise> terrainGenerator) {
X = x, Z = z;
int y;
for (x = 0; x < CHUNK_WIDTH; x++)
for (y = 0; y < CHUNK_HEIGHT; y++)
for (z = 0; z < CHUNK_DEPTH; z++) {
if (y == 0) {
Voxels.push_back((uint8_t)EBlockType::Bedrock);
continue;
}
if (y == 1 && (float)rand() / (float)RAND_MAX > 0.5f) {
Voxels.push_back((uint8_t)EBlockType::Bedrock);
continue;
}
if (pow(y / (float)CHUNK_HEIGHT, 1.1024f) + terrainGenerator->GetValueFractal(x + (Z * CHUNK_WIDTH), y, z + (X * CHUNK_DEPTH)) * 0.60f < 0.5f) {
Voxels.push_back((uint8_t)EBlockType::Grass);
continue;
}
Voxels.push_back((uint8_t)EBlockType::Air);
}
for (x = 0; x < CHUNK_WIDTH; x++)
for (y = 0; y < CHUNK_HEIGHT; y++)
for (z = 0; z < CHUNK_DEPTH; z++) {
if (BlockAt(x, y, z) == EBlockType::Bedrock)
continue;
// No need for bounds checking as a closed loop
if (BlockAt(x, y + 1, z) == EBlockType::Grass)
Voxels[x + CHUNK_WIDTH * (y + CHUNK_HEIGHT * z)] = EBlockType::Dirt;
}
// Add stone 3 layers below dirt
for (x = 0; x < CHUNK_WIDTH; x++)
for (y = 0; y < CHUNK_HEIGHT; y++)
for (z = 0; z < CHUNK_DEPTH; z++) {
if (BlockAt(x, y, z) == EBlockType::Bedrock)
continue;
if (BlockAt(x, y + 1, z) == EBlockType::Dirt)
if (BlockAt(x, y + 2, z) == EBlockType::Dirt)
// if (BlockAt(x, y + 3, z) == EBlockType::Dirt)
Voxels[x + CHUNK_WIDTH * (y + CHUNK_HEIGHT * z)] = EBlockType::Stone;
}
// Add the rest of the stone
for (x = 0; x < CHUNK_WIDTH; x++)
for (y = 0; y < CHUNK_HEIGHT; y++)
for (z = 0; z < CHUNK_DEPTH; z++) {
if (BlockAt(x, y, z) == EBlockType::Bedrock)
continue;
if (BlockAt(x, y + 1, z) == EBlockType::Stone)
Voxels[x + CHUNK_WIDTH * (y + CHUNK_HEIGHT * z)] = EBlockType::Stone;
}
Load();
}
void Chunk::Load() {
if (Loaded)
return;
m_model = glm::translate(glm::mat4(1.0f), { X * CHUNK_WIDTH, 0, Z * CHUNK_DEPTH });
if (!Voxels.empty()) {
m_mesh();
Loaded = true;
return;
}
// Generate a superflat chunk if nothing is there
// [x + WIDTH * (y + HEIGHT * z)]
for (int x = 0; x < CHUNK_WIDTH; x++)
for (int y = 0; y < CHUNK_HEIGHT; y++)
for (int z = 0; z < CHUNK_DEPTH; z++) {
if (y > 32) {
Voxels.push_back((uint8_t)EBlockType::Air);
continue;
}
std::uniform_real_distribution<float> distribution(0, 1);
float r = distribution(generator);
if (r > 0.8f) {
Voxels.push_back((uint8_t)EBlockType::Air);
continue;
}
if (y == 0)
Voxels.push_back((uint8_t)EBlockType::Bedrock);
else if (y < 28)
@@ -47,22 +145,51 @@ Chunk::Chunk(int x, int z) {
}
m_mesh();
Loaded = true;
}
Chunk::Chunk(int x, int z, std::vector<uint8_t> voxels) {
void Chunk::UploadMesh() {
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
Voxels = voxels;
m_mesh();
if (!MeshReady)
return;
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
std::vector<glm::vec3> data;
data.insert(data.end(), m_vertices.begin(), m_vertices.end());
data.insert(data.end(), m_uvs.begin(), m_uvs.end());
m_numVerts = m_vertices.size();
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(glm::vec3), &data[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const void*)(m_vertices.size() * sizeof(glm::vec3)));
m_vertices.clear();
m_uvs.clear();
data.clear();
glBindVertexArray(0);
MeshReady = !MeshReady;
}
void Chunk::Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader) {
if (!Loaded)
return;
shader->Use();
glBindVertexArray(m_vao);
@@ -79,8 +206,9 @@ void Chunk::Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shade
}
void Chunk::Update() {
void Chunk::Update(std::vector<uint8_t> voxels) {
Voxels = voxels;
m_mesh();
}
@@ -142,29 +270,10 @@ void Chunk::m_mesh() {
}
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
std::vector<glm::vec3> data;
data.insert(data.end(), m_vertices.begin(), m_vertices.end());
data.insert(data.end(), m_uvs.begin(), m_uvs.end());
m_numVerts = m_vertices.size();
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(glm::vec3), &data[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const void*)(m_vertices.size() * sizeof(glm::vec3)));
m_vertices.clear();
m_uvs.clear();
glBindVertexArray(0);
MeshReady = true;
}
Chunk::~Chunk() {
}

View File

@@ -7,6 +7,8 @@
#define CHUNK_WIDTH 16
#define CHUNK_DEPTH 16
class FastNoise;
class Camera;
class Shader;
@@ -15,15 +17,19 @@ class Voxel;
class Chunk {
public:
Chunk();
Chunk(int x, int z);
Chunk(int x, int z, std::vector<uint8_t> voxels);
Chunk(int x, int z, std::shared_ptr<FastNoise> terrainGenerator);
void Load();
void UploadMesh();
bool MeshReady = false;
void Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader);
void Update();
//bool Loaded = false;
//bool Render = false;
void Update(std::vector<uint8_t> voxels);
uint8_t BlockAt(int x, int y, int z);
@@ -32,6 +38,16 @@ public:
// to generate a mesh and send it to the GPU
std::vector<uint8_t> Voxels;
// To only be changed by the class its self
bool Loaded = false;
// To only be changed by render components
bool ShouldRender = false;
// Chunk World pos
int X,Z;
~Chunk();
private:
void m_mesh();

View File

@@ -2,3 +2,4 @@
#define MINECRAFT_WORLD_ENTITY_H_
#endif

View File

@@ -0,0 +1,14 @@
#include "../../util/fastnoise.hpp"
void dp() {
FastNoise noise;
noise.SetSeed(121212);
noise.SetNoiseType(FastNoise::SimplexFractal);
noise.SetFractalOctaves(3);
}

View File

@@ -0,0 +1,2 @@

View File

@@ -1,22 +1,152 @@
#include "world.hpp"
#include "chunk/chunk.hpp"
#include "../renderer/shader.hpp"
#include "../config.hpp"
#include "../util/fastnoise.hpp"
World::World() {
}
void World::LoadWorld() {
m_shaders["Basic"] = std::make_shared<Shader>();
m_shaders["Basic"]->Load(GameConfig.ResourceBase + "shaders/simple");
m_shaders["Basic"]->Link();
srand(time(NULL));
m_noiseGenerator = std::make_shared<FastNoise>();
m_noiseGenerator->SetSeed(rand());
m_noiseGenerator->SetNoiseType(FastNoise::SimplexFractal);
m_noiseGenerator->SetFractalOctaves(5);
for (int x = -4; x < 10; x++)
for (int y = -4; y < 4; y++) {
m_chunkLoaderQueue.push({ x, y });
}
// Spawn generator threads
for (int i = 0; i < 7; i++) {
m_generatorThreads.push_back(std::thread([&]() {
m_loadChunks();
}));
}
m_generatorRunning = true;
}
void World::SetTextureMap(GLuint map) {
m_textureMapID = map;
}
glm::vec2 World::GetChunkCoords(glm::vec3) {
glm::vec2 World::GetChunkCoords(glm::vec3 wordCoords) {
return { wordCoords.x / CHUNK_WIDTH, wordCoords.z / CHUNK_DEPTH };
}
std::vector<std::shared_ptr<Chunk>> World::GetRenderableChunks() {
std::vector<std::shared_ptr<Chunk>> chunks;
for (auto& chunk : m_chunks) {
// Should the chunk be rendererd ?
if (chunk.second->ShouldRender) {
m_chunkMutex.lock();
if (chunk.second->MeshReady)
chunk.second->UploadMesh();
m_chunkMutex.unlock();
// If not, add it
chunks.push_back(chunk.second);
}
}
return chunks;
}
void World::Render(std::shared_ptr<Camera> camera) {
glBindTexture(GL_TEXTURE_2D_ARRAY, m_textureMapID);
std::vector<std::shared_ptr<Chunk>> chunks = GetRenderableChunks();
for (int i = 0; i < chunks.size(); i++) {
chunks[i]->Render(camera, m_shaders["Basic"]);
}
}
World::~World() {
m_generatorRunning = false;
for (int i = 0; i < m_generatorThreads.size(); i++) {
m_generatorThreads[i].join();
}
}
void World::m_loadChunks() {
while (m_generatorRunning) {
m_chunkMutex.lock();
glm::vec2 coords = m_chunkLoaderQueue.front();
m_chunkLoaderQueue.pop();
m_chunkMutex.unlock();
std::shared_ptr<Chunk> loadingChunk = std::make_shared<Chunk>(coords.x, coords.y, m_noiseGenerator);
std::cout << "Loaded chunk " << coords.x << ":" << coords.y << std::endl;
m_chunkMutex.lock();
m_chunks[coords] = loadingChunk;
m_chunks[coords]->ShouldRender = true;
m_chunkMutex.unlock();
while (m_chunkLoaderQueue.empty()) {
if (!m_generatorRunning) break;
static std::chrono::milliseconds dura(1);
std::this_thread::sleep_for(dura);
}
}
}

View File

@@ -3,42 +3,72 @@
#include "../common.hpp"
#include <unordered_map>
#include "../renderer/camera.hpp"
#include "chunk/chunk.hpp"
#include <unordered_map>
#include <thread>
#include <mutex>
#include <queue>
class FastNoise;
class Shader;
class Chunk;
class World {
public:
// Default constructor
World();
// Preps the render threads and loads all of the shaders
void LoadWorld();
void SetTextureMap(GLuint map);
// Takes world coordinates and gets a chunks coordinates
glm::vec2 GetChunkCoords(glm::vec3);
glm::vec2 GetChunkCoords(glm::vec3 wordCoords);
std::vector<std::shared_ptr<Chunk>> GetRenderableChunks();
void Render(std::shared_ptr<Camera> camera);
~World();
private:
// GL stuff
// Main texture map id
GLuint m_textureMapID;
// Shaders indexed by name
std::map<std::string, std::shared_ptr<Shader>> m_shaders;
// Threads used for chunk generation
std::vector<std::thread> m_generatorThreads;
bool m_generatorRunning = false;
// Chuks
std::vector<std::shared_ptr<Chunk>> m_renderableChunks;
// Indexed by chunk coorinates
std::unordered_map<glm::vec2, std::shared_ptr<Chunk>> m_chunks;
std::queue<glm::vec2> m_chunkUpdatesQueue;
std::queue<glm::vec2> m_chunkLoaderQueue;
std::mutex m_chunkMutex;
// Generator
std::shared_ptr<FastNoise> m_noiseGenerator;
void m_loadChunks();
};
#endif