moved some stuff around, ready for dynamic chunk loading and that

This commit is contained in:
Ben
2019-10-21 18:26:10 +01:00
parent e13288a721
commit efafd4e71e
12 changed files with 66 additions and 41 deletions

170
src/world/chunk/chunk.cpp Normal file
View File

@@ -0,0 +1,170 @@
#include "chunk.hpp"
#include "../../renderer/shader.hpp"
#include "../../renderer/camera.hpp"
#include "voxel.hpp"
#include "../block.hpp"
#include <random>
static std::default_random_engine generator;
Chunk::Chunk(int x, int z) {
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
// [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)
Voxels.push_back((uint8_t)EBlockType::Stone);
else if (y < 32)
Voxels.push_back((uint8_t)EBlockType::Dirt);
else
Voxels.push_back((uint8_t)EBlockType::Grass);
}
m_mesh();
}
Chunk::Chunk(int x, int z, std::vector<uint8_t> voxels) {
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
Voxels = voxels;
m_mesh();
}
void Chunk::Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader) {
shader->Use();
glBindVertexArray(m_vao);
GLint uniTrans = glGetUniformLocation(shader->Program, "model");
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(m_model));
GLint uniView = glGetUniformLocation(shader->Program, "view");
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(camera->GetViewMatrix()));
GLint uniProj = glGetUniformLocation(shader->Program, "proj");
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(camera->GetProjectionMatrix()));
glDrawArrays(GL_TRIANGLES, 0, m_numVerts);
}
void Chunk::Update() {
m_mesh();
}
uint8_t Chunk::BlockAt(int x, int y, int z) {
if (x > CHUNK_WIDTH - 1) return 0;
if (y > CHUNK_HEIGHT - 1) return 0;
if (z > CHUNK_DEPTH - 1) return 0;
if (x < 0) return 0;
if (y < 0) return 0;
if (z < 0) return 0;
return Voxels[x + CHUNK_WIDTH * (y + CHUNK_HEIGHT * z)];
}
void Chunk::m_mesh() {
// TODO: Use greedy meshing for MAXIMUM performance
for (int x = 0; x < CHUNK_WIDTH; x++)
for (int y = 0; y < CHUNK_HEIGHT; y++)
for (int z = 0; z < CHUNK_DEPTH; z++) {
std::vector<glm::vec3> tempVerts;
std::vector<glm::vec3> tempUVs;
uint8_t block = BlockAt(x, y, z);
if (block == EBlockType::Air) continue;
Voxel tmp({x, y, z}, block);
if (BlockAt(x + 1, y, z) == EBlockType::Air)
tmp.AddFace(EFaceType::Right);
if (BlockAt(x - 1, y, z) == EBlockType::Air)
tmp.AddFace(EFaceType::Left);
if (BlockAt(x, y + 1, z) == EBlockType::Air)
tmp.AddFace(EFaceType::Top);
if (BlockAt(x, y - 1, z) == EBlockType::Air)
tmp.AddFace(EFaceType::Bottom);
if (BlockAt(x, y, z + 1) == EBlockType::Air)
tmp.AddFace(EFaceType::Front);
if (BlockAt(x, y, z - 1) == EBlockType::Air)
tmp.AddFace(EFaceType::Back);
tmp.GetMesh(tempVerts, tempUVs);
m_vertices.insert(m_vertices.end(), tempVerts.begin(), tempVerts.end());
m_uvs.insert(m_uvs.end(), tempUVs.begin(), tempUVs.end());
tmp.Clear();
}
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);
}

53
src/world/chunk/chunk.hpp Normal file
View File

@@ -0,0 +1,53 @@
#ifndef MINECRAFT_RENDERER_CHUNK_H_
#define MINECRAFT_RENDERER_CHUNK_H_
#include "../../common.hpp"
#define CHUNK_HEIGHT 128
#define CHUNK_WIDTH 16
#define CHUNK_DEPTH 16
class Camera;
class Shader;
class Voxel;
class Chunk {
public:
Chunk(int x, int z);
Chunk(int x, int z, std::vector<uint8_t> voxels);
void Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader);
void Update();
//bool Loaded = false;
//bool Render = false;
uint8_t BlockAt(int x, int y, int z);
// Indexed sequentially [x + WIDTH * (y + HEIGHT * z)] = voxelID
// the voxel id is used to index the block dictionary to get properties
// to generate a mesh and send it to the GPU
std::vector<uint8_t> Voxels;
private:
void m_mesh();
GLuint m_vao = 0;
GLuint m_vbo = 0;
// Must be translated by a multiple of 16 in the x or z, nothing in y
glm::mat4 m_model;
std::vector<glm::vec3> m_vertices;
int m_numVerts = 0;
std::vector<glm::vec3> m_uvs;
};
#endif

127
src/world/chunk/face.hpp Normal file
View File

@@ -0,0 +1,127 @@
#ifndef MINECRAFT_RENDERER_FACE_H_
#define MINECRAFT_RENDERER_FACE_H_
#include "../../common.hpp"
namespace EFaceType {
enum Face : uint8_t {
Top,
Bottom,
Left,
Right,
Front,
Back,
};
}
static std::vector<glm::vec3> CubeTopFace = {
{ -0.5f, 0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, -0.5f }
};
static std::vector<glm::vec2> CubeTopFaceUVs = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }
};
static std::vector<glm::vec3> CubeBottomFace = {
{ -0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
{ -0.5f, -0.5f, 0.5f },
{ -0.5f, -0.5f, -0.5f }
};
static std::vector<glm::vec2> CubeBottomFaceUVs = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }
};
static std::vector<glm::vec3> CubeLeftFace = {
{ -0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
{ -0.5f, -0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f }
};
static std::vector<glm::vec2> CubeLeftFaceUVs = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }
};
static std::vector<glm::vec3> CubeRightFace = {
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
};
static std::vector<glm::vec2> CubeRightFaceUVs = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }
};
static std::vector<glm::vec3> CubeFrontFace = {
{ -0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
{ -0.5f, -0.5f, 0.5f }
};
static std::vector<glm::vec2> CubeFrontFaceUVs = {
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f },
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f }
};
static std::vector<glm::vec3> CubeBackFace = {
{ -0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ -0.5f, 0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f }
};
static std::vector<glm::vec2> CubeBackFaceUVs = {
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f },
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f }
};
#endif

132
src/world/chunk/voxel.cpp Normal file
View File

@@ -0,0 +1,132 @@
#include "voxel.hpp"
#include <iostream>
#include <memory>
#include "../../renderer/shader.hpp"
#include "../../renderer/camera.hpp"
#include "face.hpp"
#include "../block.hpp"
Voxel::Voxel(glm::vec3 coordsInChunk, uint8_t block) {
// Texture winding order - top, bottom, left, right, front, back
Block = block;
m_coordsInChunk = coordsInChunk;
}
void Voxel::AddFace(EFaceType::Face face) {
std::vector<glm::vec3> verts;
std::vector<glm::vec2> uvs;
switch (face) {
case EFaceType::Top:
{
verts = CubeTopFace;
uvs = CubeTopFaceUVs;
break;
}
case EFaceType::Bottom:
{
verts = CubeBottomFace;
uvs = CubeBottomFaceUVs;
break;
}
case EFaceType::Left:
{
verts = CubeLeftFace;
uvs = CubeLeftFaceUVs;
break;
}
case EFaceType::Right:
{
verts = CubeRightFace;
uvs = CubeRightFaceUVs;
break;
}
case EFaceType::Front:
{
verts = CubeFrontFace;
uvs = CubeFrontFaceUVs;
break;
}
case EFaceType::Back:
{
verts = CubeBackFace;
uvs = CubeBackFaceUVs;
break;
}
}
verts = m_translateIntoChunk(verts, m_coordsInChunk);
m_vertices.insert(m_vertices.end(), verts.begin(), verts.end());
std::shared_ptr<CBlockEntry> block = CBlockDictionary::GetInstance()->BlockEntries[Block];
uint16_t tex = block->FaceTextures[(uint16_t)face];
std::vector<glm::vec3> uvws = {
{ uvs[0].x, uvs[0].y, (float)tex },
{ uvs[1].x, uvs[1].y, (float)tex },
{ uvs[2].x, uvs[2].y, (float)tex },
{ uvs[3].x, uvs[3].y, (float)tex },
{ uvs[4].x, uvs[4].y, (float)tex },
{ uvs[5].x, uvs[5].y, (float)tex },
};
m_uvs.insert(m_uvs.end(), uvws.begin(), uvws.end());
}
void Voxel::GetMesh(std::vector<glm::vec3>& verts, std::vector<glm::vec3>& uvs) {
verts = m_vertices;
uvs = m_uvs;
}
void Voxel::Clear() {
m_vertices.clear();
m_uvs.clear();
}
std::vector<glm::vec3> Voxel::m_translateIntoChunk(std::vector<glm::vec3> verts, glm::vec3 trans) {
for (int i = 0; i < verts.size(); i++) {
verts[i].x += trans.x;
verts[i].y += trans.y;
verts[i].z += trans.z;
}
return verts;
}

33
src/world/chunk/voxel.hpp Normal file
View File

@@ -0,0 +1,33 @@
#ifndef MINECRAFT_RENDERER_VOXEL_H_
#define MINECRAFT_RENDERER_VOXEL_H_
#include "../../common.hpp"
#include "face.hpp"
class Camera;
class Shader;
class Voxel {
public:
Voxel(glm::vec3 coordsInChunk, uint8_t block);
void AddFace(EFaceType::Face face);
void GetMesh(std::vector<glm::vec3>& verts, std::vector<glm::vec3>& uvs);
void Clear();
uint8_t Block;
private:
glm::vec3 m_coordsInChunk;
std::vector<glm::vec3> m_translateIntoChunk(std::vector<glm::vec3> verts, glm::vec3 trans);
std::vector<glm::vec3> m_vertices;
std::vector<glm::vec3> m_uvs;
};
#endif