Add files via upload

This commit is contained in:
MihailRis
2021-04-25 16:08:48 +03:00
committed by GitHub
commit e1cdcf01e9
49 changed files with 2866 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
#include "Block.h"
Block* Block::blocks[256];
Block::Block(unsigned int id, int texture) : id(id),
textureFaces{texture,texture,texture,texture,texture,texture},
emission{0,0,0}{
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef VOXELS_BLOCK_H_
#define VOXELS_BLOCK_H_
class Block {
public:
static Block* blocks[256];
const unsigned int id;
// 0 1 2 3 4 5
int textureFaces[6]; // -x,x, -y,y, -z,z
unsigned char emission[3];
unsigned char drawGroup = 0;
bool lightPassing = false;
Block(unsigned int id, int texture);
};
#endif /* VOXELS_BLOCK_H_ */
+29
View File
@@ -0,0 +1,29 @@
#include "Chunk.h"
#include "voxel.h"
#include "../lighting/Lightmap.h"
Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){
voxels = new voxel[CHUNK_VOL];
for (unsigned int i = 0; i < CHUNK_VOL; i++)
voxels[i].id = 1;
lightmap = new Lightmap();
}
Chunk::~Chunk(){
delete lightmap;
delete[] voxels;
}
bool Chunk::isEmpty(){
int id = -1;
for (int i = 0; i < CHUNK_VOL; i++){
if (voxels[i].id != id){
if (id != -1)
return false;
else
id = voxels[i].id;
}
}
return true;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef VOXELS_CHUNK_H_
#define VOXELS_CHUNK_H_
#define CHUNK_W 16
#define CHUNK_H 128
#define CHUNK_D 16
#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D)
class voxel;
class Lightmap;
class Chunk {
public:
int x,y,z;
voxel* voxels;
Lightmap* lightmap;
bool modified = true;
Chunk(int x, int y, int z);
~Chunk();
bool isEmpty();
};
#endif /* VOXELS_CHUNK_H_ */
+388
View File
@@ -0,0 +1,388 @@
#include "Chunks.h"
#include "Chunk.h"
#include "voxel.h"
#include "WorldGenerator.h"
#include "../lighting/Lightmap.h"
#include "../files/WorldFiles.h"
#include "../lighting/Lighting.h"
#include "../graphics/VoxelRenderer.h"
#include "../graphics/Mesh.h"
#include <glm/glm.hpp>
using namespace glm;
#include <math.h>
#include <limits.h>
Chunks::Chunks(int w, int h, int d, int ox, int oy, int oz) : w(w), h(h), d(d), ox(ox), oy(oy), oz(oz){
volume = w*h*d;
chunks = new Chunk*[volume];
chunksSecond = new Chunk*[volume];
meshes = new Mesh*[volume];
meshesSecond = new Mesh*[volume];
for (size_t i = 0; i < volume; i++){
chunks[i] = nullptr;
meshes[i] = nullptr;
}
}
Chunks::~Chunks(){
for (size_t i = 0; i < volume; i++){
delete chunks[i];
}
delete[] chunks;
}
bool Chunks::_buildMeshes(VoxelRenderer* renderer) {
int nearX = 0;
int nearY = 0;
int nearZ = 0;
int minDistance = 1000000000;
for (unsigned int y = 0; y < h; y++){
for (unsigned int z = 1; z < d-1; z++){
for (unsigned int x = 1; x < w-1; x++){
int index = (y * d + z) * w + x;
Chunk* chunk = chunks[index];
if (chunk == nullptr)
continue;
Mesh* mesh = meshes[index];
if (mesh != nullptr && !chunk->modified)
continue;
int lx = x - w / 2;
int ly = y - h / 2;
int lz = z - d / 2;
int distance = (lx * lx + ly * ly + lz * lz);
if (distance < minDistance){
minDistance = distance;
nearX = x;
nearY = y;
nearZ = z;
}
}
}
}
int index = (nearY * d + nearZ) * w + nearX;
Chunk* closes[27];
Chunk* chunk = chunks[index];
if (chunk == nullptr)
return false;
Mesh* mesh = meshes[index];
if (mesh == nullptr || chunk->modified){
if (mesh != nullptr)
delete mesh;
if (chunk->isEmpty()){
meshes[index] = nullptr;
return false;
}
chunk->modified = false;
for (int i = 0; i < 27; i++)
closes[i] = nullptr;
for (size_t j = 0; j < volume; j++){
Chunk* other = chunks[j];
if (other == nullptr)
continue;
int ox = other->x - chunk->x;
int oy = other->y - chunk->y;
int oz = other->z - chunk->z;
if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1)
continue;
ox += 1;
oy += 1;
oz += 1;
closes[(oy * 3 + oz) * 3 + ox] = other;
}
mesh = renderer->render(chunk, (const Chunk**)closes);
meshes[index] = mesh;
return true;
}
return false;
}
voxel* Chunks::get(int x, int y, int z){
x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D;
int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D;
if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
return nullptr;
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr)
return nullptr;
int lx = x - cx * CHUNK_W;
int ly = y - cy * CHUNK_H;
int lz = z - cz * CHUNK_D;
return &chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx];
}
unsigned char Chunks::getLight(int x, int y, int z, int channel){
x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D;
int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D;
if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
return 0;
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr)
return 0;
int lx = x - cx * CHUNK_W;
int ly = y - cy * CHUNK_H;
int lz = z - cz * CHUNK_D;
return chunk->lightmap->get(lx,ly,lz, channel);
}
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D;
int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D;
if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
return nullptr;
return chunks[(cy * d + cz) * w + cx];
}
Chunk* Chunks::getChunk(int x, int y, int z){
x -= ox;
y -= oy;
z -= oz;
if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d)
return nullptr;
return chunks[(y * d + z) * w + x];
}
void Chunks::set(int x, int y, int z, int id){
x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D;
int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D;
if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
return;
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr)
return;
int lx = x - cx * CHUNK_W;
int ly = y - cy * CHUNK_H;
int lz = z - cz * CHUNK_D;
chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx].id = id;
chunk->modified = true;
if (lx == 0 && (chunk = getChunk(cx+ox-1, cy+oy, cz+oz))) chunk->modified = true;
if (ly == 0 && (chunk = getChunk(cx+ox, cy+oy-1, cz+oz))) chunk->modified = true;
if (lz == 0 && (chunk = getChunk(cx+ox, cy+oy, cz+oz-1))) chunk->modified = true;
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cy+oy, cz+oz))) chunk->modified = true;
if (ly == CHUNK_H-1 && (chunk = getChunk(cx+ox, cy+oy+1, cz+oz))) chunk->modified = true;
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cy+oy, cz+oz+1))) chunk->modified = true;
}
voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, vec3& iend) {
float px = a.x;
float py = a.y;
float pz = a.z;
float dx = dir.x;
float dy = dir.y;
float dz = dir.z;
float t = 0.0f;
int ix = floor(px);
int iy = floor(py);
int iz = floor(pz);
float stepx = (dx > 0.0f) ? 1.0f : -1.0f;
float stepy = (dy > 0.0f) ? 1.0f : -1.0f;
float stepz = (dz > 0.0f) ? 1.0f : -1.0f;
float infinity = std::numeric_limits<float>::infinity();
float txDelta = (dx == 0.0f) ? infinity : abs(1.0f / dx);
float tyDelta = (dy == 0.0f) ? infinity : abs(1.0f / dy);
float tzDelta = (dz == 0.0f) ? infinity : abs(1.0f / dz);
float xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix);
float ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy);
float zdist = (stepz > 0) ? (iz + 1 - pz) : (pz - iz);
float txMax = (txDelta < infinity) ? txDelta * xdist : infinity;
float tyMax = (tyDelta < infinity) ? tyDelta * ydist : infinity;
float tzMax = (tzDelta < infinity) ? tzDelta * zdist : infinity;
int steppedIndex = -1;
while (t <= maxDist){
voxel* voxel = get(ix, iy, iz);
if (voxel == nullptr || voxel->id){
end.x = px + t * dx;
end.y = py + t * dy;
end.z = pz + t * dz;
iend.x = ix;
iend.y = iy;
iend.z = iz;
norm.x = norm.y = norm.z = 0.0f;
if (steppedIndex == 0) norm.x = -stepx;
if (steppedIndex == 1) norm.y = -stepy;
if (steppedIndex == 2) norm.z = -stepz;
return voxel;
}
if (txMax < tyMax) {
if (txMax < tzMax) {
ix += stepx;
t = txMax;
txMax += txDelta;
steppedIndex = 0;
} else {
iz += stepz;
t = tzMax;
tzMax += tzDelta;
steppedIndex = 2;
}
} else {
if (tyMax < tzMax) {
iy += stepy;
t = tyMax;
tyMax += tyDelta;
steppedIndex = 1;
} else {
iz += stepz;
t = tzMax;
tzMax += tzDelta;
steppedIndex = 2;
}
}
}
iend.x = ix;
iend.y = iy;
iend.z = iz;
end.x = px + t * dx;
end.y = py + t * dy;
end.z = pz + t * dz;
norm.x = norm.y = norm.z = 0.0f;
return nullptr;
}
void Chunks::setCenter(int x, int y, int z) {
int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D;
cx -= ox;
cy -= oy;
cz -= oz;
if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--;
cx -= w/2;
cy -= h/2;
cz -= d/2;
if (cx != 0 || cy != 0 || cz != 0)
translate(cx,cy,cz);
}
bool Chunks::loadVisible(WorldFiles* worldFiles){
int nearX = 0;
int nearY = 0;
int nearZ = 0;
int minDistance = 1000000000;
for (unsigned int y = 0; y < h; y++){
for (unsigned int z = 1; z < d-1; z++){
for (unsigned int x = 1; x < w-1; x++){
int index = (y * d + z) * w + x;
Chunk* chunk = chunks[index];
if (chunk != nullptr)
continue;
int lx = x - w / 2;
int ly = y - h / 2;
int lz = z - d / 2;
int distance = (lx * lx + ly * ly + lz * lz);
if (distance < minDistance){
minDistance = distance;
nearX = x;
nearY = y;
nearZ = z;
}
}
}
}
int index = (nearY * d + nearZ) * w + nearX;
Chunk* chunk = chunks[index];
if (chunk != nullptr)
return false;
chunk = new Chunk(nearX+ox,nearY+oy,nearZ+oz);
if (!worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels)){
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z);
}
chunks[index] = chunk;
Lighting::onChunkLoaded(ox+nearX, oy+nearY, oz+nearZ);
return true;
}
void Chunks::translate(int dx, int dy, int dz){
for (unsigned int i = 0; i < volume; i++){
chunksSecond[i] = nullptr;
meshesSecond[i] = nullptr;
}
for (unsigned int y = 0; y < h; y++){
for (unsigned int z = 0; z < d; z++){
for (unsigned int x = 0; x < w; x++){
Chunk* chunk = chunks[(y * d + z) * w + x];
int nx = x - dx;
int ny = y - dy;
int nz = z - dz;
if (chunk == nullptr)
continue;
Mesh* mesh = meshes[(y * d + z) * w + x];
if (nx < 0 || ny < 0 || nz < 0 || nx >= w || ny >= h || nz >= d){
delete chunk;
delete mesh;
continue;
}
meshesSecond[(ny * d + nz) * w + nx] = mesh;
chunksSecond[(ny * d + nz) * w + nx] = chunk;
}
}
}
Chunk** ctemp = chunks;
chunks = chunksSecond;
chunksSecond = ctemp;
Mesh** mtemp = meshes;
meshes = meshesSecond;
meshesSecond = mtemp;
ox += dx;
oy += dy;
oz += dz;
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef VOXELS_CHUNKS_H_
#define VOXELS_CHUNKS_H_
#include <stdlib.h>
#include <glm/glm.hpp>
using namespace glm;
class Mesh;
class VoxelRenderer;
class Chunk;
class voxel;
class WorldFiles;
class Chunks {
public:
Chunk** chunks;
Chunk** chunksSecond;
Mesh** meshes;
Mesh** meshesSecond;
size_t volume;
unsigned int w,h,d;
int ox,oy,oz;
Chunks(int w, int h, int d, int ox, int oy, int oz);
~Chunks();
Chunk* getChunk(int x, int y, int z);
Chunk* getChunkByVoxel(int x, int y, int z);
voxel* get(int x, int y, int z);
unsigned char getLight(int x, int y, int z, int channel);
void set(int x, int y, int z, int id);
voxel* rayCast(vec3 start, vec3 dir, float maxLength, vec3& end, vec3& norm, vec3& iend);
void setCenter(int x, int y, int z);
void translate(int x, int y, int z);
bool loadVisible(WorldFiles* worldFiles);
bool _buildMeshes(VoxelRenderer* renderer);
};
#endif /* VOXELS_CHUNKS_H_ */
+31
View File
@@ -0,0 +1,31 @@
#include "WorldGenerator.h"
#include "voxel.h";
#include "Chunk.h";
#include <math.h>
#include <glm/glm.hpp>
#include <glm/gtc/noise.hpp>
void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz){
for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){
int real_x = x + cx * CHUNK_W;
int real_z = z + cz * CHUNK_D;
float height = glm::perlin(glm::vec3(real_x*0.0125f,real_z*0.0125f, 0.0f));
height += glm::perlin(glm::vec3(real_x*0.025f,real_z*0.025f, 0.0f))*0.5f;
height *= 0.1f;
height += 0.05f;
for (int y = 0; y < CHUNK_H; y++){
int real_y = y + cy * CHUNK_H;
float noise = height;
int id = noise / std::fmax(0.01f, real_y*0.1f + 0.1f) > 0.1f;
if (real_y <= 2)
id = 2;
if (id == 0 && real_y == 14 && height <= 0.01f)
id = 1;
voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id;
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef VOXELS_WORLDGENERATOR_H_
#define VOXELS_WORLDGENERATOR_H_
class voxel;
class WorldGenerator {
public:
static void generate(voxel* voxels, int x, int y, int z);
};
#endif /* VOXELS_WORLDGENERATOR_H_ */
+2
View File
@@ -0,0 +1,2 @@
#include "voxel.h"
+10
View File
@@ -0,0 +1,10 @@
#ifndef VOXELS_VOXEL_H_
#define VOXELS_VOXEL_H_
#include <stdint.h>
struct voxel {
uint8_t id;
};
#endif /* VOXELS_VOXEL_H_ */