Add files via upload
This commit is contained in:
commit
e1cdcf01e9
BIN
res/block.png
Normal file
BIN
res/block.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
7
res/crosshair.glslf
Normal file
7
res/crosshair.glslf
Normal file
@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 f_color;
|
||||
|
||||
void main(){
|
||||
f_color = vec4(1.0);
|
||||
}
|
||||
7
res/crosshair.glslv
Normal file
7
res/crosshair.glslv
Normal file
@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec2 v_position;
|
||||
|
||||
void main(){
|
||||
gl_Position = vec4(v_position, 0.0, 1.0);
|
||||
}
|
||||
BIN
res/img.png
Normal file
BIN
res/img.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 342 B |
8
res/lines.glslf
Normal file
8
res/lines.glslf
Normal file
@ -0,0 +1,8 @@
|
||||
#version 330 core
|
||||
|
||||
in vec4 v_color;
|
||||
out vec4 f_color;
|
||||
|
||||
void main(){
|
||||
f_color = v_color;
|
||||
}
|
||||
13
res/lines.glslv
Normal file
13
res/lines.glslv
Normal file
@ -0,0 +1,13 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 a_position;
|
||||
layout (location = 1) in vec4 a_color;
|
||||
|
||||
out vec4 v_color;
|
||||
|
||||
uniform mat4 projview;
|
||||
|
||||
void main(){
|
||||
v_color = a_color;
|
||||
gl_Position = projview * vec4(a_position, 1.0);
|
||||
}
|
||||
14
res/main.glslf
Normal file
14
res/main.glslf
Normal file
@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
|
||||
in vec4 a_color;
|
||||
in vec2 a_texCoord;
|
||||
out vec4 f_color;
|
||||
|
||||
uniform sampler2D u_texture0;
|
||||
|
||||
void main(){
|
||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||
if (tex_color.a < 0.5)
|
||||
discard;
|
||||
f_color = a_color * tex_color;
|
||||
}
|
||||
21
res/main.glslv
Normal file
21
res/main.glslv
Normal file
@ -0,0 +1,21 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 v_position;
|
||||
layout (location = 1) in vec2 v_texCoord;
|
||||
layout (location = 2) in vec4 v_light;
|
||||
|
||||
out vec4 a_color;
|
||||
out vec2 a_texCoord;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 projview;
|
||||
|
||||
void main(){
|
||||
vec4 position = projview * model * vec4(v_position, 1.0);
|
||||
a_color = vec4(v_light.r,v_light.g,v_light.b,1.0f);
|
||||
a_texCoord = v_texCoord;
|
||||
a_color.rgb += v_light.a;
|
||||
a_color.rgb *= 1.0-position.z*0.0025;
|
||||
//a_color.rgb = pow(a_color.rgb, vec3(1.0/0.7));
|
||||
gl_Position = position;
|
||||
}
|
||||
10
res/screen.glslf
Normal file
10
res/screen.glslf
Normal file
@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 v_coord;
|
||||
out vec4 f_color;
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
void main(){
|
||||
f_color = texture(u_texture, v_coord);
|
||||
}
|
||||
10
res/screen.glslv
Normal file
10
res/screen.glslv
Normal file
@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec2 v_position;
|
||||
|
||||
out vec2 v_coord;
|
||||
|
||||
void main(){
|
||||
v_coord = v_position*0.5+0.5;
|
||||
gl_Position = vec4(v_position, 0.0, 1.0);
|
||||
}
|
||||
198
src/files/WorldFiles.cpp
Normal file
198
src/files/WorldFiles.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include "WorldFiles.h"
|
||||
|
||||
#include "files.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
|
||||
union {
|
||||
long _key;
|
||||
int _coords[2];
|
||||
} _tempcoords;
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
int bytes2Int(const unsigned char* src, unsigned int offset){
|
||||
return (src[offset] << 24) | (src[offset+1] << 16) | (src[offset+2] << 8) | (src[offset+3]);
|
||||
}
|
||||
|
||||
void int2Bytes(int value, char* dest, unsigned int offset){
|
||||
dest[offset] = (char) (value >> 24 & 255);
|
||||
dest[offset+1] = (char) (value >> 16 & 255);
|
||||
dest[offset+2] = (char) (value >> 8 & 255);
|
||||
dest[offset+3] = (char) (value >> 0 & 255);
|
||||
}
|
||||
|
||||
WorldFiles::WorldFiles(const char* directory, size_t mainBufferCapacity) : directory(directory){
|
||||
mainBuffer = new char[mainBufferCapacity];
|
||||
}
|
||||
|
||||
WorldFiles::~WorldFiles(){
|
||||
delete[] mainBuffer;
|
||||
std::unordered_map<long, char**>::iterator it;
|
||||
for (it = regions.begin(); it != regions.end(); it++){
|
||||
char** region = it->second;
|
||||
if (region == nullptr)
|
||||
continue;
|
||||
for (unsigned int i = 0; i < REGION_VOL; i++){
|
||||
delete[] region[i];
|
||||
}
|
||||
delete[] region;
|
||||
}
|
||||
regions.clear();
|
||||
}
|
||||
|
||||
void WorldFiles::put(const char* chunkData, int x, int y){
|
||||
assert(chunkData != nullptr);
|
||||
|
||||
int regionX = x >> REGION_SIZE_BIT;
|
||||
int regionY = y >> REGION_SIZE_BIT;
|
||||
|
||||
int localX = x - (regionX << REGION_SIZE_BIT);
|
||||
int localY = y - (regionY << REGION_SIZE_BIT);
|
||||
|
||||
_tempcoords._coords[0] = regionX;
|
||||
_tempcoords._coords[1] = regionY;
|
||||
char** region = regions[_tempcoords._key];
|
||||
if (region == nullptr){
|
||||
region = new char*[REGION_VOL];
|
||||
for (unsigned int i = 0; i < REGION_VOL; i++)
|
||||
region[i] = nullptr;
|
||||
regions[_tempcoords._key] = region;
|
||||
}
|
||||
char* targetChunk = region[localY * REGION_SIZE + localX];
|
||||
if (targetChunk == nullptr){
|
||||
targetChunk = new char[CHUNK_VOL];
|
||||
region[localY * REGION_SIZE + localX] = targetChunk;
|
||||
}
|
||||
for (unsigned int i = 0; i < CHUNK_VOL; i++)
|
||||
targetChunk[i] = chunkData[i];
|
||||
}
|
||||
|
||||
std::string WorldFiles::getRegionFile(int x, int y) {
|
||||
return directory + std::to_string(x) + "_" + std::to_string(y) + ".bin";
|
||||
}
|
||||
|
||||
bool WorldFiles::getChunk(int x, int y, char* out){
|
||||
assert(out != nullptr);
|
||||
|
||||
int regionX = x >> REGION_SIZE_BIT;
|
||||
int regionY = y >> REGION_SIZE_BIT;
|
||||
|
||||
int localX = x - (regionX << REGION_SIZE_BIT);
|
||||
int localY = y - (regionY << REGION_SIZE_BIT);
|
||||
int chunkIndex = localY * REGION_SIZE + localX;
|
||||
assert(chunkIndex >= 0 && chunkIndex < REGION_VOL);
|
||||
|
||||
_tempcoords._coords[0] = regionX;
|
||||
_tempcoords._coords[1] = regionY;
|
||||
|
||||
char** region = regions[_tempcoords._key];
|
||||
if (region == nullptr)
|
||||
return readChunk(x,y,out);
|
||||
|
||||
char* chunk = region[chunkIndex];
|
||||
if (chunk == nullptr)
|
||||
return readChunk(x,y,out);
|
||||
for (unsigned int i = 0; i < CHUNK_VOL; i++)
|
||||
out[i] = chunk[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldFiles::readChunk(int x, int y, char* out){
|
||||
assert(out != nullptr);
|
||||
|
||||
int regionX = x >> REGION_SIZE_BIT;
|
||||
int regionY = y >> REGION_SIZE_BIT;
|
||||
|
||||
int localX = x - (regionX << REGION_SIZE_BIT);
|
||||
int localY = y - (regionY << REGION_SIZE_BIT);
|
||||
int chunkIndex = localY * REGION_SIZE + localX;
|
||||
|
||||
std::string filename = getRegionFile(regionX, regionY);
|
||||
|
||||
std::ifstream input(filename, std::ios::binary);
|
||||
if (!input.is_open()){
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t offset;
|
||||
input.seekg(chunkIndex*4);
|
||||
input.read((char*)(&offset), 4);
|
||||
// Ordering bytes from big-endian to machine order (any, just reading)
|
||||
offset = bytes2Int((const unsigned char*)(&offset), 0);
|
||||
if (offset == 0){
|
||||
input.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
input.seekg(offset);
|
||||
input.read((char*)(&offset), 4);
|
||||
size_t compressedSize = bytes2Int((const unsigned char*)(&offset), 0);
|
||||
|
||||
input.read(mainBuffer, compressedSize);
|
||||
input.close();
|
||||
|
||||
decompressRLE(mainBuffer, compressedSize, out, CHUNK_VOL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldFiles::write(){
|
||||
std::unordered_map<long, char**>::iterator it;
|
||||
for (it = regions.begin(); it != regions.end(); it++){
|
||||
if (it->second == nullptr)
|
||||
continue;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
longToCoords(x,y, it->first);
|
||||
|
||||
unsigned int size = writeRegion(mainBuffer, x,y, it->second);
|
||||
write_binary_file(getRegionFile(x,y), mainBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int WorldFiles::writeRegion(char* out, int x, int y, char** region){
|
||||
unsigned int offset = REGION_VOL * 4;
|
||||
for (unsigned int i = 0; i < offset; i++)
|
||||
out[i] = 0;
|
||||
|
||||
char* compressed = new char[CHUNK_VOL*2];
|
||||
for (int i = 0; i < REGION_VOL; i++){
|
||||
char* chunk = region[i];
|
||||
if (chunk == nullptr){
|
||||
chunk = new char[CHUNK_VOL];
|
||||
if (readChunk((i % REGION_SIZE) + x * REGION_SIZE, (i / REGION_SIZE) + y * REGION_SIZE, chunk)){
|
||||
region[i] = chunk;
|
||||
} else {
|
||||
delete[] chunk;
|
||||
chunk = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk == nullptr){
|
||||
int2Bytes(0, out, i*4);
|
||||
} else {
|
||||
int2Bytes(offset, out, i*4);
|
||||
|
||||
unsigned int compressedSize = compressRLE(chunk, CHUNK_VOL, compressed);
|
||||
|
||||
int2Bytes(compressedSize, out, offset);
|
||||
offset += 4;
|
||||
|
||||
for (unsigned int j = 0; j < compressedSize; j++)
|
||||
out[offset++] = compressed[j];
|
||||
}
|
||||
}
|
||||
delete[] compressed;
|
||||
return offset;
|
||||
}
|
||||
|
||||
void longToCoords(int& x, int& y, long key) {
|
||||
_tempcoords._key = key;
|
||||
x = _tempcoords._coords[0];
|
||||
y = _tempcoords._coords[1];
|
||||
}
|
||||
38
src/files/WorldFiles.h
Normal file
38
src/files/WorldFiles.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef FILES_WORLDFILES_H_
|
||||
#define FILES_WORLDFILES_H_
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#define REGION_SIZE_BIT 5
|
||||
#define REGION_SIZE (1 << (REGION_SIZE_BIT))
|
||||
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
||||
|
||||
/* Требование:
|
||||
* - высота мира = 1 чанк (любых размеров)
|
||||
* Пример:
|
||||
* - CHUNK_W = 16, CHUNK_H = 128, CHUNK_D = 16
|
||||
* */
|
||||
class WorldFiles {
|
||||
public:
|
||||
std::unordered_map<long, char**> regions;
|
||||
std::string directory;
|
||||
char* mainBuffer;
|
||||
|
||||
WorldFiles(const char* directory, size_t mainBufferCapacity);
|
||||
~WorldFiles();
|
||||
|
||||
void put(const char* chunkData, int x, int y);
|
||||
|
||||
bool readChunk(int x, int y, char* out);
|
||||
bool getChunk(int x, int y, char* out);
|
||||
void readRegion(char* fileContent);
|
||||
unsigned int writeRegion(char* out, int x, int y, char** region);
|
||||
void write();
|
||||
|
||||
std::string getRegionFile(int x, int y);
|
||||
};
|
||||
|
||||
extern void longToCoords(int& x, int& y, long key);
|
||||
|
||||
#endif /* FILES_WORLDFILES_H_ */
|
||||
100
src/files/files.cpp
Normal file
100
src/files/files.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include "files.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
bool write_binary_file_part(std::string filename, const char* data, size_t offset, size_t size){
|
||||
std::ofstream output(filename, std::ios::out | std::ios::binary | std::ios::in);
|
||||
if (!output.is_open())
|
||||
return false;
|
||||
output.seekp(offset);
|
||||
output.write(data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_binary_file(std::string filename, const char* data, size_t size) {
|
||||
std::ofstream output(filename, std::ios::binary);
|
||||
if (!output.is_open())
|
||||
return false;
|
||||
output.write(data, size);
|
||||
output.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int append_binary_file(std::string filename, const char* data, size_t size) {
|
||||
std::ofstream output(filename, std::ios::binary | std::ios::app);
|
||||
if (!output.is_open())
|
||||
return 0;
|
||||
unsigned int position = output.tellp();
|
||||
output.write(data, size);
|
||||
output.close();
|
||||
return position;
|
||||
}
|
||||
|
||||
bool read_binary_file(std::string filename, char* data, size_t size) {
|
||||
std::ifstream output(filename, std::ios::binary);
|
||||
if (!output.is_open())
|
||||
return false;
|
||||
output.read(data, size);
|
||||
output.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_binary_file(std::string filename, char* data, size_t offset, size_t size) {
|
||||
std::ifstream input(filename, std::ios::binary);
|
||||
if (!input.is_open())
|
||||
return false;
|
||||
input.seekg(offset);
|
||||
input.read(data, size);
|
||||
input.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns decompressed length
|
||||
unsigned int decompressRLE(const char* src, unsigned int length, char* dst, unsigned int targetLength){
|
||||
unsigned int offset = 0;
|
||||
for (unsigned int i = 0; i < length;){
|
||||
unsigned char counter = src[i++];
|
||||
char c = src[i++];
|
||||
for (unsigned int j = 0; j <= counter; j++){
|
||||
dst[offset++] = c;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
unsigned int calcRLE(const char* src, unsigned int length) {
|
||||
unsigned int offset = 0;
|
||||
unsigned int counter = 1;
|
||||
char c = src[0];
|
||||
for (unsigned int i = 0; i < length; i++){
|
||||
char cnext = src[i];
|
||||
if (cnext != c || counter == 256){
|
||||
offset += 2;
|
||||
c = cnext;
|
||||
counter = 0;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
// max result size = length * 2; returns compressed length
|
||||
unsigned int compressRLE(const char* src, unsigned int length, char* dst) {
|
||||
unsigned int offset = 0;
|
||||
unsigned int counter = 1;
|
||||
char c = src[0];
|
||||
for (unsigned int i = 1; i < length; i++){
|
||||
char cnext = src[i];
|
||||
if (cnext != c || counter == 256){
|
||||
dst[offset++] = counter-1;
|
||||
dst[offset++] = c;
|
||||
c = cnext;
|
||||
counter = 0;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
dst[offset++] = counter-1;
|
||||
dst[offset++] = c;
|
||||
return offset;
|
||||
}
|
||||
15
src/files/files.h
Normal file
15
src/files/files.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef FILES_FILES_H_
|
||||
#define FILES_FILES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
extern bool write_binary_file(std::string filename, const char* data, size_t size);
|
||||
extern unsigned int append_binary_file(std::string filename, const char* data, size_t size);
|
||||
extern bool read_binary_file(std::string filename, char* data, size_t size);
|
||||
extern bool read_binary_file(std::string filename, char* data, size_t offset, size_t size);
|
||||
|
||||
extern unsigned int calcRLE(const char* src, unsigned int length);
|
||||
extern unsigned int compressRLE(const char* src, unsigned int length, char* dst);
|
||||
extern unsigned int decompressRLE(const char* src, unsigned int length, char* dst, unsigned int targetLength);
|
||||
|
||||
#endif /* FILES_FILES_H_ */
|
||||
76
src/graphics/LineBatch.cpp
Normal file
76
src/graphics/LineBatch.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* LineBatch.cpp
|
||||
*
|
||||
* Created on: Jun 25, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#include "LineBatch.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#define LB_VERTEX_SIZE (3+4)
|
||||
|
||||
LineBatch::LineBatch(size_t capacity) : capacity(capacity) {
|
||||
int attrs[] = {3,4, 0};
|
||||
buffer = new float[capacity * LB_VERTEX_SIZE * 2];
|
||||
mesh = new Mesh(buffer, 0, attrs);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
LineBatch::~LineBatch(){
|
||||
delete[] buffer;
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
void LineBatch::line(float x1, float y1, float z1, float x2, float y2, float z2,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index] = x1;
|
||||
buffer[index+1] = y1;
|
||||
buffer[index+2] = z1;
|
||||
buffer[index+3] = r;
|
||||
buffer[index+4] = g;
|
||||
buffer[index+5] = b;
|
||||
buffer[index+6] = a;
|
||||
index += LB_VERTEX_SIZE;
|
||||
|
||||
buffer[index] = x2;
|
||||
buffer[index+1] = y2;
|
||||
buffer[index+2] = z2;
|
||||
buffer[index+3] = r;
|
||||
buffer[index+4] = g;
|
||||
buffer[index+5] = b;
|
||||
buffer[index+6] = a;
|
||||
index += LB_VERTEX_SIZE;
|
||||
}
|
||||
|
||||
void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
||||
float r, float g, float b, float a) {
|
||||
w *= 0.5f;
|
||||
h *= 0.5f;
|
||||
d *= 0.5f;
|
||||
|
||||
line(x-w, y-h, z-d, x+w, y-h, z-d, r,g,b,a);
|
||||
line(x-w, y+h, z-d, x+w, y+h, z-d, r,g,b,a);
|
||||
line(x-w, y-h, z+d, x+w, y-h, z+d, r,g,b,a);
|
||||
line(x-w, y+h, z+d, x+w, y+h, z+d, r,g,b,a);
|
||||
|
||||
line(x-w, y-h, z-d, x-w, y+h, z-d, r,g,b,a);
|
||||
line(x+w, y-h, z-d, x+w, y+h, z-d, r,g,b,a);
|
||||
line(x-w, y-h, z+d, x-w, y+h, z+d, r,g,b,a);
|
||||
line(x+w, y-h, z+d, x+w, y+h, z+d, r,g,b,a);
|
||||
|
||||
line(x-w, y-h, z-d, x-w, y-h, z+d, r,g,b,a);
|
||||
line(x+w, y-h, z-d, x+w, y-h, z+d, r,g,b,a);
|
||||
line(x-w, y+h, z-d, x-w, y+h, z+d, r,g,b,a);
|
||||
line(x+w, y+h, z-d, x+w, y+h, z+d, r,g,b,a);
|
||||
}
|
||||
|
||||
void LineBatch::render(){
|
||||
if (index == 0)
|
||||
return;
|
||||
mesh->reload(buffer, index / LB_VERTEX_SIZE);
|
||||
mesh->draw(GL_LINES);
|
||||
index = 0;
|
||||
}
|
||||
32
src/graphics/LineBatch.h
Normal file
32
src/graphics/LineBatch.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* LineBatch.h
|
||||
*
|
||||
* Created on: Jun 25, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_LINEBATCH_H_
|
||||
#define GRAPHICS_LINEBATCH_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Mesh;
|
||||
|
||||
class LineBatch {
|
||||
Mesh* mesh;
|
||||
float* buffer;
|
||||
size_t index;
|
||||
size_t capacity;
|
||||
public:
|
||||
LineBatch(size_t capacity);
|
||||
~LineBatch();
|
||||
|
||||
void line(float x1, float y1, float z1, float x2, float y2, float z2,
|
||||
float r, float g, float b, float a);
|
||||
void box(float x, float y, float z, float w, float h, float d,
|
||||
float r, float g, float b, float a);
|
||||
|
||||
void render();
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_LINEBATCH_H_ */
|
||||
45
src/graphics/Mesh.cpp
Normal file
45
src/graphics/Mesh.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "Mesh.h"
|
||||
#include <GL/glew.h>
|
||||
|
||||
Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(vertices){
|
||||
vertexSize = 0;
|
||||
for (int i = 0; attrs[i]; i++){
|
||||
vertexSize += attrs[i];
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW);
|
||||
|
||||
// attributes
|
||||
int offset = 0;
|
||||
for (int i = 0; attrs[i]; i++){
|
||||
int size = attrs[i];
|
||||
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
|
||||
glEnableVertexAttribArray(i);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
Mesh::~Mesh(){
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
}
|
||||
|
||||
void Mesh::reload(const float* buffer, size_t vertices){
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW);
|
||||
this->vertices = vertices;
|
||||
}
|
||||
|
||||
void Mesh::draw(unsigned int primitive){
|
||||
glBindVertexArray(vao);
|
||||
glDrawArrays(primitive, 0, vertices);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
19
src/graphics/Mesh.h
Normal file
19
src/graphics/Mesh.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GRAPHICS_MESH_H_
|
||||
#define GRAPHICS_MESH_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Mesh {
|
||||
unsigned int vao;
|
||||
unsigned int vbo;
|
||||
size_t vertices;
|
||||
size_t vertexSize;
|
||||
public:
|
||||
Mesh(const float* buffer, size_t vertices, const int* attrs);
|
||||
~Mesh();
|
||||
|
||||
void reload(const float* buffer, size_t vertices);
|
||||
void draw(unsigned int primitive);
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_MESH_H_ */
|
||||
109
src/graphics/Shader.cpp
Normal file
109
src/graphics/Shader.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "Shader.h"
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
Shader::Shader(unsigned int id) : id(id){
|
||||
}
|
||||
|
||||
Shader::~Shader(){
|
||||
glDeleteProgram(id);
|
||||
}
|
||||
|
||||
void Shader::use(){
|
||||
glUseProgram(id);
|
||||
}
|
||||
|
||||
void Shader::uniformMatrix(std::string name, glm::mat4 matrix){
|
||||
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
|
||||
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix));
|
||||
}
|
||||
|
||||
|
||||
Shader* load_shader(std::string vertexFile, std::string fragmentFile) {
|
||||
// Reading Files
|
||||
std::string vertexCode;
|
||||
std::string fragmentCode;
|
||||
std::ifstream vShaderFile;
|
||||
std::ifstream fShaderFile;
|
||||
|
||||
vShaderFile.exceptions(std::ifstream::badbit);
|
||||
fShaderFile.exceptions(std::ifstream::badbit);
|
||||
try {
|
||||
vShaderFile.open(vertexFile);
|
||||
fShaderFile.open(fragmentFile);
|
||||
std::stringstream vShaderStream, fShaderStream;
|
||||
|
||||
vShaderStream << vShaderFile.rdbuf();
|
||||
fShaderStream << fShaderFile.rdbuf();
|
||||
|
||||
vShaderFile.close();
|
||||
fShaderFile.close();
|
||||
|
||||
vertexCode = vShaderStream.str();
|
||||
fragmentCode = fShaderStream.str();
|
||||
}
|
||||
catch(std::ifstream::failure& e) {
|
||||
std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
const GLchar* vShaderCode = vertexCode.c_str();
|
||||
const GLchar* fShaderCode = fragmentCode.c_str();
|
||||
|
||||
GLuint vertex, fragment;
|
||||
GLint success;
|
||||
GLchar infoLog[512];
|
||||
|
||||
// Vertex Shader
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &vShaderCode, nullptr);
|
||||
glCompileShader(vertex);
|
||||
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
||||
if (!success){
|
||||
glGetShaderInfoLog(vertex, 512, nullptr, infoLog);
|
||||
std::cerr << "SHADER::VERTEX: compilation failed" << std::endl;
|
||||
std::cerr << infoLog << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Fragment Shader
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment, 1, &fShaderCode, nullptr);
|
||||
glCompileShader(fragment);
|
||||
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
||||
if (!success){
|
||||
glGetShaderInfoLog(fragment, 512, nullptr, infoLog);
|
||||
std::cerr << "SHADER::FRAGMENT: compilation failed" << std::endl;
|
||||
std::cerr << infoLog << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Shader Program
|
||||
GLuint id = glCreateProgram();
|
||||
glAttachShader(id, vertex);
|
||||
glAttachShader(id, fragment);
|
||||
glLinkProgram(id);
|
||||
|
||||
glGetProgramiv(id, GL_LINK_STATUS, &success);
|
||||
if (!success){
|
||||
glGetProgramInfoLog(id, 512, nullptr, infoLog);
|
||||
std::cerr << "SHADER::PROGRAM: linking failed" << std::endl;
|
||||
std::cerr << infoLog << std::endl;
|
||||
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
|
||||
return new Shader(id);
|
||||
}
|
||||
20
src/graphics/Shader.h
Normal file
20
src/graphics/Shader.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef GRAPHICS_SHADER_H_
|
||||
#define GRAPHICS_SHADER_H_
|
||||
|
||||
#include <string>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
unsigned int id;
|
||||
|
||||
Shader(unsigned int id);
|
||||
~Shader();
|
||||
|
||||
void use();
|
||||
void uniformMatrix(std::string name, glm::mat4 matrix);
|
||||
};
|
||||
|
||||
extern Shader* load_shader(std::string vertexFile, std::string fragmentFile);
|
||||
|
||||
#endif /* GRAPHICS_SHADER_H_ */
|
||||
31
src/graphics/Texture.cpp
Normal file
31
src/graphics/Texture.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "Texture.h"
|
||||
#include <GL/glew.h>
|
||||
|
||||
Texture::Texture(unsigned int id, int width, int height) : id(id), width(width), height(height) {
|
||||
}
|
||||
|
||||
Texture::Texture(unsigned char* data, int width, int height) : width(width), height(height) {
|
||||
glGenTextures(1, &id);
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
||||
void Texture::bind(){
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
}
|
||||
|
||||
void Texture::reload(unsigned char* data){
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
21
src/graphics/Texture.h
Normal file
21
src/graphics/Texture.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef GRAPHICS_TEXTURE_H_
|
||||
#define GRAPHICS_TEXTURE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
unsigned int id;
|
||||
int width;
|
||||
int height;
|
||||
Texture(unsigned int id, int width, int height);
|
||||
Texture(unsigned char* data, int width, int height);
|
||||
~Texture();
|
||||
|
||||
void bind();
|
||||
void reload(unsigned char* data);
|
||||
};
|
||||
|
||||
extern Texture* load_texture(std::string filename);
|
||||
|
||||
#endif /* GRAPHICS_TEXTURE_H_ */
|
||||
299
src/graphics/VoxelRenderer.cpp
Normal file
299
src/graphics/VoxelRenderer.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
#include "VoxelRenderer.h"
|
||||
#include "Mesh.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
|
||||
#define VERTEX_SIZE (3 + 2 + 4)
|
||||
|
||||
#define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A)))
|
||||
#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X))
|
||||
#define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE))
|
||||
#define IS_CHUNK(X,Y,Z) (GET_CHUNK(X,Y,Z) != nullptr)
|
||||
#define GET_CHUNK(X,Y,Z) (chunks[((CDIV(Y, CHUNK_H)+1) * 3 + CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1])
|
||||
|
||||
#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)
|
||||
#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)])
|
||||
#define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP))
|
||||
|
||||
#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer[INDEX+0] = (X);\
|
||||
buffer[INDEX+1] = (Y);\
|
||||
buffer[INDEX+2] = (Z);\
|
||||
buffer[INDEX+3] = (U);\
|
||||
buffer[INDEX+4] = (V);\
|
||||
buffer[INDEX+5] = (R);\
|
||||
buffer[INDEX+6] = (G);\
|
||||
buffer[INDEX+7] = (B);\
|
||||
buffer[INDEX+8] = (S);\
|
||||
INDEX += VERTEX_SIZE;
|
||||
|
||||
|
||||
#define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\
|
||||
float v1 = 1-((1 + (INDEX) / 16) * uvsize);\
|
||||
float u2 = u1 + uvsize;\
|
||||
float v2 = v1 + uvsize;
|
||||
|
||||
int chunk_attrs[] = {3,2,4, 0};
|
||||
|
||||
VoxelRenderer::VoxelRenderer(size_t capacity) : capacity(capacity) {
|
||||
buffer = new float[capacity * VERTEX_SIZE * 6];
|
||||
}
|
||||
|
||||
VoxelRenderer::~VoxelRenderer(){
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){
|
||||
size_t index = 0;
|
||||
for (int y = 0; y < CHUNK_H; y++){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
unsigned int id = vox.id;
|
||||
|
||||
if (!id){
|
||||
continue;
|
||||
}
|
||||
|
||||
float l;
|
||||
float uvsize = 1.0f/16.0f;
|
||||
|
||||
Block* block = Block::blocks[id];
|
||||
unsigned char group = block->drawGroup;
|
||||
|
||||
if (!IS_BLOCKED(x,y+1,z,group)){
|
||||
l = 1.0f;
|
||||
|
||||
SETUP_UV(block->textureFaces[3]);
|
||||
|
||||
float lr = LIGHT(x,y+1,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y+1,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y+1,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y+1,z, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0, lg0, lb0, ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1, lg1, lb1, ls1);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2, lg2, lb2, ls2);
|
||||
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0, lg0, lb0, ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2, lg2, lb2, ls2);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, lr3, lg3, lb3, ls3);
|
||||
}
|
||||
if (!IS_BLOCKED(x,y-1,z,group)){
|
||||
l = 0.75f;
|
||||
|
||||
SETUP_UV(block->textureFaces[2]);
|
||||
|
||||
float lr = LIGHT(x,y-1,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y-1,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y-1,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y-1,z, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr3,lg3,lb3,ls3);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
}
|
||||
|
||||
if (!IS_BLOCKED(x+1,y,z,group)){
|
||||
l = 0.95f;
|
||||
|
||||
SETUP_UV(block->textureFaces[1]);
|
||||
|
||||
float lr = LIGHT(x+1,y,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x+1,y,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x+1,y,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x+1,y,z, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, lr3,lg3,lb3,ls3);
|
||||
}
|
||||
if (!IS_BLOCKED(x-1,y,z,group)){
|
||||
l = 0.85f;
|
||||
|
||||
SETUP_UV(block->textureFaces[0]);
|
||||
|
||||
float lr = LIGHT(x-1,y,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x-1,y,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x-1,y,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x-1,y,z, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
}
|
||||
|
||||
if (!IS_BLOCKED(x,y,z+1,group)){
|
||||
l = 0.9f;
|
||||
|
||||
SETUP_UV(block->textureFaces[5]);
|
||||
|
||||
float lr = LIGHT(x,y,z+1, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y,z+1, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y,z+1, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y,z+1, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
}
|
||||
if (!IS_BLOCKED(x,y,z-1,group)){
|
||||
l = 0.8f;
|
||||
|
||||
SETUP_UV(block->textureFaces[4]);
|
||||
|
||||
float lr = LIGHT(x,y,z-1, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y,z-1, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y,z-1, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y,z-1, 3) / 15.0f;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Mesh(buffer, index / VERTEX_SIZE, chunk_attrs);
|
||||
}
|
||||
19
src/graphics/VoxelRenderer.h
Normal file
19
src/graphics/VoxelRenderer.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GRAPHICS_VOXELRENDERER_H_
|
||||
#define GRAPHICS_VOXELRENDERER_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Mesh;
|
||||
class Chunk;
|
||||
|
||||
class VoxelRenderer {
|
||||
float* buffer;
|
||||
size_t capacity;
|
||||
public:
|
||||
VoxelRenderer(size_t capacity);
|
||||
~VoxelRenderer();
|
||||
|
||||
Mesh* render(Chunk* chunk, const Chunk** chunks);
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_VOXELRENDERER_H_ */
|
||||
122
src/lighting/LightSolver.cpp
Normal file
122
src/lighting/LightSolver.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "LightSolver.h"
|
||||
#include "Lightmap.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
LightSolver::LightSolver(Chunks* chunks, int channel) : chunks(chunks), channel(channel) {
|
||||
}
|
||||
|
||||
void LightSolver::add(int x, int y, int z, int emission) {
|
||||
if (emission <= 1)
|
||||
return;
|
||||
lightentry entry;
|
||||
entry.x = x;
|
||||
entry.y = y;
|
||||
entry.z = z;
|
||||
entry.light = emission;
|
||||
addqueue.push(entry);
|
||||
|
||||
Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z);
|
||||
chunk->modified = true;
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, entry.light);
|
||||
}
|
||||
|
||||
void LightSolver::add(int x, int y, int z) {
|
||||
add(x,y,z, chunks->getLight(x,y,z, channel));
|
||||
}
|
||||
|
||||
void LightSolver::remove(int x, int y, int z) {
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr)
|
||||
return;
|
||||
|
||||
int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel);
|
||||
if (light == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
lightentry entry;
|
||||
entry.x = x;
|
||||
entry.y = y;
|
||||
entry.z = z;
|
||||
entry.light = light;
|
||||
remqueue.push(entry);
|
||||
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, 0);
|
||||
}
|
||||
|
||||
void LightSolver::solve(){
|
||||
const int coords[] = {
|
||||
0, 0, 1,
|
||||
0, 0,-1,
|
||||
0, 1, 0,
|
||||
0,-1, 0,
|
||||
1, 0, 0,
|
||||
-1, 0, 0
|
||||
};
|
||||
|
||||
while (!remqueue.empty()){
|
||||
lightentry entry = remqueue.front();
|
||||
remqueue.pop();
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
int x = entry.x+coords[i*3+0];
|
||||
int y = entry.y+coords[i*3+1];
|
||||
int z = entry.z+coords[i*3+2];
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x,y,z);
|
||||
if (chunk) {
|
||||
int light = chunks->getLight(x,y,z, channel);
|
||||
if (light != 0 && light == entry.light-1){
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = light;
|
||||
remqueue.push(nentry);
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0);
|
||||
chunk->modified = true;
|
||||
}
|
||||
else if (light >= entry.light){
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = light;
|
||||
addqueue.push(nentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!addqueue.empty()){
|
||||
lightentry entry = addqueue.front();
|
||||
addqueue.pop();
|
||||
|
||||
if (entry.light <= 1)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
int x = entry.x+coords[i*3+0];
|
||||
int y = entry.y+coords[i*3+1];
|
||||
int z = entry.z+coords[i*3+2];
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x,y,z);
|
||||
if (chunk) {
|
||||
int light = chunks->getLight(x,y,z, channel);
|
||||
voxel* v = chunks->get(x,y,z);
|
||||
Block* block = Block::blocks[v->id];
|
||||
if (block->lightPassing && light+2 <= entry.light){
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, entry.light-1);
|
||||
chunk->modified = true;
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = entry.light-1;
|
||||
addqueue.push(nentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/lighting/LightSolver.h
Normal file
29
src/lighting/LightSolver.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef LIGHTING_LIGHTSOLVER_H_
|
||||
#define LIGHTING_LIGHTSOLVER_H_
|
||||
|
||||
#include <queue>
|
||||
|
||||
class Chunks;
|
||||
|
||||
struct lightentry {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
unsigned char light;
|
||||
};
|
||||
|
||||
class LightSolver {
|
||||
std::queue<lightentry> addqueue;
|
||||
std::queue<lightentry> remqueue;
|
||||
Chunks* chunks;
|
||||
int channel;
|
||||
public:
|
||||
LightSolver(Chunks* chunks, int channel);
|
||||
|
||||
void add(int x, int y, int z);
|
||||
void add(int x, int y, int z, int emission);
|
||||
void remove(int x, int y, int z);
|
||||
void solve();
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTSOLVER_H_ */
|
||||
246
src/lighting/Lighting.cpp
Normal file
246
src/lighting/Lighting.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
#include "Lighting.h"
|
||||
#include "LightSolver.h"
|
||||
#include "Lightmap.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
Chunks* Lighting::chunks = nullptr;
|
||||
LightSolver* Lighting::solverR = nullptr;
|
||||
LightSolver* Lighting::solverG = nullptr;
|
||||
LightSolver* Lighting::solverB = nullptr;
|
||||
LightSolver* Lighting::solverS = nullptr;
|
||||
|
||||
int Lighting::initialize(Chunks* chunks){
|
||||
Lighting::chunks = chunks;
|
||||
solverR = new LightSolver(chunks, 0);
|
||||
solverG = new LightSolver(chunks, 1);
|
||||
solverB = new LightSolver(chunks, 2);
|
||||
solverS = new LightSolver(chunks, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Lighting::finalize(){
|
||||
delete solverR, solverG, solverB, solverS;
|
||||
}
|
||||
|
||||
void Lighting::clear(){
|
||||
for (unsigned int index = 0; index < chunks->volume; index++){
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Lightmap* lightmap = chunk->lightmap;
|
||||
for (int i = 0; i < CHUNK_VOL; i++){
|
||||
lightmap->map[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lighting::onChunkLoaded(int cx, int cy, int cz){
|
||||
Chunk* chunk = chunks->getChunk(cx, cy, cz);
|
||||
Chunk* chunkUpper = chunks->getChunk(cx, cy+1, cz);
|
||||
Chunk* chunkLower = chunks->getChunk(cx, cy-1, cz);
|
||||
if (chunkLower){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
|
||||
int light = chunk->lightmap->getS(x,0,z);
|
||||
int ncy = cy-1;
|
||||
if (light < 15){
|
||||
Chunk* current = chunkLower;
|
||||
if (chunkLower->lightmap->getS(x,15,z) == 0)
|
||||
continue;
|
||||
for (int y = 15;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->lightPassing)
|
||||
break;
|
||||
//current->lightmap->setS(x,y,z, 0);
|
||||
current->modified = true;
|
||||
solverS->remove(gx,y+ncy*CHUNK_H,gz);
|
||||
current->lightmap->setS(x,y,z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chunkUpper){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
int ncy = cy;
|
||||
|
||||
int light = chunkUpper->lightmap->getS(x,0,z);
|
||||
|
||||
Chunk* current = chunk;
|
||||
if (light == 15){
|
||||
for (int y = CHUNK_H-1;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->lightPassing)
|
||||
break;
|
||||
current->lightmap->setS(x,y,z, 15);
|
||||
current->modified = true;
|
||||
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
||||
}
|
||||
} else if (light){
|
||||
solverS->add(gx,gy+CHUNK_H,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
int ncy = cy;
|
||||
|
||||
Chunk* current = chunk;
|
||||
for (int y = CHUNK_H-1;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->lightPassing)
|
||||
break;
|
||||
current->lightmap->setS(x,y,z, 15);
|
||||
current->modified = true;
|
||||
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//std::cout << "DONE" << std::endl;
|
||||
for (unsigned int y = 0; y < CHUNK_H; y++){
|
||||
for (unsigned int z = 0; z < CHUNK_D; z++){
|
||||
for (unsigned int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
Block* block = Block::blocks[vox.id];
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = y + cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
solverR->add(gx,gy,gz,block->emission[0]);
|
||||
solverG->add(gx,gy,gz,block->emission[1]);
|
||||
solverB->add(gx,gy,gz,block->emission[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int y = -1; y <= CHUNK_H; y++){
|
||||
for (int z = -1; z <= CHUNK_D; z++){
|
||||
for (int x = -1; x <= CHUNK_W; x++){
|
||||
if (!(x == -1 || x == CHUNK_W || y == -1 || y == CHUNK_H || z == -1 || z == CHUNK_D))
|
||||
continue;
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = y + cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
solverR->add(gx,gy,gz);
|
||||
solverG->add(gx,gy,gz);
|
||||
solverB->add(gx,gy,gz);
|
||||
solverS->add(gx,gy,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
solverS->solve();
|
||||
|
||||
Chunk* other;
|
||||
other = chunks->getChunk(cx-1,cy,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx+1,cy,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy-1,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy+1,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy,cz-1); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy,cz+1); if (other) other->modified = true;
|
||||
}
|
||||
|
||||
void Lighting::onBlockSet(int x, int y, int z, int id){
|
||||
Block* block = Block::blocks[id];
|
||||
if (id == 0){
|
||||
solverR->remove(x,y,z);
|
||||
solverG->remove(x,y,z);
|
||||
solverB->remove(x,y,z);
|
||||
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
|
||||
if (chunks->getLight(x,y+1,z, 3) == 0xF){
|
||||
for (int i = y; i >= 0; i--){
|
||||
voxel* vox = chunks->get(x,i,z);
|
||||
if (vox == nullptr || vox->id != 0)
|
||||
break;
|
||||
solverS->add(x,i,z, 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z);
|
||||
solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z);
|
||||
solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z);
|
||||
solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z);
|
||||
solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1);
|
||||
solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1);
|
||||
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
solverS->solve();
|
||||
} else {
|
||||
solverR->remove(x,y,z);
|
||||
solverG->remove(x,y,z);
|
||||
solverB->remove(x,y,z);
|
||||
if (!block->lightPassing){
|
||||
solverS->remove(x,y,z);
|
||||
for (int i = y-1; i >= 0; i--){
|
||||
solverS->remove(x,i,z);
|
||||
if (i == 0 || chunks->get(x,i-1,z)->id != 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
solverS->solve();
|
||||
}
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
solverR->add(x,y,z,block->emission[0]);
|
||||
solverG->add(x,y,z,block->emission[1]);
|
||||
solverB->add(x,y,z,block->emission[2]);
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/lighting/Lighting.h
Normal file
22
src/lighting/Lighting.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef LIGHTING_LIGHTING_H_
|
||||
#define LIGHTING_LIGHTING_H_
|
||||
|
||||
class Chunks;
|
||||
class LightSolver;
|
||||
|
||||
class Lighting {
|
||||
static Chunks* chunks;
|
||||
static LightSolver* solverR;
|
||||
static LightSolver* solverG;
|
||||
static LightSolver* solverB;
|
||||
static LightSolver* solverS;
|
||||
public:
|
||||
static int initialize(Chunks* chunks);
|
||||
static void finalize();
|
||||
|
||||
static void clear();
|
||||
static void onChunkLoaded(int cx, int cy, int cz);
|
||||
static void onBlockSet(int x, int y, int z, int id);
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTING_H_ */
|
||||
12
src/lighting/Lightmap.cpp
Normal file
12
src/lighting/Lightmap.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "Lightmap.h"
|
||||
|
||||
Lightmap::Lightmap(){
|
||||
map = new unsigned short[CHUNK_VOL];
|
||||
for (unsigned int i = 0; i < CHUNK_VOL; i++){
|
||||
map[i] = 0x0000;
|
||||
}
|
||||
}
|
||||
|
||||
Lightmap::~Lightmap(){
|
||||
delete[] map;
|
||||
}
|
||||
58
src/lighting/Lightmap.h
Normal file
58
src/lighting/Lightmap.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef LIGHTING_LIGHTMAP_H_
|
||||
#define LIGHTING_LIGHTMAP_H_
|
||||
|
||||
#include "../voxels/Chunk.h"
|
||||
|
||||
class Lightmap {
|
||||
public:
|
||||
unsigned short* map;
|
||||
Lightmap();
|
||||
~Lightmap();
|
||||
|
||||
inline unsigned char get(int x, int y, int z, int channel){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getR(int x, int y, int z){
|
||||
return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getG(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getB(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getS(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF;
|
||||
}
|
||||
|
||||
inline void setR(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xFFF0) | value;
|
||||
}
|
||||
|
||||
inline void setG(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xFF0F) | (value << 4);
|
||||
}
|
||||
|
||||
inline void setB(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xF0FF) | (value << 8);
|
||||
}
|
||||
|
||||
inline void setS(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0x0FFF) | (value << 12);
|
||||
}
|
||||
|
||||
inline void set(int x, int y, int z, int channel, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & (0xFFFF & (~(0xF << (channel*4))))) | (value << (channel << 2));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTMAP_H_ */
|
||||
125
src/loaders/png_loading.cpp
Normal file
125
src/loaders/png_loading.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* png_loading.cpp
|
||||
*
|
||||
* Created on: Feb 10, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#include "png_loading.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <GL/glew.h>
|
||||
#include <png.h>
|
||||
#include "../graphics/Texture.h"
|
||||
|
||||
int _png_load(const char* file, int* width, int* height){
|
||||
FILE *f;
|
||||
int is_png, bit_depth, color_type, row_bytes;
|
||||
png_infop info_ptr, end_info;
|
||||
png_uint_32 t_width, t_height;
|
||||
png_byte header[8], *image_data;
|
||||
png_bytepp row_pointers;
|
||||
png_structp png_ptr;
|
||||
GLuint texture;
|
||||
int alpha;
|
||||
|
||||
if ( !( f = fopen(file, "r" ) ) ) {
|
||||
return 0;
|
||||
}
|
||||
fread( header, 1, 8, f );
|
||||
is_png = !png_sig_cmp( header, 0, 8 );
|
||||
if ( !is_png ) {
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL,
|
||||
NULL, NULL );
|
||||
if ( !png_ptr ) {
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
info_ptr = png_create_info_struct( png_ptr );
|
||||
if ( !info_ptr ) {
|
||||
png_destroy_read_struct( &png_ptr, (png_infopp) NULL,
|
||||
(png_infopp) NULL );
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
end_info = png_create_info_struct( png_ptr );
|
||||
if ( !end_info ) {
|
||||
png_destroy_read_struct( &png_ptr, (png_infopp) NULL,
|
||||
(png_infopp) NULL );
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
if ( setjmp( png_jmpbuf( png_ptr ) ) ) {
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
png_init_io( png_ptr, f );
|
||||
png_set_sig_bytes( png_ptr, 8 );
|
||||
png_read_info( png_ptr, info_ptr );
|
||||
png_get_IHDR( png_ptr, info_ptr, &t_width, &t_height, &bit_depth,
|
||||
&color_type, NULL, NULL, NULL );
|
||||
*width = t_width;
|
||||
*height = t_height;
|
||||
png_read_update_info( png_ptr, info_ptr );
|
||||
row_bytes = png_get_rowbytes( png_ptr, info_ptr );
|
||||
image_data = (png_bytep) malloc( row_bytes * t_height * sizeof(png_byte) );
|
||||
if ( !image_data ) {
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
row_pointers = (png_bytepp) malloc( t_height * sizeof(png_bytep) );
|
||||
if ( !row_pointers ) {
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
free( image_data );
|
||||
fclose( f );
|
||||
return 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < t_height; ++i ) {
|
||||
row_pointers[t_height - 1 - i] = image_data + i * row_bytes;
|
||||
}
|
||||
png_read_image( png_ptr, row_pointers );
|
||||
switch ( png_get_color_type( png_ptr, info_ptr ) ) {
|
||||
case PNG_COLOR_TYPE_RGBA:
|
||||
alpha = GL_RGBA;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
alpha = GL_RGB;
|
||||
break;
|
||||
default:
|
||||
printf( "Color type %d not supported!\n",
|
||||
png_get_color_type( png_ptr, info_ptr ) );
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
return 0;
|
||||
}
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t_width, t_height, 0,
|
||||
alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
free( image_data );
|
||||
free( row_pointers );
|
||||
fclose( f );
|
||||
return texture;
|
||||
}
|
||||
|
||||
Texture* load_texture(std::string filename){
|
||||
int width, height;
|
||||
GLuint texture = _png_load(filename.c_str(), &width, &height);
|
||||
if (texture == 0){
|
||||
std::cerr << "Could not load texture " << filename << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
return new Texture(texture, width, height);
|
||||
}
|
||||
17
src/loaders/png_loading.h
Normal file
17
src/loaders/png_loading.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* png_loading.h
|
||||
*
|
||||
* Created on: Feb 10, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#ifndef LOADERS_PNG_LOADING_H_
|
||||
#define LOADERS_PNG_LOADING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Texture;
|
||||
|
||||
extern Texture* load_texture(std::string filename);
|
||||
|
||||
#endif /* LOADERS_PNG_LOADING_H_ */
|
||||
276
src/voxel_engine.cpp
Normal file
276
src/voxel_engine.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
#include <iostream>
|
||||
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
// GLM
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
using namespace glm;
|
||||
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/Mesh.h"
|
||||
#include "graphics/VoxelRenderer.h"
|
||||
#include "graphics/LineBatch.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "window/Camera.h"
|
||||
#include "loaders/png_loading.h"
|
||||
#include "voxels/voxel.h"
|
||||
#include "voxels/Chunk.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/Block.h"
|
||||
#include "voxels/WorldGenerator.h"
|
||||
#include "files/files.h"
|
||||
#include "files/WorldFiles.h"
|
||||
#include "lighting/LightSolver.h"
|
||||
#include "lighting/Lightmap.h"
|
||||
#include "lighting/Lighting.h"
|
||||
|
||||
int WIDTH = 1280;
|
||||
int HEIGHT = 720;
|
||||
|
||||
float vertices[] = {
|
||||
// x y
|
||||
-0.01f,-0.01f,
|
||||
0.01f, 0.01f,
|
||||
|
||||
-0.01f, 0.01f,
|
||||
0.01f,-0.01f,
|
||||
};
|
||||
|
||||
int attrs[] = {
|
||||
2, 0 //null terminator
|
||||
};
|
||||
|
||||
int main() {
|
||||
Window::initialize(WIDTH, HEIGHT, "Window 2.0");
|
||||
Events::initialize();
|
||||
|
||||
Shader* shader = load_shader("res/main.glslv", "res/main.glslf");
|
||||
if (shader == nullptr){
|
||||
std::cerr << "failed to load shader" << std::endl;
|
||||
Window::terminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Shader* crosshairShader = load_shader("res/crosshair.glslv", "res/crosshair.glslf");
|
||||
if (crosshairShader == nullptr){
|
||||
std::cerr << "failed to load crosshair shader" << std::endl;
|
||||
Window::terminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Shader* linesShader = load_shader("res/lines.glslv", "res/lines.glslf");
|
||||
if (linesShader == nullptr){
|
||||
std::cerr << "failed to load lines shader" << std::endl;
|
||||
Window::terminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Texture* texture = load_texture("res/block.png");
|
||||
if (texture == nullptr){
|
||||
std::cerr << "failed to load texture" << std::endl;
|
||||
delete shader;
|
||||
Window::terminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
// AIR
|
||||
Block* block = new Block(0,0);
|
||||
block->drawGroup = 1;
|
||||
block->lightPassing = true;
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
// STONE
|
||||
block = new Block(1,2);
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
// GRASS
|
||||
block = new Block(2,4);
|
||||
block->textureFaces[2] = 2;
|
||||
block->textureFaces[3] = 1;
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
// LAMP
|
||||
block = new Block(3,3);
|
||||
block->emission[0] = 10;
|
||||
block->emission[1] = 0;
|
||||
block->emission[2] = 0;
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
// GLASS
|
||||
block = new Block(4,5);
|
||||
block->drawGroup = 2;
|
||||
block->lightPassing = true;
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
// PLANKS
|
||||
block = new Block(5,6);
|
||||
Block::blocks[block->id] = block;
|
||||
}
|
||||
|
||||
WorldFiles wfile = WorldFiles("world/", 24*1024*1024);
|
||||
Chunks* chunks = new Chunks(16*4,1,16*4, 0,0,0);
|
||||
VoxelRenderer renderer(1024*1024*8);
|
||||
LineBatch* lineBatch = new LineBatch(4096);
|
||||
|
||||
Lighting::initialize(chunks);
|
||||
|
||||
glClearColor(0.0f,0.0f,0.0f,1);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Mesh* crosshair = new Mesh(vertices, 4, attrs);
|
||||
Camera* camera = new Camera(vec3(32,32,32), radians(90.0f));
|
||||
|
||||
float lastTime = glfwGetTime();
|
||||
float delta = 0.0f;
|
||||
|
||||
float camX = 0.0f;
|
||||
float camY = 0.0f;
|
||||
|
||||
float speed = 15;
|
||||
|
||||
int choosenBlock = 1;
|
||||
|
||||
glfwSwapInterval(0);
|
||||
|
||||
while (!Window::isShouldClose()){
|
||||
float currentTime = glfwGetTime();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_ESCAPE)){
|
||||
Window::setShouldClose(true);
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_TAB)){
|
||||
Events::toogleCursor();
|
||||
}
|
||||
|
||||
for (int i = 1; i < 6; i++){
|
||||
if (Events::jpressed(GLFW_KEY_0+i)){
|
||||
choosenBlock = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (Events::pressed(GLFW_KEY_W)){
|
||||
camera->position += camera->front * delta * speed;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_S)){
|
||||
camera->position -= camera->front * delta * speed;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_D)){
|
||||
camera->position += camera->right * delta * speed;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_A)){
|
||||
camera->position -= camera->right * delta * speed;
|
||||
}
|
||||
|
||||
chunks->setCenter(camera->position.x,0,camera->position.z);
|
||||
chunks->_buildMeshes(&renderer);
|
||||
chunks->loadVisible(&wfile);
|
||||
|
||||
if (Events::_cursor_locked){
|
||||
camY += -Events::deltaY / Window::height * 2;
|
||||
camX += -Events::deltaX / Window::height * 2;
|
||||
|
||||
if (camY < -radians(89.0f)){
|
||||
camY = -radians(89.0f);
|
||||
}
|
||||
if (camY > radians(89.0f)){
|
||||
camY = radians(89.0f);
|
||||
}
|
||||
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(camY, camX, 0);
|
||||
}
|
||||
|
||||
{
|
||||
vec3 end;
|
||||
vec3 norm;
|
||||
vec3 iend;
|
||||
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
|
||||
if (vox != nullptr){
|
||||
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);
|
||||
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_1)){
|
||||
int x = (int)iend.x;
|
||||
int y = (int)iend.y;
|
||||
int z = (int)iend.z;
|
||||
chunks->set(x,y,z, 0);
|
||||
Lighting::onBlockSet(x,y,z,0);
|
||||
}
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_2)){
|
||||
int x = (int)(iend.x)+(int)(norm.x);
|
||||
int y = (int)(iend.y)+(int)(norm.y);
|
||||
int z = (int)(iend.z)+(int)(norm.z);
|
||||
chunks->set(x, y, z, choosenBlock);
|
||||
Lighting::onBlockSet(x,y,z, choosenBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Draw VAO
|
||||
shader->use();
|
||||
shader->uniformMatrix("projview", camera->getProjection()*camera->getView());
|
||||
texture->bind();
|
||||
mat4 model(1.0f);
|
||||
for (size_t i = 0; i < chunks->volume; i++){
|
||||
Chunk* chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Mesh* mesh = chunks->meshes[i];
|
||||
if (mesh == nullptr)
|
||||
continue;
|
||||
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));
|
||||
shader->uniformMatrix("model", model);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
crosshairShader->use();
|
||||
crosshair->draw(GL_LINES);
|
||||
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("projview", camera->getProjection()*camera->getView());
|
||||
glLineWidth(2.0f);
|
||||
lineBatch->render();
|
||||
|
||||
Window::swapBuffers();
|
||||
Events::pullEvents();
|
||||
}
|
||||
|
||||
Lighting::finalize();
|
||||
|
||||
for (unsigned int i = 0; i < chunks->volume; i++){
|
||||
Chunk* chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
wfile.put((const char*)chunk->voxels, chunk->x, chunk->z);
|
||||
}
|
||||
|
||||
wfile.write();
|
||||
|
||||
delete shader;
|
||||
delete texture;
|
||||
delete chunks;
|
||||
delete crosshair;
|
||||
delete crosshairShader;
|
||||
delete linesShader;
|
||||
delete lineBatch;
|
||||
|
||||
Window::terminate();
|
||||
return 0;
|
||||
}
|
||||
8
src/voxels/Block.cpp
Normal file
8
src/voxels/Block.cpp
Normal 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
src/voxels/Block.h
Normal file
18
src/voxels/Block.h
Normal 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
src/voxels/Chunk.cpp
Normal file
29
src/voxels/Chunk.cpp
Normal 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
src/voxels/Chunk.h
Normal file
24
src/voxels/Chunk.h
Normal 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
src/voxels/Chunks.cpp
Normal file
388
src/voxels/Chunks.cpp
Normal 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
src/voxels/Chunks.h
Normal file
43
src/voxels/Chunks.h
Normal 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
src/voxels/WorldGenerator.cpp
Normal file
31
src/voxels/WorldGenerator.cpp
Normal 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
src/voxels/WorldGenerator.h
Normal file
11
src/voxels/WorldGenerator.h
Normal 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
src/voxels/voxel.cpp
Normal file
2
src/voxels/voxel.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "voxel.h"
|
||||
|
||||
10
src/voxels/voxel.h
Normal file
10
src/voxels/voxel.h
Normal 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_ */
|
||||
38
src/window/Camera.cpp
Normal file
38
src/window/Camera.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Camera.cpp
|
||||
*
|
||||
* Created on: Feb 11, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
Camera::Camera(vec3 position, float fov) : position(position), fov(fov), rotation(1.0f) {
|
||||
updateVectors();
|
||||
}
|
||||
|
||||
void Camera::updateVectors(){
|
||||
front = vec3(rotation * vec4(0,0,-1,1));
|
||||
right = vec3(rotation * vec4(1,0,0,1));
|
||||
up = vec3(rotation * vec4(0,1,0,1));
|
||||
}
|
||||
|
||||
void Camera::rotate(float x, float y, float z){
|
||||
rotation = glm::rotate(rotation, z, vec3(0,0,1));
|
||||
rotation = glm::rotate(rotation, y, vec3(0,1,0));
|
||||
rotation = glm::rotate(rotation, x, vec3(1,0,0));
|
||||
|
||||
updateVectors();
|
||||
}
|
||||
|
||||
mat4 Camera::getProjection(){
|
||||
float aspect = (float)Window::width / (float)Window::height;
|
||||
return glm::perspective(fov, aspect, 0.1f, 1500.0f);
|
||||
}
|
||||
|
||||
mat4 Camera::getView(){
|
||||
return glm::lookAt(position, position+front, up);
|
||||
}
|
||||
32
src/window/Camera.h
Normal file
32
src/window/Camera.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Camera.h
|
||||
*
|
||||
* Created on: Feb 11, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#ifndef WINDOW_CAMERA_H_
|
||||
#define WINDOW_CAMERA_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
using namespace glm;
|
||||
|
||||
class Camera {
|
||||
void updateVectors();
|
||||
public:
|
||||
vec3 front;
|
||||
vec3 up;
|
||||
vec3 right;
|
||||
|
||||
vec3 position;
|
||||
float fov;
|
||||
mat4 rotation;
|
||||
Camera(vec3 position, float fov);
|
||||
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
mat4 getProjection();
|
||||
mat4 getView();
|
||||
};
|
||||
|
||||
#endif /* WINDOW_CAMERA_H_ */
|
||||
105
src/window/Events.cpp
Normal file
105
src/window/Events.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include "Events.h"
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <string.h>
|
||||
|
||||
bool* Events::_keys;
|
||||
uint* Events::_frames;
|
||||
uint Events::_current = 0;
|
||||
float Events::deltaX = 0.0f;
|
||||
float Events::deltaY = 0.0f;
|
||||
float Events::x = 0.0f;
|
||||
float Events::y = 0.0f;
|
||||
bool Events::_cursor_locked = false;
|
||||
bool Events::_cursor_started = false;
|
||||
|
||||
#define _MOUSE_BUTTONS 1024
|
||||
|
||||
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos){
|
||||
if (Events::_cursor_started){
|
||||
Events::deltaX += xpos-Events::x;
|
||||
Events::deltaY += ypos-Events::y;
|
||||
}
|
||||
else {
|
||||
Events::_cursor_started = true;
|
||||
}
|
||||
Events::x = xpos;
|
||||
Events::y = ypos;
|
||||
}
|
||||
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode){
|
||||
if (action == GLFW_PRESS){
|
||||
Events::_keys[_MOUSE_BUTTONS+button] = true;
|
||||
Events::_frames[_MOUSE_BUTTONS+button] = Events::_current;
|
||||
}
|
||||
else if (action == GLFW_RELEASE){
|
||||
Events::_keys[_MOUSE_BUTTONS+button] = false;
|
||||
Events::_frames[_MOUSE_BUTTONS+button] = Events::_current;
|
||||
}
|
||||
}
|
||||
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
|
||||
if (action == GLFW_PRESS){
|
||||
Events::_keys[key] = true;
|
||||
Events::_frames[key] = Events::_current;
|
||||
}
|
||||
else if (action == GLFW_RELEASE){
|
||||
Events::_keys[key] = false;
|
||||
Events::_frames[key] = Events::_current;
|
||||
}
|
||||
}
|
||||
|
||||
void window_size_callback(GLFWwindow* window, int width, int height){
|
||||
glViewport(0,0, width, height);
|
||||
Window::width = width;
|
||||
Window::height = height;
|
||||
}
|
||||
|
||||
int Events::initialize(){
|
||||
GLFWwindow* window = Window::window;
|
||||
_keys = new bool[1032];
|
||||
_frames = new uint[1032];
|
||||
|
||||
memset(_keys, false, 1032*sizeof(bool));
|
||||
memset(_frames, 0, 1032*sizeof(uint));
|
||||
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
||||
glfwSetWindowSizeCallback(window, window_size_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Events::pressed(int keycode){
|
||||
if (keycode < 0 || keycode >= _MOUSE_BUTTONS)
|
||||
return false;
|
||||
return _keys[keycode];
|
||||
}
|
||||
|
||||
bool Events::jpressed(int keycode){
|
||||
if (keycode < 0 || keycode >= _MOUSE_BUTTONS)
|
||||
return false;
|
||||
return _keys[keycode] && _frames[keycode] == _current;
|
||||
}
|
||||
|
||||
bool Events::clicked(int button){
|
||||
int index = _MOUSE_BUTTONS+button;
|
||||
return _keys[index];
|
||||
}
|
||||
|
||||
bool Events::jclicked(int button){
|
||||
int index = _MOUSE_BUTTONS+button;
|
||||
return _keys[index] && _frames[index] == _current;
|
||||
}
|
||||
|
||||
void Events::toogleCursor(){
|
||||
_cursor_locked = !_cursor_locked;
|
||||
Window::setCursorMode(_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
|
||||
void Events::pullEvents(){
|
||||
_current++;
|
||||
deltaX = 0.0f;
|
||||
deltaY = 0.0f;
|
||||
glfwPollEvents();
|
||||
}
|
||||
32
src/window/Events.h
Normal file
32
src/window/Events.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef WINDOW_EVENTS_H_
|
||||
#define WINDOW_EVENTS_H_
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
class Events {
|
||||
public:
|
||||
static bool* _keys;
|
||||
static uint* _frames;
|
||||
static uint _current;
|
||||
static float deltaX;
|
||||
static float deltaY;
|
||||
static float x;
|
||||
static float y;
|
||||
static bool _cursor_locked;
|
||||
static bool _cursor_started;
|
||||
|
||||
static int initialize();
|
||||
static void pullEvents();
|
||||
|
||||
static bool pressed(int keycode);
|
||||
static bool jpressed(int keycode);
|
||||
|
||||
static bool clicked(int button);
|
||||
static bool jclicked(int button);
|
||||
|
||||
static void toogleCursor();
|
||||
};
|
||||
|
||||
#endif /* WINDOW_EVENTS_H_ */
|
||||
56
src/window/Window.cpp
Normal file
56
src/window/Window.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include <iostream>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "Window.h"
|
||||
|
||||
GLFWwindow* Window::window;
|
||||
int Window::width = 0;
|
||||
int Window::height = 0;
|
||||
|
||||
int Window::initialize(int width, int height, const char* title){
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
|
||||
//glfwWindowHint(GLFW_SAMPLES, 2);
|
||||
|
||||
window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||
if (window == nullptr){
|
||||
std::cerr << "Failed to create GLFW Window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GLEW_OK){
|
||||
std::cerr << "Failed to initialize GLEW" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
glViewport(0,0, width, height);
|
||||
|
||||
Window::width = width;
|
||||
Window::height = height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Window::setCursorMode(int mode){
|
||||
glfwSetInputMode(window, GLFW_CURSOR, mode);
|
||||
}
|
||||
|
||||
void Window::terminate(){
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool Window::isShouldClose(){
|
||||
return glfwWindowShouldClose(window);
|
||||
}
|
||||
|
||||
void Window::setShouldClose(bool flag){
|
||||
glfwSetWindowShouldClose(window, flag);
|
||||
}
|
||||
|
||||
void Window::swapBuffers(){
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
20
src/window/Window.h
Normal file
20
src/window/Window.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef WINDOW_WINDOW_H_
|
||||
#define WINDOW_WINDOW_H_
|
||||
|
||||
class GLFWwindow;
|
||||
|
||||
class Window {
|
||||
public:
|
||||
static int width;
|
||||
static int height;
|
||||
static GLFWwindow* window; // не лучшее решение делать window публичным
|
||||
static int initialize(int width, int height, const char* title);
|
||||
static void terminate();
|
||||
|
||||
static void setCursorMode(int mode);
|
||||
static bool isShouldClose();
|
||||
static void setShouldClose(bool flag);
|
||||
static void swapBuffers();
|
||||
};
|
||||
|
||||
#endif /* WINDOW_WINDOW_H_ */
|
||||
Loading…
x
Reference in New Issue
Block a user