moved some stuff around, ready for dynamic chunk loading and that
This commit is contained in:
170
src/world/chunk/chunk.cpp
Normal file
170
src/world/chunk/chunk.cpp
Normal 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
53
src/world/chunk/chunk.hpp
Normal 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
127
src/world/chunk/face.hpp
Normal 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
132
src/world/chunk/voxel.cpp
Normal 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
33
src/world/chunk/voxel.hpp
Normal 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
|
||||
Reference in New Issue
Block a user