├── res ├── block.png ├── crosshair.glslf ├── crosshair.glslv ├── img.png ├── lines.glslf ├── lines.glslv ├── main.glslf ├── main.glslv ├── screen.glslf └── screen.glslv └── src ├── files ├── files.cpp └── files.h ├── graphics ├── LineBatch.cpp ├── LineBatch.h ├── Mesh.cpp ├── Mesh.h ├── Shader.cpp ├── Shader.h ├── Texture.cpp ├── Texture.h ├── VoxelRenderer.cpp └── VoxelRenderer.h ├── lighting ├── LightSolver.cpp ├── LightSolver.h ├── Lighting.cpp ├── Lighting.h ├── Lightmap.cpp └── Lightmap.h ├── loaders ├── png_loading.cpp └── png_loading.h ├── voxel_engine.cpp ├── voxels ├── Block.cpp ├── Block.h ├── Chunk.cpp ├── Chunk.h ├── Chunks.cpp ├── Chunks.h ├── voxel.cpp └── voxel.h └── window ├── Camera.cpp ├── Camera.h ├── Events.cpp ├── Events.h ├── Window.cpp └── Window.h /res/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MihailRis/VoxelEngine-Tutorials-Part-8/afdd7c5d09fd4758693a22270e6368f456171cf3/res/block.png -------------------------------------------------------------------------------- /res/crosshair.glslf: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | out vec4 f_color; 4 | 5 | void main(){ 6 | f_color = vec4(1.0); 7 | } 8 | -------------------------------------------------------------------------------- /res/crosshair.glslv: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec2 v_position; 4 | 5 | void main(){ 6 | gl_Position = vec4(v_position, 0.0, 1.0); 7 | } 8 | -------------------------------------------------------------------------------- /res/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MihailRis/VoxelEngine-Tutorials-Part-8/afdd7c5d09fd4758693a22270e6368f456171cf3/res/img.png -------------------------------------------------------------------------------- /res/lines.glslf: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec4 v_color; 4 | out vec4 f_color; 5 | 6 | void main(){ 7 | f_color = v_color; 8 | } 9 | -------------------------------------------------------------------------------- /res/lines.glslv: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec3 a_position; 4 | layout (location = 1) in vec4 a_color; 5 | 6 | out vec4 v_color; 7 | 8 | uniform mat4 projview; 9 | 10 | void main(){ 11 | v_color = a_color; 12 | gl_Position = projview * vec4(a_position, 1.0); 13 | } 14 | -------------------------------------------------------------------------------- /res/main.glslf: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec4 a_color; 4 | in vec2 a_texCoord; 5 | out vec4 f_color; 6 | 7 | uniform sampler2D u_texture0; 8 | 9 | void main(){ 10 | vec4 tex_color = texture(u_texture0, a_texCoord); 11 | if (tex_color.a < 0.5) 12 | discard; 13 | f_color = a_color * tex_color; 14 | } 15 | -------------------------------------------------------------------------------- /res/main.glslv: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec3 v_position; 4 | layout (location = 1) in vec2 v_texCoord; 5 | layout (location = 2) in vec4 v_light; 6 | 7 | out vec4 a_color; 8 | out vec2 a_texCoord; 9 | 10 | uniform mat4 model; 11 | uniform mat4 projview; 12 | 13 | void main(){ 14 | a_color = vec4(v_light.r,v_light.g,v_light.b,1.0f); 15 | a_texCoord = v_texCoord; 16 | a_color.rgb += v_light.a; 17 | //a_color.rgb = pow(a_color.rgb, vec3(1.0/0.7)); 18 | gl_Position = projview * model * vec4(v_position, 1.0); 19 | } 20 | -------------------------------------------------------------------------------- /res/screen.glslf: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 v_coord; 4 | out vec4 f_color; 5 | 6 | uniform sampler2D u_texture; 7 | 8 | void main(){ 9 | f_color = texture(u_texture, v_coord); 10 | } 11 | -------------------------------------------------------------------------------- /res/screen.glslv: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec2 v_position; 4 | 5 | out vec2 v_coord; 6 | 7 | void main(){ 8 | v_coord = v_position*0.5+0.5; 9 | gl_Position = vec4(v_position, 0.0, 1.0); 10 | } 11 | -------------------------------------------------------------------------------- /src/files/files.cpp: -------------------------------------------------------------------------------- 1 | #include "files.h" 2 | 3 | #include 4 | #include 5 | 6 | bool write_binary_file(std::string filename, const char* data, size_t size) { 7 | std::ofstream output(filename, std::ios::binary); 8 | if (!output.is_open()) 9 | return false; 10 | output.write(data, size); 11 | output.close(); 12 | return true; 13 | } 14 | 15 | 16 | bool read_binary_file(std::string filename, char* data, size_t size) { 17 | std::ifstream output(filename, std::ios::binary); 18 | if (!output.is_open()) 19 | return false; 20 | output.read(data, size); 21 | output.close(); 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /src/files/files.h: -------------------------------------------------------------------------------- 1 | #ifndef FILES_FILES_H_ 2 | #define FILES_FILES_H_ 3 | 4 | #include 5 | 6 | extern bool write_binary_file(std::string filename, const char* data, size_t size); 7 | extern bool read_binary_file(std::string filename, char* data, size_t size); 8 | 9 | #endif /* FILES_FILES_H_ */ 10 | -------------------------------------------------------------------------------- /src/graphics/LineBatch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LineBatch.cpp 3 | * 4 | * Created on: Jun 25, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #include "LineBatch.h" 9 | #include "Mesh.h" 10 | 11 | #include 12 | 13 | #define LB_VERTEX_SIZE (3+4) 14 | 15 | LineBatch::LineBatch(size_t capacity) : capacity(capacity) { 16 | int attrs[] = {3,4, 0}; 17 | buffer = new float[capacity * LB_VERTEX_SIZE * 2]; 18 | mesh = new Mesh(buffer, 0, attrs); 19 | index = 0; 20 | } 21 | 22 | LineBatch::~LineBatch(){ 23 | delete[] buffer; 24 | delete mesh; 25 | } 26 | 27 | void LineBatch::line(float x1, float y1, float z1, float x2, float y2, float z2, 28 | float r, float g, float b, float a) { 29 | buffer[index] = x1; 30 | buffer[index+1] = y1; 31 | buffer[index+2] = z1; 32 | buffer[index+3] = r; 33 | buffer[index+4] = g; 34 | buffer[index+5] = b; 35 | buffer[index+6] = a; 36 | index += LB_VERTEX_SIZE; 37 | 38 | buffer[index] = x2; 39 | buffer[index+1] = y2; 40 | buffer[index+2] = z2; 41 | buffer[index+3] = r; 42 | buffer[index+4] = g; 43 | buffer[index+5] = b; 44 | buffer[index+6] = a; 45 | index += LB_VERTEX_SIZE; 46 | } 47 | 48 | void LineBatch::box(float x, float y, float z, float w, float h, float d, 49 | float r, float g, float b, float a) { 50 | w *= 0.5f; 51 | h *= 0.5f; 52 | d *= 0.5f; 53 | 54 | line(x-w, y-h, z-d, x+w, y-h, z-d, r,g,b,a); 55 | line(x-w, y+h, z-d, x+w, y+h, z-d, r,g,b,a); 56 | line(x-w, y-h, z+d, x+w, y-h, z+d, r,g,b,a); 57 | line(x-w, y+h, z+d, x+w, y+h, z+d, r,g,b,a); 58 | 59 | line(x-w, y-h, z-d, x-w, y+h, z-d, r,g,b,a); 60 | line(x+w, y-h, z-d, x+w, y+h, z-d, r,g,b,a); 61 | line(x-w, y-h, z+d, x-w, y+h, z+d, r,g,b,a); 62 | line(x+w, y-h, z+d, x+w, y+h, z+d, r,g,b,a); 63 | 64 | line(x-w, y-h, z-d, x-w, y-h, z+d, r,g,b,a); 65 | line(x+w, y-h, z-d, x+w, y-h, z+d, r,g,b,a); 66 | line(x-w, y+h, z-d, x-w, y+h, z+d, r,g,b,a); 67 | line(x+w, y+h, z-d, x+w, y+h, z+d, r,g,b,a); 68 | } 69 | 70 | void LineBatch::render(){ 71 | if (index == 0) 72 | return; 73 | mesh->reload(buffer, index / LB_VERTEX_SIZE); 74 | mesh->draw(GL_LINES); 75 | index = 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/graphics/LineBatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LineBatch.h 3 | * 4 | * Created on: Jun 25, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #ifndef GRAPHICS_LINEBATCH_H_ 9 | #define GRAPHICS_LINEBATCH_H_ 10 | 11 | #include 12 | 13 | class Mesh; 14 | 15 | class LineBatch { 16 | Mesh* mesh; 17 | float* buffer; 18 | size_t index; 19 | size_t capacity; 20 | public: 21 | LineBatch(size_t capacity); 22 | ~LineBatch(); 23 | 24 | void line(float x1, float y1, float z1, float x2, float y2, float z2, 25 | float r, float g, float b, float a); 26 | void box(float x, float y, float z, float w, float h, float d, 27 | float r, float g, float b, float a); 28 | 29 | void render(); 30 | }; 31 | 32 | #endif /* GRAPHICS_LINEBATCH_H_ */ 33 | -------------------------------------------------------------------------------- /src/graphics/Mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "Mesh.h" 2 | #include 3 | 4 | Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(vertices){ 5 | vertexSize = 0; 6 | for (int i = 0; attrs[i]; i++){ 7 | vertexSize += attrs[i]; 8 | } 9 | 10 | glGenVertexArrays(1, &vao); 11 | glGenBuffers(1, &vbo); 12 | 13 | glBindVertexArray(vao); 14 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 15 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW); 16 | 17 | // attributes 18 | int offset = 0; 19 | for (int i = 0; attrs[i]; i++){ 20 | int size = attrs[i]; 21 | glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float))); 22 | glEnableVertexAttribArray(i); 23 | offset += size; 24 | } 25 | 26 | glBindVertexArray(0); 27 | } 28 | 29 | Mesh::~Mesh(){ 30 | glDeleteVertexArrays(1, &vao); 31 | glDeleteBuffers(1, &vbo); 32 | } 33 | 34 | void Mesh::reload(const float* buffer, size_t vertices){ 35 | glBindVertexArray(vao); 36 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 37 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW); 38 | this->vertices = vertices; 39 | } 40 | 41 | void Mesh::draw(unsigned int primitive){ 42 | glBindVertexArray(vao); 43 | glDrawArrays(primitive, 0, vertices); 44 | glBindVertexArray(0); 45 | } 46 | -------------------------------------------------------------------------------- /src/graphics/Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICS_MESH_H_ 2 | #define GRAPHICS_MESH_H_ 3 | 4 | #include 5 | 6 | class Mesh { 7 | unsigned int vao; 8 | unsigned int vbo; 9 | size_t vertices; 10 | size_t vertexSize; 11 | public: 12 | Mesh(const float* buffer, size_t vertices, const int* attrs); 13 | ~Mesh(); 14 | 15 | void reload(const float* buffer, size_t vertices); 16 | void draw(unsigned int primitive); 17 | }; 18 | 19 | #endif /* GRAPHICS_MESH_H_ */ 20 | -------------------------------------------------------------------------------- /src/graphics/Shader.cpp: -------------------------------------------------------------------------------- 1 | #include "Shader.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | Shader::Shader(unsigned int id) : id(id){ 14 | } 15 | 16 | Shader::~Shader(){ 17 | glDeleteProgram(id); 18 | } 19 | 20 | void Shader::use(){ 21 | glUseProgram(id); 22 | } 23 | 24 | void Shader::uniformMatrix(std::string name, glm::mat4 matrix){ 25 | GLuint transformLoc = glGetUniformLocation(id, name.c_str()); 26 | glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix)); 27 | } 28 | 29 | 30 | Shader* load_shader(std::string vertexFile, std::string fragmentFile) { 31 | // Reading Files 32 | std::string vertexCode; 33 | std::string fragmentCode; 34 | std::ifstream vShaderFile; 35 | std::ifstream fShaderFile; 36 | 37 | vShaderFile.exceptions(std::ifstream::badbit); 38 | fShaderFile.exceptions(std::ifstream::badbit); 39 | try { 40 | vShaderFile.open(vertexFile); 41 | fShaderFile.open(fragmentFile); 42 | std::stringstream vShaderStream, fShaderStream; 43 | 44 | vShaderStream << vShaderFile.rdbuf(); 45 | fShaderStream << fShaderFile.rdbuf(); 46 | 47 | vShaderFile.close(); 48 | fShaderFile.close(); 49 | 50 | vertexCode = vShaderStream.str(); 51 | fragmentCode = fShaderStream.str(); 52 | } 53 | catch(std::ifstream::failure& e) { 54 | std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; 55 | return nullptr; 56 | } 57 | const GLchar* vShaderCode = vertexCode.c_str(); 58 | const GLchar* fShaderCode = fragmentCode.c_str(); 59 | 60 | GLuint vertex, fragment; 61 | GLint success; 62 | GLchar infoLog[512]; 63 | 64 | // Vertex Shader 65 | vertex = glCreateShader(GL_VERTEX_SHADER); 66 | glShaderSource(vertex, 1, &vShaderCode, nullptr); 67 | glCompileShader(vertex); 68 | glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 69 | if (!success){ 70 | glGetShaderInfoLog(vertex, 512, nullptr, infoLog); 71 | std::cerr << "SHADER::VERTEX: compilation failed" << std::endl; 72 | std::cerr << infoLog << std::endl; 73 | return nullptr; 74 | } 75 | 76 | // Fragment Shader 77 | fragment = glCreateShader(GL_FRAGMENT_SHADER); 78 | glShaderSource(fragment, 1, &fShaderCode, nullptr); 79 | glCompileShader(fragment); 80 | glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); 81 | if (!success){ 82 | glGetShaderInfoLog(fragment, 512, nullptr, infoLog); 83 | std::cerr << "SHADER::FRAGMENT: compilation failed" << std::endl; 84 | std::cerr << infoLog << std::endl; 85 | return nullptr; 86 | } 87 | 88 | // Shader Program 89 | GLuint id = glCreateProgram(); 90 | glAttachShader(id, vertex); 91 | glAttachShader(id, fragment); 92 | glLinkProgram(id); 93 | 94 | glGetProgramiv(id, GL_LINK_STATUS, &success); 95 | if (!success){ 96 | glGetProgramInfoLog(id, 512, nullptr, infoLog); 97 | std::cerr << "SHADER::PROGRAM: linking failed" << std::endl; 98 | std::cerr << infoLog << std::endl; 99 | 100 | glDeleteShader(vertex); 101 | glDeleteShader(fragment); 102 | return nullptr; 103 | } 104 | 105 | glDeleteShader(vertex); 106 | glDeleteShader(fragment); 107 | 108 | return new Shader(id); 109 | } 110 | -------------------------------------------------------------------------------- /src/graphics/Shader.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICS_SHADER_H_ 2 | #define GRAPHICS_SHADER_H_ 3 | 4 | #include 5 | #include 6 | 7 | class Shader { 8 | public: 9 | unsigned int id; 10 | 11 | Shader(unsigned int id); 12 | ~Shader(); 13 | 14 | void use(); 15 | void uniformMatrix(std::string name, glm::mat4 matrix); 16 | }; 17 | 18 | extern Shader* load_shader(std::string vertexFile, std::string fragmentFile); 19 | 20 | #endif /* GRAPHICS_SHADER_H_ */ 21 | -------------------------------------------------------------------------------- /src/graphics/Texture.cpp: -------------------------------------------------------------------------------- 1 | #include "Texture.h" 2 | #include 3 | 4 | Texture::Texture(unsigned int id, int width, int height) : id(id), width(width), height(height) { 5 | } 6 | 7 | Texture::Texture(unsigned char* data, int width, int height) : width(width), height(height) { 8 | glGenTextures(1, &id); 9 | glBindTexture(GL_TEXTURE_2D, id); 10 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 11 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 12 | GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data); 13 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 14 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 15 | glBindTexture(GL_TEXTURE_2D, 0); 16 | } 17 | 18 | Texture::~Texture() { 19 | glDeleteTextures(1, &id); 20 | } 21 | 22 | void Texture::bind(){ 23 | glBindTexture(GL_TEXTURE_2D, id); 24 | } 25 | 26 | void Texture::reload(unsigned char* data){ 27 | glBindTexture(GL_TEXTURE_2D, id); 28 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 29 | GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data); 30 | glBindTexture(GL_TEXTURE_2D, 0); 31 | } 32 | -------------------------------------------------------------------------------- /src/graphics/Texture.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICS_TEXTURE_H_ 2 | #define GRAPHICS_TEXTURE_H_ 3 | 4 | #include 5 | 6 | class Texture { 7 | public: 8 | unsigned int id; 9 | int width; 10 | int height; 11 | Texture(unsigned int id, int width, int height); 12 | Texture(unsigned char* data, int width, int height); 13 | ~Texture(); 14 | 15 | void bind(); 16 | void reload(unsigned char* data); 17 | }; 18 | 19 | extern Texture* load_texture(std::string filename); 20 | 21 | #endif /* GRAPHICS_TEXTURE_H_ */ 22 | -------------------------------------------------------------------------------- /src/graphics/VoxelRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "VoxelRenderer.h" 2 | #include "Mesh.h" 3 | #include "../voxels/Chunk.h" 4 | #include "../voxels/voxel.h" 5 | #include "../voxels/Block.h" 6 | #include "../lighting/Lightmap.h" 7 | 8 | #define VERTEX_SIZE (3 + 2 + 4) 9 | 10 | #define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A))) 11 | #define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) 12 | #define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) 13 | #define IS_CHUNK(X,Y,Z) (GET_CHUNK(X,Y,Z) != nullptr) 14 | #define GET_CHUNK(X,Y,Z) (chunks[((CDIV(Y, CHUNK_H)+1) * 3 + CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1]) 15 | 16 | #define LIGHT(X,Y,Z, CHANNEL) (IS_CHUNK(X,Y,Z) ? GET_CHUNK(X,Y,Z)->lightmap->get(LOCAL(X, CHUNK_W), LOCAL(Y, CHUNK_H), LOCAL(Z, CHUNK_D), (CHANNEL)) : 0) 17 | #define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)]) 18 | #define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP)) 19 | 20 | #define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer[INDEX+0] = (X);\ 21 | buffer[INDEX+1] = (Y);\ 22 | buffer[INDEX+2] = (Z);\ 23 | buffer[INDEX+3] = (U);\ 24 | buffer[INDEX+4] = (V);\ 25 | buffer[INDEX+5] = (R);\ 26 | buffer[INDEX+6] = (G);\ 27 | buffer[INDEX+7] = (B);\ 28 | buffer[INDEX+8] = (S);\ 29 | INDEX += VERTEX_SIZE; 30 | 31 | 32 | #define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\ 33 | float v1 = 1-((1 + (INDEX) / 16) * uvsize);\ 34 | float u2 = u1 + uvsize;\ 35 | float v2 = v1 + uvsize; 36 | 37 | int chunk_attrs[] = {3,2,4, 0}; 38 | 39 | VoxelRenderer::VoxelRenderer(size_t capacity) : capacity(capacity) { 40 | buffer = new float[capacity * VERTEX_SIZE * 6]; 41 | } 42 | 43 | VoxelRenderer::~VoxelRenderer(){ 44 | delete[] buffer; 45 | } 46 | 47 | Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){ 48 | size_t index = 0; 49 | for (int y = 0; y < CHUNK_H; y++){ 50 | for (int z = 0; z < CHUNK_D; z++){ 51 | for (int x = 0; x < CHUNK_W; x++){ 52 | voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; 53 | unsigned int id = vox.id; 54 | 55 | if (!id){ 56 | continue; 57 | } 58 | 59 | float l; 60 | float uvsize = 1.0f/16.0f; 61 | 62 | Block* block = Block::blocks[id]; 63 | unsigned char group = block->drawGroup; 64 | 65 | if (!IS_BLOCKED(x,y+1,z,group)){ 66 | l = 1.0f; 67 | 68 | SETUP_UV(block->textureFaces[3]); 69 | 70 | float lr = LIGHT(x,y+1,z, 0) / 15.0f; 71 | float lg = LIGHT(x,y+1,z, 1) / 15.0f; 72 | float lb = LIGHT(x,y+1,z, 2) / 15.0f; 73 | float ls = LIGHT(x,y+1,z, 3) / 15.0f; 74 | 75 | float lr0 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 5.0f / 15.0f; 76 | float lr1 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 5.0f / 15.0f; 77 | float lr2 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 5.0f / 15.0f; 78 | float lr3 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 5.0f / 15.0f; 79 | 80 | float lg0 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 5.0f / 15.0f; 81 | float lg1 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 5.0f / 15.0f; 82 | float lg2 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 5.0f / 15.0f; 83 | float lg3 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 5.0f / 15.0f; 84 | 85 | float lb0 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 5.0f / 15.0f; 86 | float lb1 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 5.0f / 15.0f; 87 | float lb2 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 5.0f / 15.0f; 88 | float lb3 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 5.0f / 15.0f; 89 | 90 | float ls0 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 5.0f / 15.0f; 91 | float ls1 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 5.0f / 15.0f; 92 | float ls2 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 5.0f / 15.0f; 93 | float ls3 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 5.0f / 15.0f; 94 | 95 | VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0, lg0, lb0, ls0); 96 | VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1, lg1, lb1, ls1); 97 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2, lg2, lb2, ls2); 98 | 99 | VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0, lg0, lb0, ls0); 100 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2, lg2, lb2, ls2); 101 | VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, lr3, lg3, lb3, ls3); 102 | } 103 | if (!IS_BLOCKED(x,y-1,z,group)){ 104 | l = 0.75f; 105 | 106 | SETUP_UV(block->textureFaces[2]); 107 | 108 | float lr = LIGHT(x,y-1,z, 0) / 15.0f; 109 | float lg = LIGHT(x,y-1,z, 1) / 15.0f; 110 | float lb = LIGHT(x,y-1,z, 2) / 15.0f; 111 | float ls = LIGHT(x,y-1,z, 3) / 15.0f; 112 | 113 | float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 5.0f / 15.0f; 114 | float lr1 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 5.0f / 15.0f; 115 | float lr2 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 5.0f / 15.0f; 116 | float lr3 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 5.0f / 15.0f; 117 | 118 | float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 5.0f / 15.0f; 119 | float lg1 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 5.0f / 15.0f; 120 | float lg2 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 5.0f / 15.0f; 121 | float lg3 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 5.0f / 15.0f; 122 | 123 | float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 5.0f / 15.0f; 124 | float lb1 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 5.0f / 15.0f; 125 | float lb2 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 5.0f / 15.0f; 126 | float lb3 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 5.0f / 15.0f; 127 | 128 | float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 5.0f / 15.0f; 129 | float ls1 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 5.0f / 15.0f; 130 | float ls2 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 5.0f / 15.0f; 131 | float ls3 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 5.0f / 15.0f; 132 | 133 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); 134 | VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 135 | VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); 136 | 137 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); 138 | VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr3,lg3,lb3,ls3); 139 | VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 140 | } 141 | 142 | if (!IS_BLOCKED(x+1,y,z,group)){ 143 | l = 0.95f; 144 | 145 | SETUP_UV(block->textureFaces[1]); 146 | 147 | float lr = LIGHT(x+1,y,z, 0) / 15.0f; 148 | float lg = LIGHT(x+1,y,z, 1) / 15.0f; 149 | float lb = LIGHT(x+1,y,z, 2) / 15.0f; 150 | float ls = LIGHT(x+1,y,z, 3) / 15.0f; 151 | 152 | float lr0 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y-1,z,0)) / 5.0f / 15.0f; 153 | float lr1 = (LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y+1,z,0)) / 5.0f / 15.0f; 154 | float lr2 = (LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y+1,z,0)) / 5.0f / 15.0f; 155 | float lr3 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y-1,z,0)) / 5.0f / 15.0f; 156 | 157 | float lg0 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y-1,z,1)) / 5.0f / 15.0f; 158 | float lg1 = (LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y+1,z,1)) / 5.0f / 15.0f; 159 | float lg2 = (LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y+1,z,1)) / 5.0f / 15.0f; 160 | float lg3 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y-1,z,1)) / 5.0f / 15.0f; 161 | 162 | float lb0 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y-1,z,2)) / 5.0f / 15.0f; 163 | float lb1 = (LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y+1,z,2)) / 5.0f / 15.0f; 164 | float lb2 = (LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y+1,z,2)) / 5.0f / 15.0f; 165 | float lb3 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y-1,z,2)) / 5.0f / 15.0f; 166 | 167 | float ls0 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y-1,z,3)) / 5.0f / 15.0f; 168 | float ls1 = (LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y+1,z,3)) / 5.0f / 15.0f; 169 | float ls2 = (LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y+1,z,3)) / 5.0f / 15.0f; 170 | float ls3 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y-1,z,3)) / 5.0f / 15.0f; 171 | 172 | VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); 173 | VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1); 174 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); 175 | 176 | VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); 177 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); 178 | VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, lr3,lg3,lb3,ls3); 179 | } 180 | if (!IS_BLOCKED(x-1,y,z,group)){ 181 | l = 0.85f; 182 | 183 | SETUP_UV(block->textureFaces[0]); 184 | 185 | float lr = LIGHT(x-1,y,z, 0) / 15.0f; 186 | float lg = LIGHT(x-1,y,z, 1) / 15.0f; 187 | float lb = LIGHT(x-1,y,z, 2) / 15.0f; 188 | float ls = LIGHT(x-1,y,z, 3) / 15.0f; 189 | 190 | float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y-1,z,0)) / 5.0f / 15.0f; 191 | float lr1 = (LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y+1,z,0)) / 5.0f / 15.0f; 192 | float lr2 = (LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y+1,z,0)) / 5.0f / 15.0f; 193 | float lr3 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y-1,z,0)) / 5.0f / 15.0f; 194 | 195 | float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y-1,z,1)) / 5.0f / 15.0f; 196 | float lg1 = (LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y+1,z,1)) / 5.0f / 15.0f; 197 | float lg2 = (LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y+1,z,1)) / 5.0f / 15.0f; 198 | float lg3 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y-1,z,1)) / 5.0f / 15.0f; 199 | 200 | float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y-1,z,2)) / 5.0f / 15.0f; 201 | float lb1 = (LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y+1,z,2)) / 5.0f / 15.0f; 202 | float lb2 = (LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y+1,z,2)) / 5.0f / 15.0f; 203 | float lb3 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y-1,z,2)) / 5.0f / 15.0f; 204 | 205 | float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y-1,z,3)) / 5.0f / 15.0f; 206 | float ls1 = (LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y+1,z,3)) / 5.0f / 15.0f; 207 | float ls2 = (LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y+1,z,3)) / 5.0f / 15.0f; 208 | float ls3 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y-1,z,3)) / 5.0f / 15.0f; 209 | 210 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); 211 | VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 212 | VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); 213 | 214 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); 215 | VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); 216 | VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 217 | } 218 | 219 | if (!IS_BLOCKED(x,y,z+1,group)){ 220 | l = 0.9f; 221 | 222 | SETUP_UV(block->textureFaces[5]); 223 | 224 | float lr = LIGHT(x,y,z+1, 0) / 15.0f; 225 | float lg = LIGHT(x,y,z+1, 1) / 15.0f; 226 | float lb = LIGHT(x,y,z+1, 2) / 15.0f; 227 | float ls = LIGHT(x,y,z+1, 3) / 15.0f; 228 | 229 | float lr0 = l*(LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 5.0f / 15.0f; 230 | float lr1 = l*(LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 5.0f / 15.0f; 231 | float lr2 = l*(LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 5.0f / 15.0f; 232 | float lr3 = l*(LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 5.0f / 15.0f; 233 | 234 | float lg0 = l*(LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 5.0f / 15.0f; 235 | float lg1 = l*(LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 5.0f / 15.0f; 236 | float lg2 = l*(LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 5.0f / 15.0f; 237 | float lg3 = l*(LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 5.0f / 15.0f; 238 | 239 | float lb0 = l*(LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 5.0f / 15.0f; 240 | float lb1 = l*(LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 5.0f / 15.0f; 241 | float lb2 = l*(LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 5.0f / 15.0f; 242 | float lb3 = l*(LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 5.0f / 15.0f; 243 | 244 | float ls0 = l*(LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 5.0f / 15.0f; 245 | float ls1 = l*(LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 5.0f / 15.0f; 246 | float ls2 = l*(LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 5.0f / 15.0f; 247 | float ls3 = l*(LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 5.0f / 15.0f; 248 | 249 | VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); 250 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 251 | VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); 252 | 253 | VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); 254 | VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); 255 | VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); 256 | } 257 | if (!IS_BLOCKED(x,y,z-1,group)){ 258 | l = 0.8f; 259 | 260 | SETUP_UV(block->textureFaces[4]); 261 | 262 | float lr = LIGHT(x,y,z-1, 0) / 15.0f; 263 | float lg = LIGHT(x,y,z-1, 1) / 15.0f; 264 | float lb = LIGHT(x,y,z-1, 2) / 15.0f; 265 | float ls = LIGHT(x,y,z-1, 3) / 15.0f; 266 | 267 | float lr0 = l*(LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 5.0f / 15.0f; 268 | float lr1 = l*(LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 5.0f / 15.0f; 269 | float lr2 = l*(LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 5.0f / 15.0f; 270 | float lr3 = l*(LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 5.0f / 15.0f; 271 | 272 | float lg0 = l*(LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 5.0f / 15.0f; 273 | float lg1 = l*(LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 5.0f / 15.0f; 274 | float lg2 = l*(LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 5.0f / 15.0f; 275 | float lg3 = l*(LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 5.0f / 15.0f; 276 | 277 | float lb0 = l*(LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 5.0f / 15.0f; 278 | float lb1 = l*(LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 5.0f / 15.0f; 279 | float lb2 = l*(LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 5.0f / 15.0f; 280 | float lb3 = l*(LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 5.0f / 15.0f; 281 | 282 | float ls0 = l*(LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 5.0f / 15.0f; 283 | float ls1 = l*(LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 5.0f / 15.0f; 284 | float ls2 = l*(LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 5.0f / 15.0f; 285 | float ls3 = l*(LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 5.0f / 15.0f; 286 | 287 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); 288 | VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1); 289 | VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); 290 | 291 | VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); 292 | VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); 293 | VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3); 294 | } 295 | } 296 | } 297 | } 298 | return new Mesh(buffer, index / VERTEX_SIZE, chunk_attrs); 299 | } 300 | -------------------------------------------------------------------------------- /src/graphics/VoxelRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICS_VOXELRENDERER_H_ 2 | #define GRAPHICS_VOXELRENDERER_H_ 3 | 4 | #include 5 | 6 | class Mesh; 7 | class Chunk; 8 | 9 | class VoxelRenderer { 10 | float* buffer; 11 | size_t capacity; 12 | public: 13 | VoxelRenderer(size_t capacity); 14 | ~VoxelRenderer(); 15 | 16 | Mesh* render(Chunk* chunk, const Chunk** chunks); 17 | }; 18 | 19 | #endif /* GRAPHICS_VOXELRENDERER_H_ */ 20 | -------------------------------------------------------------------------------- /src/lighting/LightSolver.cpp: -------------------------------------------------------------------------------- 1 | #include "LightSolver.h" 2 | #include "Lightmap.h" 3 | #include "../voxels/Chunks.h" 4 | #include "../voxels/Chunk.h" 5 | #include "../voxels/voxel.h" 6 | #include "../voxels/Block.h" 7 | 8 | LightSolver::LightSolver(Chunks* chunks, int channel) : chunks(chunks), channel(channel) { 9 | } 10 | 11 | void LightSolver::add(int x, int y, int z, int emission) { 12 | if (emission <= 1) 13 | return; 14 | lightentry entry; 15 | entry.x = x; 16 | entry.y = y; 17 | entry.z = z; 18 | entry.light = emission; 19 | addqueue.push(entry); 20 | 21 | Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z); 22 | chunk->modified = true; 23 | chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, entry.light); 24 | } 25 | 26 | void LightSolver::add(int x, int y, int z) { 27 | add(x,y,z, chunks->getLight(x,y,z, channel)); 28 | } 29 | 30 | void LightSolver::remove(int x, int y, int z) { 31 | Chunk* chunk = chunks->getChunkByVoxel(x, y, z); 32 | if (chunk == nullptr) 33 | return; 34 | 35 | int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel); 36 | if (light == 0){ 37 | return; 38 | } 39 | 40 | lightentry entry; 41 | entry.x = x; 42 | entry.y = y; 43 | entry.z = z; 44 | entry.light = light; 45 | remqueue.push(entry); 46 | 47 | chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, 0); 48 | } 49 | 50 | void LightSolver::solve(){ 51 | const int coords[] = { 52 | 0, 0, 1, 53 | 0, 0,-1, 54 | 0, 1, 0, 55 | 0,-1, 0, 56 | 1, 0, 0, 57 | -1, 0, 0 58 | }; 59 | 60 | while (!remqueue.empty()){ 61 | lightentry entry = remqueue.front(); 62 | remqueue.pop(); 63 | 64 | for (size_t i = 0; i < 6; i++) { 65 | int x = entry.x+coords[i*3+0]; 66 | int y = entry.y+coords[i*3+1]; 67 | int z = entry.z+coords[i*3+2]; 68 | Chunk* chunk = chunks->getChunkByVoxel(x,y,z); 69 | if (chunk) { 70 | int light = chunks->getLight(x,y,z, channel); 71 | if (light != 0 && light == entry.light-1){ 72 | lightentry nentry; 73 | nentry.x = x; 74 | nentry.y = y; 75 | nentry.z = z; 76 | nentry.light = light; 77 | remqueue.push(nentry); 78 | chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0); 79 | chunk->modified = true; 80 | } 81 | else if (light >= entry.light){ 82 | lightentry nentry; 83 | nentry.x = x; 84 | nentry.y = y; 85 | nentry.z = z; 86 | nentry.light = light; 87 | addqueue.push(nentry); 88 | } 89 | } 90 | } 91 | } 92 | 93 | while (!addqueue.empty()){ 94 | lightentry entry = addqueue.front(); 95 | addqueue.pop(); 96 | 97 | if (entry.light <= 1) 98 | continue; 99 | 100 | for (size_t i = 0; i < 6; i++) { 101 | int x = entry.x+coords[i*3+0]; 102 | int y = entry.y+coords[i*3+1]; 103 | int z = entry.z+coords[i*3+2]; 104 | Chunk* chunk = chunks->getChunkByVoxel(x,y,z); 105 | if (chunk) { 106 | int light = chunks->getLight(x,y,z, channel); 107 | voxel* v = chunks->get(x,y,z); 108 | Block* block = Block::blocks[v->id]; 109 | if (block->lightPassing && light+2 <= entry.light){ 110 | chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, entry.light-1); 111 | chunk->modified = true; 112 | lightentry nentry; 113 | nentry.x = x; 114 | nentry.y = y; 115 | nentry.z = z; 116 | nentry.light = entry.light-1; 117 | addqueue.push(nentry); 118 | } 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/lighting/LightSolver.h: -------------------------------------------------------------------------------- 1 | #ifndef LIGHTING_LIGHTSOLVER_H_ 2 | #define LIGHTING_LIGHTSOLVER_H_ 3 | 4 | #include 5 | 6 | class Chunks; 7 | 8 | struct lightentry { 9 | int x; 10 | int y; 11 | int z; 12 | unsigned char light; 13 | }; 14 | 15 | class LightSolver { 16 | std::queue addqueue; 17 | std::queue remqueue; 18 | Chunks* chunks; 19 | int channel; 20 | public: 21 | LightSolver(Chunks* chunks, int channel); 22 | 23 | void add(int x, int y, int z); 24 | void add(int x, int y, int z, int emission); 25 | void remove(int x, int y, int z); 26 | void solve(); 27 | }; 28 | 29 | #endif /* LIGHTING_LIGHTSOLVER_H_ */ 30 | -------------------------------------------------------------------------------- /src/lighting/Lighting.cpp: -------------------------------------------------------------------------------- 1 | #include "Lighting.h" 2 | #include "LightSolver.h" 3 | #include "Lightmap.h" 4 | #include "../voxels/Chunks.h" 5 | #include "../voxels/Chunk.h" 6 | #include "../voxels/voxel.h" 7 | #include "../voxels/Block.h" 8 | 9 | Chunks* Lighting::chunks = nullptr; 10 | LightSolver* Lighting::solverR = nullptr; 11 | LightSolver* Lighting::solverG = nullptr; 12 | LightSolver* Lighting::solverB = nullptr; 13 | LightSolver* Lighting::solverS = nullptr; 14 | 15 | int Lighting::initialize(Chunks* chunks){ 16 | Lighting::chunks = chunks; 17 | solverR = new LightSolver(chunks, 0); 18 | solverG = new LightSolver(chunks, 1); 19 | solverB = new LightSolver(chunks, 2); 20 | solverS = new LightSolver(chunks, 3); 21 | return 0; 22 | } 23 | 24 | void Lighting::finalize(){ 25 | delete solverR, solverG, solverB, solverS; 26 | } 27 | 28 | void Lighting::clear(){ 29 | for (unsigned int y = 0; y < chunks->h; y++){ 30 | for (unsigned int z = 0; z < chunks->d; z++){ 31 | for (unsigned int x = 0; x < chunks->w; x++){ 32 | Chunk* chunk = chunks->getChunk(x,y,z); 33 | Lightmap* lightmap = chunk->lightmap; 34 | for (int i = 0; i < CHUNK_VOL; i++){ 35 | lightmap->map[i] = 0; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | void Lighting::onWorldLoaded(){ 43 | for (int y = 0; y < chunks->h*CHUNK_H; y++){ 44 | for (int z = 0; z < chunks->d*CHUNK_D; z++){ 45 | for (int x = 0; x < chunks->w*CHUNK_W; x++){ 46 | voxel* vox = chunks->get(x,y,z); 47 | Block* block = Block::blocks[vox->id]; 48 | if (block->emission[0] || block->emission[1] || block->emission[2]){ 49 | solverR->add(x,y,z,block->emission[0]); 50 | solverG->add(x,y,z,block->emission[1]); 51 | solverB->add(x,y,z,block->emission[2]); 52 | } 53 | } 54 | } 55 | } 56 | 57 | for (int z = 0; z < chunks->d*CHUNK_D; z++){ 58 | for (int x = 0; x < chunks->w*CHUNK_W; x++){ 59 | for (int y = chunks->h*CHUNK_H-1; y >= 0; y--){ 60 | voxel* vox = chunks->get(x,y,z); 61 | if (vox->id != 0){ 62 | break; 63 | } 64 | chunks->getChunkByVoxel(x,y,z)->lightmap->setS(x % CHUNK_W, y % CHUNK_H, z % CHUNK_D, 0xF); 65 | } 66 | } 67 | } 68 | 69 | for (int z = 0; z < chunks->d*CHUNK_D; z++){ 70 | for (int x = 0; x < chunks->w*CHUNK_W; x++){ 71 | for (int y = chunks->h*CHUNK_H-1; y >= 0; y--){ 72 | voxel* vox = chunks->get(x,y,z); 73 | if (vox->id != 0){ 74 | break; 75 | } 76 | if ( 77 | chunks->getLight(x-1,y,z, 3) == 0 || 78 | chunks->getLight(x+1,y,z, 3) == 0 || 79 | chunks->getLight(x,y-1,z, 3) == 0 || 80 | chunks->getLight(x,y+1,z, 3) == 0 || 81 | chunks->getLight(x,y,z-1, 3) == 0 || 82 | chunks->getLight(x,y,z+1, 3) == 0 83 | ){ 84 | solverS->add(x,y,z); 85 | } 86 | chunks->getChunkByVoxel(x,y,z)->lightmap->setS(x % CHUNK_W, y % CHUNK_H, z % CHUNK_D, 0xF); 87 | } 88 | } 89 | } 90 | 91 | solverR->solve(); 92 | solverG->solve(); 93 | solverB->solve(); 94 | solverS->solve(); 95 | } 96 | 97 | void Lighting::onBlockSet(int x, int y, int z, int id){ 98 | if (id == 0){ 99 | solverR->remove(x,y,z); 100 | solverG->remove(x,y,z); 101 | solverB->remove(x,y,z); 102 | 103 | solverR->solve(); 104 | solverG->solve(); 105 | solverB->solve(); 106 | 107 | if (chunks->getLight(x,y+1,z, 3) == 0xF){ 108 | for (int i = y; i >= 0; i--){ 109 | if (chunks->get(x,i,z)->id != 0) 110 | break; 111 | solverS->add(x,i,z, 0xF); 112 | } 113 | } 114 | 115 | solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z); 116 | solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z); 117 | solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z); 118 | solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z); 119 | solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1); 120 | solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1); 121 | 122 | solverR->solve(); 123 | solverG->solve(); 124 | solverB->solve(); 125 | solverS->solve(); 126 | } else { 127 | solverR->remove(x,y,z); 128 | solverG->remove(x,y,z); 129 | solverB->remove(x,y,z); 130 | solverS->remove(x,y,z); 131 | for (int i = y-1; i >= 0; i--){ 132 | solverS->remove(x,i,z); 133 | if (i == 0 || chunks->get(x,i-1,z)->id != 0){ 134 | break; 135 | } 136 | } 137 | solverR->solve(); 138 | solverG->solve(); 139 | solverB->solve(); 140 | solverS->solve(); 141 | 142 | Block* block = Block::blocks[id]; 143 | if (block->emission[0] || block->emission[1] || block->emission[2]){ 144 | solverR->add(x,y,z,block->emission[0]); 145 | solverG->add(x,y,z,block->emission[1]); 146 | solverB->add(x,y,z,block->emission[2]); 147 | solverR->solve(); 148 | solverG->solve(); 149 | solverB->solve(); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/lighting/Lighting.h: -------------------------------------------------------------------------------- 1 | #ifndef LIGHTING_LIGHTING_H_ 2 | #define LIGHTING_LIGHTING_H_ 3 | 4 | class Chunks; 5 | class LightSolver; 6 | 7 | class Lighting { 8 | static Chunks* chunks; 9 | static LightSolver* solverR; 10 | static LightSolver* solverG; 11 | static LightSolver* solverB; 12 | static LightSolver* solverS; 13 | public: 14 | static int initialize(Chunks* chunks); 15 | static void finalize(); 16 | 17 | static void clear(); 18 | static void onWorldLoaded(); 19 | static void onBlockSet(int x, int y, int z, int id); 20 | }; 21 | 22 | #endif /* LIGHTING_LIGHTING_H_ */ 23 | -------------------------------------------------------------------------------- /src/lighting/Lightmap.cpp: -------------------------------------------------------------------------------- 1 | #include "Lightmap.h" 2 | 3 | Lightmap::Lightmap(){ 4 | map = new unsigned short[CHUNK_VOL]; 5 | for (unsigned int i = 0; i < CHUNK_VOL; i++){ 6 | map[i] = 0x0000; 7 | } 8 | } 9 | 10 | Lightmap::~Lightmap(){ 11 | delete[] map; 12 | } 13 | -------------------------------------------------------------------------------- /src/lighting/Lightmap.h: -------------------------------------------------------------------------------- 1 | #ifndef LIGHTING_LIGHTMAP_H_ 2 | #define LIGHTING_LIGHTMAP_H_ 3 | 4 | #include "../voxels/Chunk.h" 5 | 6 | class Lightmap { 7 | public: 8 | unsigned short* map; 9 | Lightmap(); 10 | ~Lightmap(); 11 | 12 | inline unsigned char get(int x, int y, int z, int channel){ 13 | return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF; 14 | } 15 | 16 | inline unsigned char getR(int x, int y, int z){ 17 | return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF; 18 | } 19 | 20 | inline unsigned char getG(int x, int y, int z){ 21 | return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF; 22 | } 23 | 24 | inline unsigned char getB(int x, int y, int z){ 25 | return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF; 26 | } 27 | 28 | inline unsigned char getS(int x, int y, int z){ 29 | return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF; 30 | } 31 | 32 | inline void setR(int x, int y, int z, int value){ 33 | const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; 34 | map[index] = (map[index] & 0xFFF0) | value; 35 | } 36 | 37 | inline void setG(int x, int y, int z, int value){ 38 | const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; 39 | map[index] = (map[index] & 0xFF0F) | (value << 4); 40 | } 41 | 42 | inline void setB(int x, int y, int z, int value){ 43 | const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; 44 | map[index] = (map[index] & 0xF0FF) | (value << 8); 45 | } 46 | 47 | inline void setS(int x, int y, int z, int value){ 48 | const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; 49 | map[index] = (map[index] & 0x0FFF) | (value << 12); 50 | } 51 | 52 | inline void set(int x, int y, int z, int channel, int value){ 53 | const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; 54 | map[index] = (map[index] & (0xFFFF & (~(0xF << (channel*4))))) | (value << (channel << 2)); 55 | } 56 | }; 57 | 58 | #endif /* LIGHTING_LIGHTMAP_H_ */ 59 | -------------------------------------------------------------------------------- /src/loaders/png_loading.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * png_loading.cpp 3 | * 4 | * Created on: Feb 10, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #include "png_loading.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include "../graphics/Texture.h" 14 | 15 | int _png_load(const char* file, int* width, int* height){ 16 | FILE *f; 17 | int is_png, bit_depth, color_type, row_bytes; 18 | png_infop info_ptr, end_info; 19 | png_uint_32 t_width, t_height; 20 | png_byte header[8], *image_data; 21 | png_bytepp row_pointers; 22 | png_structp png_ptr; 23 | GLuint texture; 24 | int alpha; 25 | 26 | if ( !( f = fopen(file, "r" ) ) ) { 27 | return 0; 28 | } 29 | fread( header, 1, 8, f ); 30 | is_png = !png_sig_cmp( header, 0, 8 ); 31 | if ( !is_png ) { 32 | fclose( f ); 33 | return 0; 34 | } 35 | png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, 36 | NULL, NULL ); 37 | if ( !png_ptr ) { 38 | fclose( f ); 39 | return 0; 40 | } 41 | info_ptr = png_create_info_struct( png_ptr ); 42 | if ( !info_ptr ) { 43 | png_destroy_read_struct( &png_ptr, (png_infopp) NULL, 44 | (png_infopp) NULL ); 45 | fclose( f ); 46 | return 0; 47 | } 48 | end_info = png_create_info_struct( png_ptr ); 49 | if ( !end_info ) { 50 | png_destroy_read_struct( &png_ptr, (png_infopp) NULL, 51 | (png_infopp) NULL ); 52 | fclose( f ); 53 | return 0; 54 | } 55 | if ( setjmp( png_jmpbuf( png_ptr ) ) ) { 56 | png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); 57 | fclose( f ); 58 | return 0; 59 | } 60 | png_init_io( png_ptr, f ); 61 | png_set_sig_bytes( png_ptr, 8 ); 62 | png_read_info( png_ptr, info_ptr ); 63 | png_get_IHDR( png_ptr, info_ptr, &t_width, &t_height, &bit_depth, 64 | &color_type, NULL, NULL, NULL ); 65 | *width = t_width; 66 | *height = t_height; 67 | png_read_update_info( png_ptr, info_ptr ); 68 | row_bytes = png_get_rowbytes( png_ptr, info_ptr ); 69 | image_data = (png_bytep) malloc( row_bytes * t_height * sizeof(png_byte) ); 70 | if ( !image_data ) { 71 | png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); 72 | fclose( f ); 73 | return 0; 74 | } 75 | row_pointers = (png_bytepp) malloc( t_height * sizeof(png_bytep) ); 76 | if ( !row_pointers ) { 77 | png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); 78 | free( image_data ); 79 | fclose( f ); 80 | return 0; 81 | } 82 | for (unsigned int i = 0; i < t_height; ++i ) { 83 | row_pointers[t_height - 1 - i] = image_data + i * row_bytes; 84 | } 85 | png_read_image( png_ptr, row_pointers ); 86 | switch ( png_get_color_type( png_ptr, info_ptr ) ) { 87 | case PNG_COLOR_TYPE_RGBA: 88 | alpha = GL_RGBA; 89 | break; 90 | case PNG_COLOR_TYPE_RGB: 91 | alpha = GL_RGB; 92 | break; 93 | default: 94 | printf( "Color type %d not supported!\n", 95 | png_get_color_type( png_ptr, info_ptr ) ); 96 | png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); 97 | return 0; 98 | } 99 | glGenTextures(1, &texture); 100 | glBindTexture(GL_TEXTURE_2D, texture); 101 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 102 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t_width, t_height, 0, 103 | alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data); 104 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); 105 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4); 107 | glGenerateMipmap(GL_TEXTURE_2D); 108 | glBindTexture(GL_TEXTURE_2D, 0); 109 | 110 | png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); 111 | free( image_data ); 112 | free( row_pointers ); 113 | fclose( f ); 114 | return texture; 115 | } 116 | 117 | Texture* load_texture(std::string filename){ 118 | int width, height; 119 | GLuint texture = _png_load(filename.c_str(), &width, &height); 120 | if (texture == 0){ 121 | std::cerr << "Could not load texture " << filename << std::endl; 122 | return nullptr; 123 | } 124 | return new Texture(texture, width, height); 125 | } 126 | -------------------------------------------------------------------------------- /src/loaders/png_loading.h: -------------------------------------------------------------------------------- 1 | /* 2 | * png_loading.h 3 | * 4 | * Created on: Feb 10, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #ifndef LOADERS_PNG_LOADING_H_ 9 | #define LOADERS_PNG_LOADING_H_ 10 | 11 | #include 12 | 13 | class Texture; 14 | 15 | extern Texture* load_texture(std::string filename); 16 | 17 | #endif /* LOADERS_PNG_LOADING_H_ */ 18 | -------------------------------------------------------------------------------- /src/voxel_engine.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define GLEW_STATIC 4 | #include 5 | #include 6 | 7 | // GLM 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace glm; 13 | 14 | #include "graphics/Shader.h" 15 | #include "graphics/Texture.h" 16 | #include "graphics/Mesh.h" 17 | #include "graphics/VoxelRenderer.h" 18 | #include "graphics/LineBatch.h" 19 | #include "window/Window.h" 20 | #include "window/Events.h" 21 | #include "window/Camera.h" 22 | #include "loaders/png_loading.h" 23 | #include "voxels/voxel.h" 24 | #include "voxels/Chunk.h" 25 | #include "voxels/Chunks.h" 26 | #include "voxels/Block.h" 27 | #include "files/files.h" 28 | #include "lighting/LightSolver.h" 29 | #include "lighting/Lightmap.h" 30 | #include "lighting/Lighting.h" 31 | 32 | int WIDTH = 1280; 33 | int HEIGHT = 720; 34 | 35 | float vertices[] = { 36 | // x y 37 | -0.01f,-0.01f, 38 | 0.01f, 0.01f, 39 | 40 | -0.01f, 0.01f, 41 | 0.01f,-0.01f, 42 | }; 43 | 44 | int attrs[] = { 45 | 2, 0 //null terminator 46 | }; 47 | 48 | int main() { 49 | Window::initialize(WIDTH, HEIGHT, "Window 2.0"); 50 | Events::initialize(); 51 | 52 | Shader* shader = load_shader("res/main.glslv", "res/main.glslf"); 53 | if (shader == nullptr){ 54 | std::cerr << "failed to load shader" << std::endl; 55 | Window::terminate(); 56 | return 1; 57 | } 58 | 59 | Shader* crosshairShader = load_shader("res/crosshair.glslv", "res/crosshair.glslf"); 60 | if (crosshairShader == nullptr){ 61 | std::cerr << "failed to load crosshair shader" << std::endl; 62 | Window::terminate(); 63 | return 1; 64 | } 65 | 66 | Shader* linesShader = load_shader("res/lines.glslv", "res/lines.glslf"); 67 | if (linesShader == nullptr){ 68 | std::cerr << "failed to load lines shader" << std::endl; 69 | Window::terminate(); 70 | return 1; 71 | } 72 | 73 | Texture* texture = load_texture("res/block.png"); 74 | if (texture == nullptr){ 75 | std::cerr << "failed to load texture" << std::endl; 76 | delete shader; 77 | Window::terminate(); 78 | return 1; 79 | } 80 | 81 | { 82 | // AIR 83 | Block* block = new Block(0,0); 84 | block->drawGroup = 1; 85 | block->lightPassing = true; 86 | Block::blocks[block->id] = block; 87 | 88 | // STONE 89 | block = new Block(1,2); 90 | Block::blocks[block->id] = block; 91 | 92 | // GRASS 93 | block = new Block(2,4); 94 | block->textureFaces[2] = 2; 95 | block->textureFaces[3] = 1; 96 | Block::blocks[block->id] = block; 97 | 98 | // LAMP 99 | block = new Block(3,3); 100 | block->emission[0] = 10; 101 | block->emission[1] = 0; 102 | block->emission[2] = 0; 103 | Block::blocks[block->id] = block; 104 | 105 | // GLASS 106 | block = new Block(4,5); 107 | block->drawGroup = 2; 108 | block->lightPassing = true; 109 | Block::blocks[block->id] = block; 110 | 111 | // GLASS 112 | block = new Block(5,6); 113 | Block::blocks[block->id] = block; 114 | } 115 | 116 | Chunks* chunks = new Chunks(16,16,16); 117 | Mesh** meshes = new Mesh*[chunks->volume]; 118 | for (size_t i = 0; i < chunks->volume; i++) 119 | meshes[i] = nullptr; 120 | VoxelRenderer renderer(1024*1024*8); 121 | LineBatch* lineBatch = new LineBatch(4096); 122 | 123 | Lighting::initialize(chunks); 124 | 125 | glClearColor(0.0f,0.0f,0.0f,1); 126 | 127 | glEnable(GL_DEPTH_TEST); 128 | glEnable(GL_CULL_FACE); 129 | glEnable(GL_BLEND); 130 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 131 | 132 | Mesh* crosshair = new Mesh(vertices, 4, attrs); 133 | Camera* camera = new Camera(vec3(96,16,96), radians(90.0f)); 134 | 135 | float lastTime = glfwGetTime(); 136 | float delta = 0.0f; 137 | 138 | float camX = 0.0f; 139 | float camY = 0.0f; 140 | 141 | float speed = 15; 142 | 143 | int choosenBlock = 1; 144 | 145 | Lighting::onWorldLoaded(); 146 | 147 | while (!Window::isShouldClose()){ 148 | float currentTime = glfwGetTime(); 149 | delta = currentTime - lastTime; 150 | lastTime = currentTime; 151 | 152 | if (Events::jpressed(GLFW_KEY_ESCAPE)){ 153 | Window::setShouldClose(true); 154 | } 155 | if (Events::jpressed(GLFW_KEY_TAB)){ 156 | Events::toogleCursor(); 157 | } 158 | 159 | for (int i = 1; i < 6; i++){ 160 | if (Events::jpressed(GLFW_KEY_0+i)){ 161 | choosenBlock = i; 162 | } 163 | } 164 | if (Events::jpressed(GLFW_KEY_F1)){ 165 | unsigned char* buffer = new unsigned char[chunks->volume * CHUNK_VOL]; 166 | chunks->write(buffer); 167 | write_binary_file("world.bin", (const char*)buffer, chunks->volume * CHUNK_VOL); 168 | delete[] buffer; 169 | std::cout << "world saved in " << (chunks->volume * CHUNK_VOL) << " bytes" << std::endl; 170 | } 171 | if (Events::jpressed(GLFW_KEY_F2)){ 172 | unsigned char* buffer = new unsigned char[chunks->volume * CHUNK_VOL]; 173 | read_binary_file("world.bin", (char*)buffer, chunks->volume * CHUNK_VOL); 174 | chunks->read(buffer); 175 | delete[] buffer; 176 | 177 | Lighting::clear(); 178 | Lighting::onWorldLoaded(); 179 | } 180 | 181 | if (Events::pressed(GLFW_KEY_W)){ 182 | camera->position += camera->front * delta * speed; 183 | } 184 | if (Events::pressed(GLFW_KEY_S)){ 185 | camera->position -= camera->front * delta * speed; 186 | } 187 | if (Events::pressed(GLFW_KEY_D)){ 188 | camera->position += camera->right * delta * speed; 189 | } 190 | if (Events::pressed(GLFW_KEY_A)){ 191 | camera->position -= camera->right * delta * speed; 192 | } 193 | 194 | if (Events::_cursor_locked){ 195 | camY += -Events::deltaY / Window::height * 2; 196 | camX += -Events::deltaX / Window::height * 2; 197 | 198 | if (camY < -radians(89.0f)){ 199 | camY = -radians(89.0f); 200 | } 201 | if (camY > radians(89.0f)){ 202 | camY = radians(89.0f); 203 | } 204 | 205 | camera->rotation = mat4(1.0f); 206 | camera->rotate(camY, camX, 0); 207 | } 208 | 209 | { 210 | vec3 end; 211 | vec3 norm; 212 | vec3 iend; 213 | voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend); 214 | if (vox != nullptr){ 215 | lineBatch->box(iend.x+0.5f, iend.y+0.5f, iend.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f); 216 | 217 | if (Events::jclicked(GLFW_MOUSE_BUTTON_1)){ 218 | int x = (int)iend.x; 219 | int y = (int)iend.y; 220 | int z = (int)iend.z; 221 | chunks->set(x,y,z, 0); 222 | Lighting::onBlockSet(x,y,z,0); 223 | } 224 | if (Events::jclicked(GLFW_MOUSE_BUTTON_2)){ 225 | int x = (int)(iend.x)+(int)(norm.x); 226 | int y = (int)(iend.y)+(int)(norm.y); 227 | int z = (int)(iend.z)+(int)(norm.z); 228 | chunks->set(x, y, z, choosenBlock); 229 | Lighting::onBlockSet(x,y,z, choosenBlock); 230 | } 231 | } 232 | } 233 | 234 | Chunk* closes[27]; 235 | for (size_t i = 0; i < chunks->volume; i++){ 236 | Chunk* chunk = chunks->chunks[i]; 237 | if (!chunk->modified) 238 | continue; 239 | chunk->modified = false; 240 | if (meshes[i] != nullptr) 241 | delete meshes[i]; 242 | 243 | for (int i = 0; i < 27; i++) 244 | closes[i] = nullptr; 245 | for (size_t j = 0; j < chunks->volume; j++){ 246 | Chunk* other = chunks->chunks[j]; 247 | 248 | int ox = other->x - chunk->x; 249 | int oy = other->y - chunk->y; 250 | int oz = other->z - chunk->z; 251 | 252 | if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1) 253 | continue; 254 | 255 | ox += 1; 256 | oy += 1; 257 | oz += 1; 258 | closes[(oy * 3 + oz) * 3 + ox] = other; 259 | } 260 | Mesh* mesh = renderer.render(chunk, (const Chunk**)closes); 261 | meshes[i] = mesh; 262 | } 263 | 264 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 265 | 266 | // Draw VAO 267 | shader->use(); 268 | shader->uniformMatrix("projview", camera->getProjection()*camera->getView()); 269 | texture->bind(); 270 | mat4 model(1.0f); 271 | for (size_t i = 0; i < chunks->volume; i++){ 272 | Chunk* chunk = chunks->chunks[i]; 273 | Mesh* mesh = meshes[i]; 274 | model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W+0.5f, chunk->y*CHUNK_H+0.5f, chunk->z*CHUNK_D+0.5f)); 275 | shader->uniformMatrix("model", model); 276 | mesh->draw(GL_TRIANGLES); 277 | } 278 | 279 | crosshairShader->use(); 280 | crosshair->draw(GL_LINES); 281 | 282 | linesShader->use(); 283 | linesShader->uniformMatrix("projview", camera->getProjection()*camera->getView()); 284 | glLineWidth(2.0f); 285 | lineBatch->render(); 286 | 287 | Window::swapBuffers(); 288 | Events::pullEvents(); 289 | } 290 | 291 | Lighting::finalize(); 292 | 293 | delete shader; 294 | delete texture; 295 | delete chunks; 296 | delete crosshair; 297 | delete crosshairShader; 298 | delete linesShader; 299 | delete lineBatch; 300 | 301 | Window::terminate(); 302 | return 0; 303 | } 304 | -------------------------------------------------------------------------------- /src/voxels/Block.cpp: -------------------------------------------------------------------------------- 1 | #include "Block.h" 2 | 3 | Block* Block::blocks[256]; 4 | 5 | Block::Block(unsigned int id, int texture) : id(id), 6 | textureFaces{texture,texture,texture,texture,texture,texture}, 7 | emission{0,0,0}{ 8 | } 9 | -------------------------------------------------------------------------------- /src/voxels/Block.h: -------------------------------------------------------------------------------- 1 | #ifndef VOXELS_BLOCK_H_ 2 | #define VOXELS_BLOCK_H_ 3 | 4 | class Block { 5 | public: 6 | static Block* blocks[256]; 7 | 8 | const unsigned int id; 9 | // 0 1 2 3 4 5 10 | int textureFaces[6]; // -x,x, -y,y, -z,z 11 | unsigned char emission[3]; 12 | unsigned char drawGroup = 0; 13 | bool lightPassing = false; 14 | 15 | Block(unsigned int id, int texture); 16 | }; 17 | 18 | #endif /* VOXELS_BLOCK_H_ */ 19 | -------------------------------------------------------------------------------- /src/voxels/Chunk.cpp: -------------------------------------------------------------------------------- 1 | #include "Chunk.h" 2 | #include "voxel.h" 3 | #include "../lighting/Lightmap.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){ 9 | voxels = new voxel[CHUNK_VOL]; 10 | lightmap = new Lightmap(); 11 | 12 | for (int z = 0; z < CHUNK_D; z++){ 13 | for (int x = 0; x < CHUNK_W; x++){ 14 | int real_x = x + this->x * CHUNK_W; 15 | int real_z = z + this->z * CHUNK_D; 16 | //float height = glm::perlin(glm::vec3(real_x*0.0026125f,real_z*0.0026125f, 0.0f)); 17 | //height += glm::perlin(glm::vec3(real_x*0.006125f,real_z*0.006125f, 0.0f))*0.5f; 18 | for (int y = 0; y < CHUNK_H; y++){ 19 | int real_y = y + this->y * CHUNK_H; 20 | int id = glm::perlin(glm::vec3(real_x*0.0125f,real_y*0.0125f, real_z*0.0125f)) > 0.1f;//*/real_y <= (height) * 60 + 30; 21 | if (real_y <= 2) 22 | id = 2; 23 | //srand(real_x*62345+real_y*43634+real_z*742); 24 | //if (real_y > 10 && rand() % 3000 == 0) 25 | // id = 3; 26 | //if (real_x == 0 || real_x == 16*CHUNK_W-1) 27 | // id = 1; 28 | //if (real_z == 0 || real_z == 16*CHUNK_D-1) 29 | // id = 1; 30 | //if (real_y == 4*CHUNK_D-1) 31 | // id = 1; 32 | voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id; 33 | } 34 | } 35 | } 36 | } 37 | 38 | Chunk::~Chunk(){ 39 | delete lightmap; 40 | delete[] voxels; 41 | } 42 | -------------------------------------------------------------------------------- /src/voxels/Chunk.h: -------------------------------------------------------------------------------- 1 | #ifndef VOXELS_CHUNK_H_ 2 | #define VOXELS_CHUNK_H_ 3 | 4 | #define CHUNK_W 16 5 | #define CHUNK_H 16 6 | #define CHUNK_D 16 7 | #define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D) 8 | 9 | class voxel; 10 | class Lightmap; 11 | 12 | class Chunk { 13 | public: 14 | int x,y,z; 15 | voxel* voxels; 16 | Lightmap* lightmap; 17 | bool modified = true; 18 | Chunk(int x, int y, int z); 19 | ~Chunk(); 20 | }; 21 | 22 | #endif /* VOXELS_CHUNK_H_ */ 23 | -------------------------------------------------------------------------------- /src/voxels/Chunks.cpp: -------------------------------------------------------------------------------- 1 | #include "Chunks.h" 2 | #include "Chunk.h" 3 | #include "voxel.h" 4 | #include "../lighting/Lightmap.h" 5 | 6 | #include 7 | 8 | using namespace glm; 9 | 10 | #include 11 | #include 12 | 13 | Chunks::Chunks(int w, int h, int d) : w(w), h(h), d(d){ 14 | volume = w*h*d; 15 | chunks = new Chunk*[volume]; 16 | 17 | int index = 0; 18 | for (int y = 0; y < h; y++){ 19 | for (int z = 0; z < d; z++){ 20 | for (int x = 0; x < w; x++, index++){ 21 | Chunk* chunk = new Chunk(x,y,z); 22 | chunks[index] = chunk; 23 | } 24 | } 25 | } 26 | } 27 | 28 | Chunks::~Chunks(){ 29 | for (size_t i = 0; i < volume; i++){ 30 | delete chunks[i]; 31 | } 32 | delete[] chunks; 33 | } 34 | 35 | voxel* Chunks::get(int x, int y, int z){ 36 | int cx = x / CHUNK_W; 37 | int cy = y / CHUNK_H; 38 | int cz = z / CHUNK_D; 39 | if (x < 0) cx--; 40 | if (y < 0) cy--; 41 | if (z < 0) cz--; 42 | if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) 43 | return nullptr; 44 | Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 45 | int lx = x - cx * CHUNK_W; 46 | int ly = y - cy * CHUNK_H; 47 | int lz = z - cz * CHUNK_D; 48 | return &chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx]; 49 | } 50 | 51 | unsigned char Chunks::getLight(int x, int y, int z, int channel){ 52 | int cx = x / CHUNK_W; 53 | int cy = y / CHUNK_H; 54 | int cz = z / CHUNK_D; 55 | if (x < 0) cx--; 56 | if (y < 0) cy--; 57 | if (z < 0) cz--; 58 | if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) 59 | return 0; 60 | Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 61 | int lx = x - cx * CHUNK_W; 62 | int ly = y - cy * CHUNK_H; 63 | int lz = z - cz * CHUNK_D; 64 | return chunk->lightmap->get(lx,ly,lz, channel); 65 | } 66 | 67 | Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ 68 | int cx = x / CHUNK_W; 69 | int cy = y / CHUNK_H; 70 | int cz = z / CHUNK_D; 71 | if (x < 0) cx--; 72 | if (y < 0) cy--; 73 | if (z < 0) cz--; 74 | if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) 75 | return nullptr; 76 | return chunks[(cy * d + cz) * w + cx]; 77 | } 78 | 79 | Chunk* Chunks::getChunk(int x, int y, int z){ 80 | if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d) 81 | return nullptr; 82 | return chunks[(y * d + z) * w + x]; 83 | } 84 | 85 | void Chunks::set(int x, int y, int z, int id){ 86 | int cx = x / CHUNK_W; 87 | int cy = y / CHUNK_H; 88 | int cz = z / CHUNK_D; 89 | if (x < 0) cx--; 90 | if (y < 0) cy--; 91 | if (z < 0) cz--; 92 | if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) 93 | return; 94 | Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 95 | int lx = x - cx * CHUNK_W; 96 | int ly = y - cy * CHUNK_H; 97 | int lz = z - cz * CHUNK_D; 98 | chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx].id = id; 99 | chunk->modified = true; 100 | 101 | if (lx == 0 && (chunk = getChunk(cx-1, cy, cz))) chunk->modified = true; 102 | if (ly == 0 && (chunk = getChunk(cx, cy-1, cz))) chunk->modified = true; 103 | if (lz == 0 && (chunk = getChunk(cx, cy, cz-1))) chunk->modified = true; 104 | 105 | if (lx == CHUNK_W-1 && (chunk = getChunk(cx+1, cy, cz))) chunk->modified = true; 106 | if (ly == CHUNK_H-1 && (chunk = getChunk(cx, cy+1, cz))) chunk->modified = true; 107 | if (lz == CHUNK_D-1 && (chunk = getChunk(cx, cy, cz+1))) chunk->modified = true; 108 | } 109 | 110 | voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, vec3& iend) { 111 | float px = a.x; 112 | float py = a.y; 113 | float pz = a.z; 114 | 115 | float dx = dir.x; 116 | float dy = dir.y; 117 | float dz = dir.z; 118 | 119 | float t = 0.0f; 120 | int ix = floor(px); 121 | int iy = floor(py); 122 | int iz = floor(pz); 123 | 124 | float stepx = (dx > 0.0f) ? 1.0f : -1.0f; 125 | float stepy = (dy > 0.0f) ? 1.0f : -1.0f; 126 | float stepz = (dz > 0.0f) ? 1.0f : -1.0f; 127 | 128 | float infinity = std::numeric_limits::infinity(); 129 | 130 | float txDelta = (dx == 0.0f) ? infinity : abs(1.0f / dx); 131 | float tyDelta = (dy == 0.0f) ? infinity : abs(1.0f / dy); 132 | float tzDelta = (dz == 0.0f) ? infinity : abs(1.0f / dz); 133 | 134 | float xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix); 135 | float ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy); 136 | float zdist = (stepz > 0) ? (iz + 1 - pz) : (pz - iz); 137 | 138 | float txMax = (txDelta < infinity) ? txDelta * xdist : infinity; 139 | float tyMax = (tyDelta < infinity) ? tyDelta * ydist : infinity; 140 | float tzMax = (tzDelta < infinity) ? tzDelta * zdist : infinity; 141 | 142 | int steppedIndex = -1; 143 | 144 | while (t <= maxDist){ 145 | voxel* voxel = get(ix, iy, iz); 146 | if (voxel == nullptr || voxel->id){ 147 | end.x = px + t * dx; 148 | end.y = py + t * dy; 149 | end.z = pz + t * dz; 150 | 151 | iend.x = ix; 152 | iend.y = iy; 153 | iend.z = iz; 154 | 155 | norm.x = norm.y = norm.z = 0.0f; 156 | if (steppedIndex == 0) norm.x = -stepx; 157 | if (steppedIndex == 1) norm.y = -stepy; 158 | if (steppedIndex == 2) norm.z = -stepz; 159 | return voxel; 160 | } 161 | if (txMax < tyMax) { 162 | if (txMax < tzMax) { 163 | ix += stepx; 164 | t = txMax; 165 | txMax += txDelta; 166 | steppedIndex = 0; 167 | } else { 168 | iz += stepz; 169 | t = tzMax; 170 | tzMax += tzDelta; 171 | steppedIndex = 2; 172 | } 173 | } else { 174 | if (tyMax < tzMax) { 175 | iy += stepy; 176 | t = tyMax; 177 | tyMax += tyDelta; 178 | steppedIndex = 1; 179 | } else { 180 | iz += stepz; 181 | t = tzMax; 182 | tzMax += tzDelta; 183 | steppedIndex = 2; 184 | } 185 | } 186 | } 187 | iend.x = ix; 188 | iend.y = iy; 189 | iend.z = iz; 190 | 191 | end.x = px + t * dx; 192 | end.y = py + t * dy; 193 | end.z = pz + t * dz; 194 | norm.x = norm.y = norm.z = 0.0f; 195 | return nullptr; 196 | } 197 | 198 | void Chunks::write(unsigned char* dest) { 199 | size_t index = 0; 200 | for (size_t i = 0; i < volume; i++){ 201 | Chunk* chunk = chunks[i]; 202 | for (size_t j = 0; j < CHUNK_VOL; j++, index++){ 203 | dest[index] = chunk->voxels[j].id; 204 | } 205 | } 206 | } 207 | 208 | void Chunks::read(unsigned char* source) { 209 | size_t index = 0; 210 | for (size_t i = 0; i < volume; i++){ 211 | Chunk* chunk = chunks[i]; 212 | for (size_t j = 0; j < CHUNK_VOL; j++, index++){ 213 | chunk->voxels[j].id = source[index]; 214 | } 215 | chunk->modified = true; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/voxels/Chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef VOXELS_CHUNKS_H_ 2 | #define VOXELS_CHUNKS_H_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace glm; 8 | 9 | class Chunk; 10 | class voxel; 11 | 12 | class Chunks { 13 | public: 14 | Chunk** chunks; 15 | size_t volume; 16 | unsigned int w,h,d; 17 | 18 | Chunks(int w, int h, int d); 19 | ~Chunks(); 20 | 21 | Chunk* getChunk(int x, int y, int z); 22 | Chunk* getChunkByVoxel(int x, int y, int z); 23 | voxel* get(int x, int y, int z); 24 | unsigned char getLight(int x, int y, int z, int channel); 25 | void set(int x, int y, int z, int id); 26 | voxel* rayCast(vec3 start, vec3 dir, float maxLength, vec3& end, vec3& norm, vec3& iend); 27 | 28 | void write(unsigned char* dest); 29 | void read(unsigned char* source); 30 | }; 31 | 32 | #endif /* VOXELS_CHUNKS_H_ */ 33 | -------------------------------------------------------------------------------- /src/voxels/voxel.cpp: -------------------------------------------------------------------------------- 1 | #include "voxel.h" 2 | 3 | -------------------------------------------------------------------------------- /src/voxels/voxel.h: -------------------------------------------------------------------------------- 1 | #ifndef VOXELS_VOXEL_H_ 2 | #define VOXELS_VOXEL_H_ 3 | 4 | #include 5 | 6 | struct voxel { 7 | uint8_t id; 8 | }; 9 | 10 | #endif /* VOXELS_VOXEL_H_ */ 11 | -------------------------------------------------------------------------------- /src/window/Camera.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Camera.cpp 3 | * 4 | * Created on: Feb 11, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #include "Camera.h" 9 | #include "Window.h" 10 | 11 | #include 12 | 13 | Camera::Camera(vec3 position, float fov) : position(position), fov(fov), rotation(1.0f) { 14 | updateVectors(); 15 | } 16 | 17 | void Camera::updateVectors(){ 18 | front = vec3(rotation * vec4(0,0,-1,1)); 19 | right = vec3(rotation * vec4(1,0,0,1)); 20 | up = vec3(rotation * vec4(0,1,0,1)); 21 | } 22 | 23 | void Camera::rotate(float x, float y, float z){ 24 | rotation = glm::rotate(rotation, z, vec3(0,0,1)); 25 | rotation = glm::rotate(rotation, y, vec3(0,1,0)); 26 | rotation = glm::rotate(rotation, x, vec3(1,0,0)); 27 | 28 | updateVectors(); 29 | } 30 | 31 | mat4 Camera::getProjection(){ 32 | float aspect = (float)Window::width / (float)Window::height; 33 | return glm::perspective(fov, aspect, 0.1f, 1500.0f); 34 | } 35 | 36 | mat4 Camera::getView(){ 37 | return glm::lookAt(position, position+front, up); 38 | } 39 | -------------------------------------------------------------------------------- /src/window/Camera.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Camera.h 3 | * 4 | * Created on: Feb 11, 2020 5 | * Author: MihailRis 6 | */ 7 | 8 | #ifndef WINDOW_CAMERA_H_ 9 | #define WINDOW_CAMERA_H_ 10 | 11 | #include 12 | using namespace glm; 13 | 14 | class Camera { 15 | void updateVectors(); 16 | public: 17 | vec3 front; 18 | vec3 up; 19 | vec3 right; 20 | 21 | vec3 position; 22 | float fov; 23 | mat4 rotation; 24 | Camera(vec3 position, float fov); 25 | 26 | void rotate(float x, float y, float z); 27 | 28 | mat4 getProjection(); 29 | mat4 getView(); 30 | }; 31 | 32 | #endif /* WINDOW_CAMERA_H_ */ 33 | -------------------------------------------------------------------------------- /src/window/Events.cpp: -------------------------------------------------------------------------------- 1 | #include "Events.h" 2 | #include 3 | #include 4 | #include 5 | 6 | bool* Events::_keys; 7 | uint* Events::_frames; 8 | uint Events::_current = 0; 9 | float Events::deltaX = 0.0f; 10 | float Events::deltaY = 0.0f; 11 | float Events::x = 0.0f; 12 | float Events::y = 0.0f; 13 | bool Events::_cursor_locked = false; 14 | bool Events::_cursor_started = false; 15 | 16 | #define _MOUSE_BUTTONS 1024 17 | 18 | void cursor_position_callback(GLFWwindow* window, double xpos, double ypos){ 19 | if (Events::_cursor_started){ 20 | Events::deltaX += xpos-Events::x; 21 | Events::deltaY += ypos-Events::y; 22 | } 23 | else { 24 | Events::_cursor_started = true; 25 | } 26 | Events::x = xpos; 27 | Events::y = ypos; 28 | } 29 | 30 | void mouse_button_callback(GLFWwindow* window, int button, int action, int mode){ 31 | if (action == GLFW_PRESS){ 32 | Events::_keys[_MOUSE_BUTTONS+button] = true; 33 | Events::_frames[_MOUSE_BUTTONS+button] = Events::_current; 34 | } 35 | else if (action == GLFW_RELEASE){ 36 | Events::_keys[_MOUSE_BUTTONS+button] = false; 37 | Events::_frames[_MOUSE_BUTTONS+button] = Events::_current; 38 | } 39 | } 40 | 41 | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { 42 | if (action == GLFW_PRESS){ 43 | Events::_keys[key] = true; 44 | Events::_frames[key] = Events::_current; 45 | } 46 | else if (action == GLFW_RELEASE){ 47 | Events::_keys[key] = false; 48 | Events::_frames[key] = Events::_current; 49 | } 50 | } 51 | 52 | void window_size_callback(GLFWwindow* window, int width, int height){ 53 | glViewport(0,0, width, height); 54 | Window::width = width; 55 | Window::height = height; 56 | } 57 | 58 | int Events::initialize(){ 59 | GLFWwindow* window = Window::window; 60 | _keys = new bool[1032]; 61 | _frames = new uint[1032]; 62 | 63 | memset(_keys, false, 1032*sizeof(bool)); 64 | memset(_frames, 0, 1032*sizeof(uint)); 65 | 66 | glfwSetKeyCallback(window, key_callback); 67 | glfwSetMouseButtonCallback(window, mouse_button_callback); 68 | glfwSetCursorPosCallback(window, cursor_position_callback); 69 | glfwSetWindowSizeCallback(window, window_size_callback); 70 | return 0; 71 | } 72 | 73 | bool Events::pressed(int keycode){ 74 | if (keycode < 0 || keycode >= _MOUSE_BUTTONS) 75 | return false; 76 | return _keys[keycode]; 77 | } 78 | 79 | bool Events::jpressed(int keycode){ 80 | if (keycode < 0 || keycode >= _MOUSE_BUTTONS) 81 | return false; 82 | return _keys[keycode] && _frames[keycode] == _current; 83 | } 84 | 85 | bool Events::clicked(int button){ 86 | int index = _MOUSE_BUTTONS+button; 87 | return _keys[index]; 88 | } 89 | 90 | bool Events::jclicked(int button){ 91 | int index = _MOUSE_BUTTONS+button; 92 | return _keys[index] && _frames[index] == _current; 93 | } 94 | 95 | void Events::toogleCursor(){ 96 | _cursor_locked = !_cursor_locked; 97 | Window::setCursorMode(_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL); 98 | } 99 | 100 | void Events::pullEvents(){ 101 | _current++; 102 | deltaX = 0.0f; 103 | deltaY = 0.0f; 104 | glfwPollEvents(); 105 | } 106 | -------------------------------------------------------------------------------- /src/window/Events.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_EVENTS_H_ 2 | #define WINDOW_EVENTS_H_ 3 | 4 | #include "Window.h" 5 | 6 | typedef unsigned int uint; 7 | 8 | class Events { 9 | public: 10 | static bool* _keys; 11 | static uint* _frames; 12 | static uint _current; 13 | static float deltaX; 14 | static float deltaY; 15 | static float x; 16 | static float y; 17 | static bool _cursor_locked; 18 | static bool _cursor_started; 19 | 20 | static int initialize(); 21 | static void pullEvents(); 22 | 23 | static bool pressed(int keycode); 24 | static bool jpressed(int keycode); 25 | 26 | static bool clicked(int button); 27 | static bool jclicked(int button); 28 | 29 | static void toogleCursor(); 30 | }; 31 | 32 | #endif /* WINDOW_EVENTS_H_ */ 33 | -------------------------------------------------------------------------------- /src/window/Window.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Window.h" 5 | 6 | GLFWwindow* Window::window; 7 | int Window::width = 0; 8 | int Window::height = 0; 9 | 10 | int Window::initialize(int width, int height, const char* title){ 11 | glfwInit(); 12 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 13 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 14 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 15 | glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); 16 | //glfwWindowHint(GLFW_SAMPLES, 2); 17 | 18 | window = glfwCreateWindow(width, height, title, nullptr, nullptr); 19 | if (window == nullptr){ 20 | std::cerr << "Failed to create GLFW Window" << std::endl; 21 | glfwTerminate(); 22 | return -1; 23 | } 24 | glfwMakeContextCurrent(window); 25 | 26 | glewExperimental = GL_TRUE; 27 | if (glewInit() != GLEW_OK){ 28 | std::cerr << "Failed to initialize GLEW" << std::endl; 29 | return -1; 30 | } 31 | glViewport(0,0, width, height); 32 | 33 | Window::width = width; 34 | Window::height = height; 35 | return 0; 36 | } 37 | 38 | void Window::setCursorMode(int mode){ 39 | glfwSetInputMode(window, GLFW_CURSOR, mode); 40 | } 41 | 42 | void Window::terminate(){ 43 | glfwTerminate(); 44 | } 45 | 46 | bool Window::isShouldClose(){ 47 | return glfwWindowShouldClose(window); 48 | } 49 | 50 | void Window::setShouldClose(bool flag){ 51 | glfwSetWindowShouldClose(window, flag); 52 | } 53 | 54 | void Window::swapBuffers(){ 55 | glfwSwapBuffers(window); 56 | } 57 | -------------------------------------------------------------------------------- /src/window/Window.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_WINDOW_H_ 2 | #define WINDOW_WINDOW_H_ 3 | 4 | class GLFWwindow; 5 | 6 | class Window { 7 | public: 8 | static int width; 9 | static int height; 10 | static GLFWwindow* window; // не лучшее решение делать window публичным 11 | static int initialize(int width, int height, const char* title); 12 | static void terminate(); 13 | 14 | static void setCursorMode(int mode); 15 | static bool isShouldClose(); 16 | static void setShouldClose(bool flag); 17 | static void swapBuffers(); 18 | }; 19 | 20 | #endif /* WINDOW_WINDOW_H_ */ 21 | --------------------------------------------------------------------------------