world-wide commit to ruin everything

This commit is contained in:
MihailRis 2022-10-28 22:44:32 +03:00
parent fbce36a05c
commit 8a073e4e8a
57 changed files with 1433 additions and 958 deletions

View File

@ -11,6 +11,9 @@ CPP_SRCS += \
../src/graphics/Mesh.cpp \ ../src/graphics/Mesh.cpp \
../src/graphics/Shader.cpp \ ../src/graphics/Shader.cpp \
../src/graphics/Texture.cpp \ ../src/graphics/Texture.cpp \
../src/graphics/Sprite.cpp \
../src/graphics/UVRegion.cpp \
../src/graphics/Framebuffer.cpp \
../src/graphics/VoxelRenderer.cpp ../src/graphics/VoxelRenderer.cpp
OBJS += \ OBJS += \
@ -21,6 +24,9 @@ OBJS += \
./src/graphics/Mesh.o \ ./src/graphics/Mesh.o \
./src/graphics/Shader.o \ ./src/graphics/Shader.o \
./src/graphics/Texture.o \ ./src/graphics/Texture.o \
./src/graphics/Sprite.o \
./src/graphics/UVRegion.o \
./src/graphics/Framebuffer.o \
./src/graphics/VoxelRenderer.o ./src/graphics/VoxelRenderer.o
CPP_DEPS += \ CPP_DEPS += \
@ -31,6 +37,9 @@ CPP_DEPS += \
./src/graphics/Mesh.d \ ./src/graphics/Mesh.d \
./src/graphics/Shader.d \ ./src/graphics/Shader.d \
./src/graphics/Texture.d \ ./src/graphics/Texture.d \
./src/graphics/Sprite.d \
./src/graphics/UVRegion.d \
./src/graphics/Framebuffer.d \
./src/graphics/VoxelRenderer.d ./src/graphics/VoxelRenderer.d

View File

@ -8,6 +8,7 @@ CPP_SRCS += \
../src/player_control.cpp \ ../src/player_control.cpp \
../src/hud_render.cpp \ ../src/hud_render.cpp \
../src/world_render.cpp \ ../src/world_render.cpp \
../src/declarations.cpp \
../src/voxel_engine.cpp ../src/voxel_engine.cpp
OBJS += \ OBJS += \
@ -15,6 +16,7 @@ OBJS += \
./src/player_control.o \ ./src/player_control.o \
./src/hud_render.o \ ./src/hud_render.o \
./src/world_render.o \ ./src/world_render.o \
./src/declarations.o \
./src/voxel_engine.o ./src/voxel_engine.o
CPP_DEPS += \ CPP_DEPS += \
@ -22,6 +24,7 @@ CPP_DEPS += \
./src/player_control.d \ ./src/player_control.d \
./src/hud_render.d \ ./src/hud_render.d \
./src/world_render.d \ ./src/world_render.d \
./src/declarations.d \
./src/voxel_engine.d ./src/voxel_engine.d

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 793 B

View File

@ -11,10 +11,11 @@ uniform float u_fogFactor;
void main(){ void main(){
vec4 tex_color = texture(u_texture0, a_texCoord); vec4 tex_color = texture(u_texture0, a_texCoord);
//if (tex_color.a < 0.5) float depth = (a_distance/256.0);
// discard;
float depth = (a_distance/256.0)*(a_distance/256.0)*256.0/6;
float alpha = a_color.a * tex_color.a; float alpha = a_color.a * tex_color.a;
// anyway it's any alpha-test alternative required
if (alpha < 0.1f)
discard;
f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, depth*u_fogFactor)); f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, depth*u_fogFactor));
f_color.a = alpha; f_color.a = alpha;
} }

View File

@ -15,12 +15,19 @@ uniform vec3 u_skyLightColor;
uniform vec3 u_cameraPos; uniform vec3 u_cameraPos;
uniform float u_gamma; uniform float u_gamma;
uniform vec3 u_torchlightColor;
uniform float u_torchlightDistance;
void main(){ void main(){
vec2 pos2d = (u_model * vec4(v_position, 1.0)).xz-u_cameraPos.xz; vec2 pos2d = (u_model * vec4(v_position, 1.0)).xz-u_cameraPos.xz;
vec4 viewmodelpos = u_view * u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0); vec4 modelpos = u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0);
a_color = vec4(pow(v_light.rgb, vec3(u_gamma)),1.0f); vec4 viewmodelpos = u_view * modelpos;
vec3 light = v_light.rgb;
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz)/u_torchlightDistance);
light += torchlight * u_torchlightColor;
a_color = vec4(pow(light, vec3(u_gamma)),1.0f);
a_texCoord = v_texCoord; a_texCoord = v_texCoord;
a_color.rgb += u_skyLightColor * v_light.a*0.5; a_color.rgb += u_skyLightColor * v_light.a;
a_distance = length(viewmodelpos); a_distance = pow(length(viewmodelpos), 1.5);
gl_Position = u_proj * viewmodelpos; gl_Position = u_proj * viewmodelpos;
} }

View File

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -12,5 +12,5 @@ uniform mat4 u_projview;
void main(){ void main(){
a_textureCoord = v_textureCoord; a_textureCoord = v_textureCoord;
a_color = v_color; a_color = v_color;
gl_Position = u_projview * vec4(v_position, 0.0, 1.0); gl_Position = u_projview * vec4(v_position, 0.5, 1.0);
} }

View File

@ -25,6 +25,12 @@ bool ALSource::play(){
return alCheck(); return alCheck();
} }
bool ALSource::isPlaying() {
int state;
alGetSourcei(id, AL_SOURCE_STATE, &state);
return state == AL_PLAYING;
}
bool ALSource::setPosition(glm::vec3 position) { bool ALSource::setPosition(glm::vec3 position) {
alSource3f(id, AL_POSITION, position.x, position.y, position.z); alSource3f(id, AL_POSITION, position.x, position.y, position.z);
return alCheck(); return alCheck();
@ -84,7 +90,9 @@ bool Audio::initialize(){
void Audio::finalize(){ void Audio::finalize(){
for (ALSource* source : allsources){ for (ALSource* source : allsources){
if (source->isPlaying()){
alSourceStop(source->id); alCheck(); alSourceStop(source->id); alCheck();
}
alDeleteSources(1, &source->id); alCheck(); alDeleteSources(1, &source->id); alCheck();
} }
@ -168,7 +176,7 @@ bool Audio::get_available_devices(std::vector<std::string>& devicesVec){
return true; return true;
} }
void Audio::setOrientation(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up){ void Audio::setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up){
ALfloat listenerOri[] = { at.x, at.y, at.z, up.x, up.y, up.z }; ALfloat listenerOri[] = { at.x, at.y, at.z, up.x, up.y, up.z };
alListener3f(AL_POSITION, position.x, position.y, position.z); alListener3f(AL_POSITION, position.x, position.y, position.z);

View File

@ -16,6 +16,7 @@ struct ALSource {
ALuint id; ALuint id;
ALSource(ALuint id) : id(id) {} ALSource(ALuint id) : id(id) {}
bool isPlaying();
bool setPosition(glm::vec3 position); bool setPosition(glm::vec3 position);
bool setVelocity(glm::vec3 velocity); bool setVelocity(glm::vec3 velocity);
bool setBuffer(ALBuffer* buffer); bool setBuffer(ALBuffer* buffer);
@ -54,7 +55,7 @@ public:
static void finalize(); static void finalize();
static bool get_available_devices(std::vector<std::string>& devicesVec); static bool get_available_devices(std::vector<std::string>& devicesVec);
static void setOrientation(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up); static void setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
}; };

154
src/declarations.cpp Normal file
View File

@ -0,0 +1,154 @@
#include "declarations.h"
#include "Assets.h"
#include "graphics/Shader.h"
#include "graphics/Texture.h"
#include "graphics/Font.h"
#include "window/Window.h"
#include "voxels/Block.h"
// Shaders, textures
bool _load_shader(Assets* assets, std::string vertex_file, std::string fragment_file, std::string name){
Shader* shader = load_shader(vertex_file, fragment_file);
if (shader == nullptr){
std::cerr << "failed to load shader '" << name << "'" << std::endl;
return false;
}
assets->store(shader, name);
return true;
}
bool _load_texture(Assets* assets, std::string filename, std::string name){
Texture* texture = load_texture(filename);
if (texture == nullptr){
std::cerr << "failed to load texture '" << name << "'" << std::endl;
return false;
}
assets->store(texture, name);
return true;
}
bool _load_font(Assets* assets, std::string filename, std::string name){
std::vector<Texture*> pages;
for (size_t i = 0; i <= 4; i++){
Texture* texture = load_texture(filename+"_"+std::to_string(i)+".png");
if (texture == nullptr){
std::cerr << "failed to load bitmap font '" << name << "' (missing page " << std::to_string(i) << ")" << std::endl;
return false;
}
pages.push_back(texture);
}
Font* font = new Font(pages);
assets->store(font, name);
return true;
}
int initialize_assets(Assets* assets) {
#define LOAD_SHADER(VERTEX, FRAGMENT, NAME) \
if (!_load_shader(assets, VERTEX, FRAGMENT, NAME))\
return 1;
#define LOAD_TEXTURE(FILENAME, NAME) \
if (!_load_texture(assets, FILENAME, NAME))\
return 1;
#define LOAD_FONT(FILENAME, NAME) \
if (!_load_font(assets, FILENAME, NAME))\
return 1;
LOAD_SHADER("res/main.glslv", "res/main.glslf", "main");
LOAD_SHADER("res/crosshair.glslv", "res/crosshair.glslf", "crosshair");
LOAD_SHADER("res/lines.glslv", "res/lines.glslf", "lines");
LOAD_SHADER("res/ui.glslv", "res/ui.glslf", "ui");
LOAD_TEXTURE("res/block.png", "block");
LOAD_TEXTURE("res/slot.png", "slot");
LOAD_FONT("res/font", "normal");
return 0;
}
// All in-game definitions (blocks, items, etc..)
void setup_definitions() {
for (size_t i = 0; i < 256; i++)
Block::blocks[i] = nullptr;
Block* block = new Block(BLOCK_AIR, 0);
block->drawGroup = 1;
block->lightPassing = true;
block->skyLightPassing = true;
block->obstacle = false;
block->selectable = false;
block->model = 0;
Block::blocks[block->id] = block;
block = new Block(BLOCK_DIRT, 2);
Block::blocks[block->id] = block;
block = new Block(BLOCK_GRASS_BLOCK, 4);
block->textureFaces[2] = 2;
block->textureFaces[3] = 1;
Block::blocks[block->id] = block;
block = new Block(BLOCK_LAMP, 3);
block->emission[0] = 15;
block->emission[1] = 14;
block->emission[2] = 13;
Block::blocks[block->id] = block;
block = new Block(BLOCK_GLASS,5);
block->drawGroup = 2;
block->lightPassing = true;
Block::blocks[block->id] = block;
block = new Block(BLOCK_PLANKS, 6);
Block::blocks[block->id] = block;
block = new Block(BLOCK_WOOD, 7);
block->textureFaces[2] = 8;
block->textureFaces[3] = 8;
Block::blocks[block->id] = block;
block = new Block(BLOCK_LEAVES, 9);
Block::blocks[block->id] = block;
block = new Block(BLOCK_STONE, 10);
Block::blocks[block->id] = block;
block = new Block(BLOCK_WATER, 11);
block->drawGroup = 4;
block->lightPassing = true;
block->skyLightPassing = false;
block->obstacle = false;
block->selectable = false;
Block::blocks[block->id] = block;
block = new Block(BLOCK_SAND, 12);
Block::blocks[block->id] = block;
block = new Block(BLOCK_BEDROCK, 13);
block->breakable = false;
Block::blocks[block->id] = block;
block = new Block(BLOCK_GRASS, 14);
block->drawGroup = 5;
block->lightPassing = true;
block->obstacle = false;
block->model = 2;
Block::blocks[block->id] = block;
block = new Block(BLOCK_FLOWER, 16);
block->drawGroup = 5;
block->lightPassing = true;
block->obstacle = false;
block->model = 2;
Block::blocks[block->id] = block;
block = new Block(BLOCK_BRICK, 17);
Block::blocks[block->id] = block;
block = new Block(BLOCK_METAL, 18);
Block::blocks[block->id] = block;
block = new Block(BLOCK_RUST, 19);
Block::blocks[block->id] = block;
}

View File

@ -2,164 +2,29 @@
#define DECLARATIONS_H #define DECLARATIONS_H
#include <iostream> #include <iostream>
#include "Assets.h"
#include "graphics/Shader.h"
#include "graphics/Texture.h"
#include "graphics/Font.h"
#include "window/Window.h"
#include "voxels/Block.h" #define BLOCK_AIR 0
#define BLOCK_DIRT 1
#define BLOCK_GRASS_BLOCK 2
#define BLOCK_LAMP 3
#define BLOCK_GLASS 4
#define BLOCK_PLANKS 5
#define BLOCK_WOOD 6
#define BLOCK_LEAVES 7
#define BLOCK_STONE 8
#define BLOCK_WATER 9
#define BLOCK_SAND 10
#define BLOCK_BEDROCK 11
#define BLOCK_GRASS 12
#define BLOCK_FLOWER 13
#define BLOCK_BRICK 14
#define BLOCK_METAL 15
#define BLOCK_RUST 16
class Assets;
// Shaders, textures, renderers int initialize_assets(Assets* assets);
void setup_definitions();
bool _load_shader(Assets* assets, std::string vertex_file, std::string fragment_file, std::string name){
Shader* shader = load_shader(vertex_file, fragment_file);
if (shader == nullptr){
std::cerr << "failed to load shader '" << name << "'" << std::endl;
return false;
}
assets->store(shader, name);
return true;
}
bool _load_texture(Assets* assets, std::string filename, std::string name){
Texture* texture = load_texture(filename);
if (texture == nullptr){
std::cerr << "failed to load texture '" << name << "'" << std::endl;
return false;
}
assets->store(texture, name);
return true;
}
bool _load_font(Assets* assets, std::string filename, std::string name){
std::vector<Texture*> pages;
for (size_t i = 0; i <= 4; i++){
Texture* texture = load_texture(filename+"_"+std::to_string(i)+".png");
if (texture == nullptr){
std::cerr << "failed to load bitmap font '" << name << "' (missing page " << std::to_string(i) << ")" << std::endl;
return false;
}
pages.push_back(texture);
}
Font* font = new Font(pages);
assets->store(font, name);
return true;
}
int initialize_assets(Assets* assets) {
#define LOAD_SHADER(VERTEX, FRAGMENT, NAME) \
if (!_load_shader(assets, VERTEX, FRAGMENT, NAME))\
return 1;
#define LOAD_TEXTURE(FILENAME, NAME) \
if (!_load_texture(assets, FILENAME, NAME))\
return 1;
#define LOAD_FONT(FILENAME, NAME) \
if (!_load_font(assets, FILENAME, NAME))\
return 1;
LOAD_SHADER("res/main.glslv", "res/main.glslf", "main");
LOAD_SHADER("res/crosshair.glslv", "res/crosshair.glslf", "crosshair");
LOAD_SHADER("res/lines.glslv", "res/lines.glslf", "lines");
LOAD_SHADER("res/ui.glslv", "res/ui.glslf", "ui");
LOAD_TEXTURE("res/block.png", "block");
LOAD_TEXTURE("res/sprite.png", "sprite");
LOAD_FONT("res/font", "normal");
return 0;
}
// All in-game definitions (blocks, items, etc..)
void setup_definitions() {
for (size_t i = 0; i < 256; i++)
Block::blocks[i] = nullptr;
// AIR 0
Block* block = new Block(0,0);
block->drawGroup = 1;
block->lightPassing = true;
block->skyLightPassing = true;
block->obstacle = false;
block->selectable = false;
block->model = 0;
Block::blocks[block->id] = block;
// DIRT 1
block = new Block(1,2);
Block::blocks[block->id] = block;
// GRASS BLOCK2
block = new Block(2,4);
block->textureFaces[2] = 2;
block->textureFaces[3] = 1;
Block::blocks[block->id] = block;
// LAMP 3
block = new Block(3,3);
block->emission[0] = 15;
block->emission[1] = 14;
block->emission[2] = 13;
Block::blocks[block->id] = block;
// GLASS 4
block = new Block(4,5);
block->drawGroup = 2;
block->lightPassing = true;
Block::blocks[block->id] = block;
// PLANKS 5
block = new Block(5,6);
Block::blocks[block->id] = block;
// WOOD 6
block = new Block(6,7);
block->textureFaces[2] = 8;
block->textureFaces[3] = 8;
Block::blocks[block->id] = block;
// LEAVES 7
block = new Block(7,9);
Block::blocks[block->id] = block;
// STONE 8
block = new Block(8,10);
Block::blocks[block->id] = block;
// WATER 9
block = new Block(9,11);
block->drawGroup = 4;
block->lightPassing = true;
block->skyLightPassing = false;
block->obstacle = false;
block->selectable = false;
Block::blocks[block->id] = block;
// SAND 10
block = new Block(10,12);
Block::blocks[block->id] = block;
// BEDROCK 11
block = new Block(11,13);
block->breakable = false;
Block::blocks[block->id] = block;
// GRASS 12
block = new Block(12,14);
block->drawGroup = 5;
block->lightPassing = true;
block->obstacle = false;
block->model = 2;
Block::blocks[block->id] = block;
// FLOWER 13
block = new Block(13,16);
block->drawGroup = 5;
block->lightPassing = true;
block->obstacle = false;
block->model = 2;
Block::blocks[block->id] = block;
}
#endif // DECLARATIONS_H #endif // DECLARATIONS_H

View File

@ -19,6 +19,9 @@ union {
#define SECTION_POSITION 1 #define SECTION_POSITION 1
#define SECTION_ROTATION 2 #define SECTION_ROTATION 2
#define SECTION_FLAGS 3
#define PLAYER_FLAG_FLIGHT 0x1
#define PLAYER_FLAG_NOCLIP 0x2
unsigned long WorldFiles::totalCompressed = 0; unsigned long WorldFiles::totalCompressed = 0;
@ -33,7 +36,7 @@ void int2Bytes(int value, char* dest, unsigned int offset){
dest[offset+3] = (char) (value >> 0 & 255); dest[offset+3] = (char) (value >> 0 & 255);
} }
void float2Bytes(float fvalue, char* dest, unsigned int offset){ void floatToBytes(float fvalue, char* dest, unsigned int offset){
uint32_t value = *((uint32_t*)&fvalue); uint32_t value = *((uint32_t*)&fvalue);
dest[offset] = (char) (value >> 24 & 255); dest[offset] = (char) (value >> 24 & 255);
dest[offset+1] = (char) (value >> 16 & 255); dest[offset+1] = (char) (value >> 16 & 255);
@ -58,15 +61,15 @@ WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : direc
WorldFiles::~WorldFiles(){ WorldFiles::~WorldFiles(){
delete[] mainBufferIn; delete[] mainBufferIn;
delete[] mainBufferOut; delete[] mainBufferOut;
std::unordered_map<long, char**>::iterator it; std::unordered_map<long, WorldRegion>::iterator it;
for (it = regions.begin(); it != regions.end(); it++){ for (it = regions.begin(); it != regions.end(); it++){
char** region = it->second; WorldRegion region = it->second;
if (region == nullptr) if (region.chunksData == nullptr)
continue; continue;
for (unsigned int i = 0; i < REGION_VOL; i++){ for (unsigned int i = 0; i < REGION_VOL; i++){
delete[] region[i]; delete[] region.chunksData[i];
} }
delete[] region; delete[] region.chunksData;
} }
regions.clear(); regions.clear();
} }
@ -82,17 +85,17 @@ void WorldFiles::put(const char* chunkData, int x, int y){
_tempcoords._coords[0] = regionX; _tempcoords._coords[0] = regionX;
_tempcoords._coords[1] = regionY; _tempcoords._coords[1] = regionY;
char** region = regions[_tempcoords._key]; WorldRegion& region = regions[_tempcoords._key];
if (region == nullptr){ region.unsaved = true;
region = new char*[REGION_VOL]; if (region.chunksData == nullptr){
region.chunksData = new char*[REGION_VOL];
for (unsigned int i = 0; i < REGION_VOL; i++) for (unsigned int i = 0; i < REGION_VOL; i++)
region[i] = nullptr; region.chunksData[i] = nullptr;
regions[_tempcoords._key] = region;
} }
char* targetChunk = region[localY * REGION_SIZE + localX]; char* targetChunk = region.chunksData[localY * REGION_SIZE + localX];
if (targetChunk == nullptr){ if (targetChunk == nullptr){
targetChunk = new char[CHUNK_VOL]; targetChunk = new char[CHUNK_VOL];
region[localY * REGION_SIZE + localX] = targetChunk; region.chunksData[localY * REGION_SIZE + localX] = targetChunk;
totalCompressed += CHUNK_VOL; totalCompressed += CHUNK_VOL;
} }
for (unsigned int i = 0; i < CHUNK_VOL; i++) for (unsigned int i = 0; i < CHUNK_VOL; i++)
@ -122,11 +125,11 @@ bool WorldFiles::getChunk(int x, int y, char* out){
_tempcoords._coords[0] = regionX; _tempcoords._coords[0] = regionX;
_tempcoords._coords[1] = regionY; _tempcoords._coords[1] = regionY;
char** region = regions[_tempcoords._key]; WorldRegion& region = regions[_tempcoords._key];
if (region == nullptr) if (region.chunksData == nullptr)
return readChunk(x,y,out); return readChunk(x,y,out);
char* chunk = region[chunkIndex]; char* chunk = region.chunksData[chunkIndex];
if (chunk == nullptr) if (chunk == nullptr)
return readChunk(x,y,out); return readChunk(x,y,out);
for (unsigned int i = 0; i < CHUNK_VOL; i++) for (unsigned int i = 0; i < CHUNK_VOL; i++)
@ -174,34 +177,38 @@ bool WorldFiles::readChunk(int x, int y, char* out){
} }
void WorldFiles::write(){ void WorldFiles::write(){
std::unordered_map<long, char**>::iterator it; std::unordered_map<long, WorldRegion>::iterator it;
for (it = regions.begin(); it != regions.end(); it++){ for (it = regions.begin(); it != regions.end(); it++){
if (it->second == nullptr) if (it->second.chunksData == nullptr || !it->second.unsaved)
continue; continue;
int x; int x;
int y; int y;
longToCoords(x,y, it->first); longToCoords(x,y, it->first);
unsigned int size = writeRegion(mainBufferOut, x,y, it->second); unsigned int size = writeRegion(mainBufferOut, x,y, it->second.chunksData);
write_binary_file(getRegionFile(x,y), mainBufferOut, size); write_binary_file(getRegionFile(x,y), mainBufferOut, size);
} }
} }
void WorldFiles::writePlayer(Player* player){ void WorldFiles::writePlayer(Player* player){
char dst[1+3*4 + 1+2*4]; char dst[1+3*4 + 1+2*4 + 1+1];
glm::vec3 position = player->hitbox->position; glm::vec3 position = player->hitbox->position;
size_t offset = 0; size_t offset = 0;
dst[offset++] = SECTION_POSITION; dst[offset++] = SECTION_POSITION;
float2Bytes(position.x, dst, offset); offset += 4; floatToBytes(position.x, dst, offset); offset += 4;
float2Bytes(position.y, dst, offset); offset += 4; floatToBytes(position.y, dst, offset); offset += 4;
float2Bytes(position.z, dst, offset); offset += 4; floatToBytes(position.z, dst, offset); offset += 4;
dst[offset++] = SECTION_ROTATION; dst[offset++] = SECTION_ROTATION;
float2Bytes(player->camX, dst, offset); offset += 4; floatToBytes(player->camX, dst, offset); offset += 4;
float2Bytes(player->camY, dst, offset); offset += 4; floatToBytes(player->camY, dst, offset); offset += 4;
dst[offset++] = SECTION_FLAGS;
dst[offset++] = player->flight * PLAYER_FLAG_FLIGHT |
player->noclip * PLAYER_FLAG_NOCLIP;
write_binary_file(getPlayerFile(), (const char*)dst, sizeof(dst)); write_binary_file(getPlayerFile(), (const char*)dst, sizeof(dst));
} }
@ -227,6 +234,13 @@ bool WorldFiles::readPlayer(Player* player) {
player->camX = bytes2Float(data, offset); offset += 4; player->camX = bytes2Float(data, offset); offset += 4;
player->camY = bytes2Float(data, offset); offset += 4; player->camY = bytes2Float(data, offset); offset += 4;
break; break;
case SECTION_FLAGS:
{
unsigned char flags = data[offset++];
player->flight = flags & PLAYER_FLAG_FLIGHT;
player->noclip = flags & PLAYER_FLAG_NOCLIP;
}
break;
} }
} }
player->hitbox->position = position; player->hitbox->position = position;

View File

@ -12,15 +12,15 @@ class Player;
#define REGION_SIZE (1 << (REGION_SIZE_BIT)) #define REGION_SIZE (1 << (REGION_SIZE_BIT))
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE)) #define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
/* Требование: struct WorldRegion {
* - высота мира = 1 чанк (любых размеров) char** chunksData;
* Пример: bool unsaved;
* - CHUNK_W = 16, CHUNK_H = 128, CHUNK_D = 16 };
* */
class WorldFiles { class WorldFiles {
public: public:
static unsigned long totalCompressed; static unsigned long totalCompressed;
std::unordered_map<long, char**> regions; std::unordered_map<long, WorldRegion> regions;
std::string directory; std::string directory;
char* mainBufferIn; char* mainBufferIn;
char* mainBufferOut; char* mainBufferOut;

View File

@ -69,36 +69,38 @@ unsigned int decompressRLE(const char* src, unsigned int length, char* dst, unsi
unsigned int calcRLE(const char* src, unsigned int length) { unsigned int calcRLE(const char* src, unsigned int length) {
unsigned int offset = 0; unsigned int offset = 0;
unsigned int counter = 1; unsigned int counter = 0;
char c = src[0]; char c = src[0];
for (unsigned int i = 0; i < length; i++){ for (unsigned int i = 0; i < length; i++){
char cnext = src[i]; char cnext = src[i];
if (cnext != c || counter == 256){ if (cnext != c || counter == 255){
offset += 2; offset += 2;
c = cnext; c = cnext;
counter = 0; counter = 0;
} } else {
counter++; counter++;
} }
}
return offset + 2; return offset + 2;
} }
// max result size = length * 2; returns compressed length // max result size = length * 2; returns compressed length
unsigned int compressRLE(const char* src, unsigned int length, char* dst) { unsigned int compressRLE(const char* src, unsigned int length, char* dst) {
unsigned int offset = 0; unsigned int offset = 0;
unsigned int counter = 1; unsigned int counter = 0;
char c = src[0]; char c = src[0];
for (unsigned int i = 1; i < length; i++){ for (unsigned int i = 1; i < length; i++){
char cnext = src[i]; char cnext = src[i];
if (cnext != c || counter == 256){ if (cnext != c || counter == 255){
dst[offset++] = counter-1; dst[offset++] = counter;
dst[offset++] = c; dst[offset++] = c;
c = cnext; c = cnext;
counter = 0; counter = 0;
} } else {
counter++; counter++;
} }
dst[offset++] = counter-1; }
dst[offset++] = counter;
dst[offset++] = c; dst[offset++] = c;
return offset; return offset;
} }

View File

@ -1,6 +1,7 @@
#include "Batch2D.h" #include "Batch2D.h"
#include "Mesh.h" #include "Mesh.h"
#include "Texture.h" #include "Texture.h"
#include "Sprite.h"
#include <GL/glew.h> #include <GL/glew.h>
@ -86,6 +87,116 @@ void Batch2D::rect(float x, float y, float w, float h){
vertex(x+w, y+h, 1, 1, r,g,b,a); vertex(x+w, y+h, 1, 1, r,g,b,a);
} }
void Batch2D::rect(
float x, float y,
float w, float h,
float ox, float oy,
float angle,
UVRegion region,
bool flippedX,
bool flippedY,
vec4 tint) {
if (index + 6*VERTEX_SIZE >= capacity)
render();
float centerX = w*ox;
float centerY = h*oy;
float acenterX = w-centerX;
float acenterY = h-centerY;
float _x1 = -centerX;
float _y1 = -centerY;
float _x2 = -centerX;
float _y2 = +acenterY;
float _x3 = +acenterX;
float _y3 = +acenterY;
float _x4 = +acenterX;
float _y4 = -centerY;
float x1,y1,x2,y2,x3,y3,x4,y4;
if (angle != 0) {
float s = sin(angle);
float c = cos(angle);
x1 = c * _x1 - s * _y1;
y1 = s * _x1 + c * _y1;
x2 = c * _x2 - s * _y2;
y2 = s * _x2 + c * _y2;
x3 = c * _x3 - s * _y3;
y3 = s * _x3 + c * _y3;
x4 = x1 + (x3 - x2);
y4 = y3 - (y2 - y1);
} else {
x1 = _x1;
y1 = _y1;
x2 = _x2;
y2 = _y2;
x3 = _x3;
y3 = _y3;
x4 = _x4;
y4 = _y4;
}
x1 += x; x2 += x; x3 += x; x4 += x;
y1 += y; y2 += y; y3 += y; y4 += y;
float u1 = region.u1;
float v1 = region.v1;
float u2 = region.u1;
float v2 = region.v2;
float u3 = region.u2;
float v3 = region.v2;
float u4 = region.u2;
float v4 = region.v1;
if (flippedX) {
float temp = u1;
u1 = u3;
u4 = temp;
u2 = u3;
u3 = temp;
}
if (flippedY) {
float temp = v1;
v1 = v2;
v4 = v2;
v2 = temp;
v3 = temp;
}
vertex(x1, y1, u1, v1, tint.r, tint.g, tint.b, tint.a);
vertex(x2, y2, u2, v2, tint.r, tint.g, tint.b, tint.a);
vertex(x3, y3, u3, v3, tint.r, tint.g, tint.b, tint.a);
/* Right down triangle */
vertex(x1, y1, u1, v1, tint.r, tint.g, tint.b, tint.a);
vertex(x3, y3, u3, v3, tint.r, tint.g, tint.b, tint.a);
vertex(x4, y4, u4, v4, tint.r, tint.g, tint.b, tint.a);
}
void Batch2D::sprite(Sprite* sprite) {
vec2 position = sprite->position;
vec2 size = sprite->size;
vec2 origin = sprite->origin;
texture(sprite->texture);
rect(
position.x, position.y,
size.x, size.y,
origin.x, origin.y,
sprite->angle,
sprite->region,
sprite->flippedX,
sprite->flippedY,
sprite->color);
}
void Batch2D::sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint){ void Batch2D::sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint){
float scale = 1.0f / (float)atlasRes; float scale = 1.0f / (float)atlasRes;
float u = (index % atlasRes) * scale; float u = (index % atlasRes) * scale;
@ -99,16 +210,19 @@ void Batch2D::blockSprite(float x, float y, float w, float h, int atlasRes, int
float vu = 1.0f - ((index[3] / atlasRes) * scale) - scale; float vu = 1.0f - ((index[3] / atlasRes) * scale) - scale;
float uf = (index[0] % atlasRes) * scale; float uf = (index[0] % atlasRes) * scale;
float vf = 1.0f - ((index[0] / atlasRes) * scale) - scale; float vf = 1.0f - ((index[0] / atlasRes) * scale) - scale;
if (index[0] + 6*VERTEX_SIZE >= capacity) if (this->index + 18*VERTEX_SIZE >= capacity)
render(); render();
vec2 points[7] = {vec2(x+(w*0.5f), y+(h*0.5f)), float ar = 0.88f;
vec2(x, y+(h*0.25f)), float ox = x + (w * 0.5f);
vec2(x+(w*0.5f), y), float sx = w * 0.5f * ar;
vec2(x+w, y+(h*0.25f)), vec2 points[7] = {vec2(ox, y+(h*0.5f)),
vec2(x+w, y+(h*0.75f)), vec2(ox-sx, y+(h*0.25f)),
vec2(x+(w*0.5f), y+h), vec2(ox, y),
vec2(x, y+(h*0.75f))}; vec2(ox+sx, y+(h*0.25f)),
vec2(ox+sx, y+(h*0.75f)),
vec2(ox, y+h),
vec2(ox-sx, y+(h*0.75f))};
vec2 uvpoints[8] = {vec2(uu, vu), vec2 uvpoints[8] = {vec2(uu, vu),
vec2(uu+scale, vu), vec2(uu+scale, vu),

View File

@ -4,16 +4,18 @@
#include <stdlib.h> #include <stdlib.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "UVRegion.h"
using namespace glm; using namespace glm;
class Mesh; class Mesh;
class Texture; class Texture;
class Sprite;
class Batch2D { class Batch2D {
float* buffer; float* buffer;
size_t capacity; size_t capacity;
size_t offset; size_t offset;
glm::vec4 color;
Mesh* mesh; Mesh* mesh;
size_t index; size_t index;
@ -28,13 +30,23 @@ class Batch2D {
float r, float g, float b, float a); float r, float g, float b, float a);
public: public:
glm::vec4 color;
Batch2D(size_t capacity); Batch2D(size_t capacity);
~Batch2D(); ~Batch2D();
void begin(); void begin();
void texture(Texture* texture); void texture(Texture* texture);
void sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint); void sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint);
void sprite(Sprite* sprite);
void blockSprite(float x, float y, float w, float h, int atlasRes, int index[6], vec4 tint); void blockSprite(float x, float y, float w, float h, int atlasRes, int index[6], vec4 tint);
void rect(float x, float y,
float w, float h,
float ox, float oy,
float angle, UVRegion region,
bool flippedX, bool flippedY,
vec4 tint);
void rect(float x, float y, float w, float h); void rect(float x, float y, float w, float h);
void rect(float x, float y, float w, float h, void rect(float x, float y, float w, float h,
float u, float v, float tx, float ty, float u, float v, float tx, float ty,

View File

@ -7,7 +7,7 @@
#define VERTEX_SIZE 9 #define VERTEX_SIZE 9
Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 1.0f){ Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 0.0f){
const int attrs[] = { const int attrs[] = {
3, 2, 4, 0 //null terminator 3, 2, 4, 0 //null terminator
}; };

View File

@ -19,9 +19,9 @@ int Font::getGlyphWidth(char c) {
case '.': case '.':
case ',': case ',':
case ':': case ':':
case ';': return 3; case ';': return 7;
case 't': return 5; case 't': return 8;
case ' ': return 3; case ' ': return 7;
} }
return 7; return 7;
} }
@ -75,7 +75,7 @@ void Font::draw(Batch2D* batch, std::wstring text, int x, int y, int style) {
break; break;
} }
batch->sprite(x, y, RES, RES, 16, c, vec4(1.0f)); batch->sprite(x, y, RES, RES, 16, c, batch->color);
} }
else if (charpage > page && charpage < next){ else if (charpage > page && charpage < next){
next = charpage; next = charpage;

View File

@ -0,0 +1,37 @@
#include "Framebuffer.h"
#include <GL/glew.h>
#include "Texture.h"
Framebuffer::Framebuffer(int width, int height) : width(width), height(height) {
glGenFramebuffers(1, &fbo);
bind();
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
texture = new Texture(tex, width, height);
glGenRenderbuffers(1, &depth);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
unbind();
}
Framebuffer::~Framebuffer() {
delete texture;
glDeleteFramebuffers(1, &fbo);
}
void Framebuffer::bind() {
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
void Framebuffer::unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

View File

@ -0,0 +1,20 @@
#ifndef SRC_GRAPHICS_FRAMEBUFFER_H_
#define SRC_GRAPHICS_FRAMEBUFFER_H_
class Texture;
class Framebuffer {
unsigned int fbo;
unsigned int depth;
public:
int width;
int height;
Texture* texture;
Framebuffer(int width, int height);
~Framebuffer();
void bind();
void unbind();
};
#endif /* SRC_GRAPHICS_FRAMEBUFFER_H_ */

17
src/graphics/Sprite.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "Sprite.h"
#include "Texture.h"
Sprite::Sprite(glm::vec2 position, glm::vec2 size, Texture* texture)
: position(position),
size(size),
origin(0.5f, 0.5f),
color(1.0f, 1.0f, 1.0f, 1.0f),
angle(0.0f),
texture(texture),
region() {
}
Sprite::~Sprite() {
}

29
src/graphics/Sprite.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef SRC_GRAPHICS_SPRITE_H_
#define SRC_GRAPHICS_SPRITE_H_
#include <glm/glm.hpp>
#include "UVRegion.h"
class Texture;
class Sprite {
public:
glm::vec2 position;
glm::vec2 size;
glm::vec2 origin;
glm::vec4 color;
float angle;
bool flippedX = false;
bool flippedY = false;
Texture* texture;
UVRegion region;
Sprite(glm::vec2 position, glm::vec2 size, Texture* texture);
virtual ~Sprite();
void setTexture(Texture* texture) {
this->texture = texture;
}
};
#endif /* SRC_GRAPHICS_SPRITE_H_ */

View File

@ -0,0 +1 @@
#include "UVRegion.h"

17
src/graphics/UVRegion.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef SRC_GRAPHICS_UVREGION_H_
#define SRC_GRAPHICS_UVREGION_H_
class UVRegion {
public:
float u1;
float v1;
float u2;
float v2;
UVRegion(float u1, float v1, float u2, float v2)
: u1(u1), v1(v1), u2(u2), v2(v2){}
UVRegion() : u1(0.0f), v1(0.0f), u2(1.0f), v2(1.0f){}
};
#endif /* SRC_GRAPHICS_UVREGION_H_ */

View File

@ -12,7 +12,7 @@
#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) #define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X))
#define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) #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 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 GET_CHUNK(X,Y,Z) (chunks[(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 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 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)])
@ -43,13 +43,7 @@ VoxelRenderer::VoxelRenderer() {
VoxelRenderer::~VoxelRenderer(){ VoxelRenderer::~VoxelRenderer(){
} }
inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
unsigned int id = vox.id;
if (!id){
return;
}
float l; float l;
float uvsize = 1.0f/16.0f; float uvsize = 1.0f/16.0f;
@ -61,10 +55,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[3]); SETUP_UV(block->textureFaces[3]);
float lr = LIGHT(x,y+1,z, 0) / 15.0f; const float lr = LIGHT(x,y+1,z, 0) / 15.0f;
float lg = LIGHT(x,y+1,z, 1) / 15.0f; const float lg = LIGHT(x,y+1,z, 1) / 15.0f;
float lb = LIGHT(x,y+1,z, 2) / 15.0f; const float lb = LIGHT(x,y+1,z, 2) / 15.0f;
float ls = LIGHT(x,y+1,z, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -99,10 +93,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[2]); SETUP_UV(block->textureFaces[2]);
float lr = LIGHT(x,y-1,z, 0) / 15.0f; const float lr = LIGHT(x,y-1,z, 0) / 15.0f;
float lg = LIGHT(x,y-1,z, 1) / 15.0f; const float lg = LIGHT(x,y-1,z, 1) / 15.0f;
float lb = LIGHT(x,y-1,z, 2) / 15.0f; const float lb = LIGHT(x,y-1,z, 2) / 15.0f;
float ls = LIGHT(x,y-1,z, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -138,10 +132,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[1]); SETUP_UV(block->textureFaces[1]);
float lr = LIGHT(x+1,y,z, 0) / 15.0f; const float lr = LIGHT(x+1,y,z, 0) / 15.0f;
float lg = LIGHT(x+1,y,z, 1) / 15.0f; const float lg = LIGHT(x+1,y,z, 1) / 15.0f;
float lb = LIGHT(x+1,y,z, 2) / 15.0f; const float lb = LIGHT(x+1,y,z, 2) / 15.0f;
float ls = LIGHT(x+1,y,z, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -176,10 +170,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[0]); SETUP_UV(block->textureFaces[0]);
float lr = LIGHT(x-1,y,z, 0) / 15.0f; const float lr = LIGHT(x-1,y,z, 0) / 15.0f;
float lg = LIGHT(x-1,y,z, 1) / 15.0f; const float lg = LIGHT(x-1,y,z, 1) / 15.0f;
float lb = LIGHT(x-1,y,z, 2) / 15.0f; const float lb = LIGHT(x-1,y,z, 2) / 15.0f;
float ls = LIGHT(x-1,y,z, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -215,10 +209,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[5]); SETUP_UV(block->textureFaces[5]);
float lr = LIGHT(x,y,z+1, 0) / 15.0f; const float lr = LIGHT(x,y,z+1, 0) / 15.0f;
float lg = LIGHT(x,y,z+1, 1) / 15.0f; const float lg = LIGHT(x,y,z+1, 1) / 15.0f;
float lb = LIGHT(x,y,z+1, 2) / 15.0f; const float lb = LIGHT(x,y,z+1, 2) / 15.0f;
float ls = LIGHT(x,y,z+1, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -253,10 +247,10 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
SETUP_UV(block->textureFaces[4]); SETUP_UV(block->textureFaces[4]);
float lr = LIGHT(x,y,z-1, 0) / 15.0f; const float lr = LIGHT(x,y,z-1, 0) / 15.0f;
float lg = LIGHT(x,y,z-1, 1) / 15.0f; const float lg = LIGHT(x,y,z-1, 1) / 15.0f;
float lb = LIGHT(x,y,z-1, 2) / 15.0f; const float lb = LIGHT(x,y,z-1, 2) / 15.0f;
float ls = LIGHT(x,y,z-1, 3) / 15.0f; const 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)) / 75.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)) / 75.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)) / 75.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)) / 75.0f;
@ -288,8 +282,82 @@ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const
} }
} }
inline void _renderBlockShadeless(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
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)){
SETUP_UV(block->textureFaces[3]);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, 1,1,1,0);
}
if (!IS_BLOCKED(x,y-1,z,group)){
SETUP_UV(block->textureFaces[2]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x+1,y,z,group)){
SETUP_UV(block->textureFaces[1]);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
}
if (!IS_BLOCKED(x-1,y,z,group)){
SETUP_UV(block->textureFaces[0]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x,y,z+1,group)){
SETUP_UV(block->textureFaces[5]);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x,y,z-1,group)){
SETUP_UV(block->textureFaces[4]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
}
}
inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){
@ -304,7 +372,6 @@ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const
return; return;
} }
float l;
float uvsize = 1.0f/16.0f; float uvsize = 1.0f/16.0f;
float lr = LIGHT(x,y,z, 0) / 15.0f; float lr = LIGHT(x,y,z, 0) / 15.0f;
@ -348,9 +415,6 @@ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const
float ls6 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f; float ls6 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f;
float ls7 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; float ls7 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f;
l = 0.95f;
{SETUP_UV(block->textureFaces[1]); {SETUP_UV(block->textureFaces[1]);
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr0,lg0,lb0,ls0); VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr0,lg0,lb0,ls0);
@ -361,9 +425,6 @@ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr2,lg2,lb2,ls2); VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr2,lg2,lb2,ls2);
VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr3,lg3,lb3,ls3);} VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr3,lg3,lb3,ls3);}
l = 0.85f;
{SETUP_UV(block->textureFaces[0]); {SETUP_UV(block->textureFaces[0]);
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr0,lg0,lb0,ls0); VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr0,lg0,lb0,ls0);
@ -374,9 +435,6 @@ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const
VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr3,lg3,lb3,ls3); VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr3,lg3,lb3,ls3);
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u2,v2, lr1,lg1,lb1,ls1);} VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u2,v2, lr1,lg1,lb1,ls1);}
l = 0.9f;
{SETUP_UV(block->textureFaces[5]); {SETUP_UV(block->textureFaces[5]);
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr4,lg4,lb4,ls4); VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr4,lg4,lb4,ls4);
@ -387,9 +445,6 @@ inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const
VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr7,lg7,lb7,ls7); VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr7,lg7,lb7,ls7);
VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u2,v2, lr5,lg5,lb5,ls5);} VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u2,v2, lr5,lg5,lb5,ls5);}
l = 0.8f;
{SETUP_UV(block->textureFaces[4]); {SETUP_UV(block->textureFaces[4]);
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr4,lg4,lb4,ls4); VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr4,lg4,lb4,ls4);
@ -408,9 +463,15 @@ const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& s
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
if (vox.id == 0)
continue;
if (vox.id == 9 || vox.id == 4 || vox.id == 12 || vox.id == 13) if (vox.id == 9 || vox.id == 4 || vox.id == 12 || vox.id == 13)
continue; continue;
_renderBlock(buffer, x, y, z, chunks, vox, index); Block* block = Block::blocks[vox.id];
if (block->emission[0] || block->emission[1] || block->emission[2]){
continue;
}
_renderBlock(buffer, x, y, z, chunks, vox.id, index);
} }
} }
} }
@ -419,9 +480,25 @@ const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& s
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
if (vox.id == 0)
continue;
Block* block = Block::blocks[vox.id];
if (block->emission[0] || block->emission[1] || block->emission[2]){
_renderBlockShadeless(buffer, x, y, z, chunks, vox.id, index);
}
}
}
}
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];
if (vox.id == 0)
continue;
if (vox.id != 9) if (vox.id != 9)
continue; continue;
_renderBlock(buffer, x, y, z, chunks, vox, index); _renderBlock(buffer, x, y, z, chunks, vox.id, index);
} }
} }
} }
@ -430,7 +507,9 @@ const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& s
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
if (vox.id != 12 && vox.id != 13) if (vox.id == 0)
continue;
if (Block::blocks[vox.id]->model != BLOCK_MODEL_GRASS)
continue; continue;
_renderXBlock(buffer, x, y, z, chunks, vox, index); _renderXBlock(buffer, x, y, z, chunks, vox, index);
} }
@ -441,9 +520,11 @@ const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& s
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
if (vox.id == 0)
continue;
if (vox.id != 4) if (vox.id != 4)
continue; continue;
_renderBlock(buffer, x, y, z, chunks, vox, index); _renderBlock(buffer, x, y, z, chunks, vox.id, index);
} }
} }
} }

View File

@ -12,6 +12,7 @@ class Chunk;
class VoxelRenderer { class VoxelRenderer {
public: public:
std::vector<float> buffer; std::vector<float> buffer;
unsigned char lights[27 * 4];
VoxelRenderer(); VoxelRenderer();
~VoxelRenderer(); ~VoxelRenderer();

View File

@ -1,12 +1,15 @@
#include "hud_render.h" #include "hud_render.h"
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Assets.h" #include "Assets.h"
#include "graphics/Shader.h" #include "graphics/Shader.h"
#include "graphics/Batch2D.h" #include "graphics/Batch2D.h"
#include "graphics/Font.h" #include "graphics/Font.h"
#include "graphics/Mesh.h"
#include "window/Camera.h" #include "window/Camera.h"
#include "window/Window.h" #include "window/Window.h"
#include "window/Events.h"
#include "voxels/Chunks.h" #include "voxels/Chunks.h"
#include "voxels/Block.h" #include "voxels/Block.h"
#include "world/World.h" #include "world/World.h"
@ -15,6 +18,19 @@
HudRenderer::HudRenderer() { HudRenderer::HudRenderer() {
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
};
crosshair = new Mesh(vertices, 4, attrs);
batch = new Batch2D(1024); batch = new Batch2D(1024);
uicamera = new Camera(glm::vec3(), Window::height / 1.0f); uicamera = new Camera(glm::vec3(), Window::height / 1.0f);
uicamera->perspective = false; uicamera->perspective = false;
@ -22,48 +38,103 @@ HudRenderer::HudRenderer() {
} }
HudRenderer::~HudRenderer() { HudRenderer::~HudRenderer() {
delete crosshair;
delete batch; delete batch;
delete uicamera; delete uicamera;
} }
void HudRenderer::drawDebug(Level* level, Assets* assets, int fps, bool occlusion){
void HudRenderer::draw(World* world, Level* level, Assets* assets, bool devdata, int fps){
Chunks* chunks = level->chunks; Chunks* chunks = level->chunks;
Player* player = level->player; Player* player = level->player;
glDisable(GL_DEPTH_TEST); Font* font = assets->getFont("normal");
glDisable(GL_CULL_FACE);
Shader* uishader = assets->getShader("ui"); Shader* uishader = assets->getShader("ui");
uishader->use(); uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView()); uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
batch->color = vec4(1.0f);
// Draw debug info
Font* font = assets->getFont("normal");
batch->begin(); batch->begin();
if (devdata){
font->draw(batch, L"chunks: "+std::to_wstring(chunks->chunksCount), 16, 16, STYLE_OUTLINE); font->draw(batch, L"chunks: "+std::to_wstring(chunks->chunksCount), 16, 16, STYLE_OUTLINE);
font->draw(batch, std::to_wstring((int)player->camera->position.x), 10, 30, STYLE_OUTLINE); font->draw(batch, std::to_wstring((int)player->camera->position.x), 10, 30, STYLE_OUTLINE);
font->draw(batch, std::to_wstring((int)player->camera->position.y), 50, 30, STYLE_OUTLINE); font->draw(batch, std::to_wstring((int)player->camera->position.y), 50, 30, STYLE_OUTLINE);
font->draw(batch, std::to_wstring((int)player->camera->position.z), 90, 30, STYLE_OUTLINE); font->draw(batch, std::to_wstring((int)player->camera->position.z), 90, 30, STYLE_OUTLINE);
font->draw(batch, L"fps:", 16, 42, STYLE_OUTLINE); font->draw(batch, L"fps:", 16, 42, STYLE_OUTLINE);
font->draw(batch, std::to_wstring(fps), 40, 42, STYLE_OUTLINE); font->draw(batch, std::to_wstring(fps), 44, 42, STYLE_OUTLINE);
} font->draw(batch, L"occlusion: "+std::to_wstring(occlusion), 16, 54, STYLE_OUTLINE);
batch->render(); batch->render();
}
void HudRenderer::draw(Level* level, Assets* assets){
uicamera->fov = Window::height;
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
Shader* uishader = assets->getShader("ui");
uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
// Chosen block preview // Chosen block preview
Texture* blocks = assets->getTexture("block"); Texture* blocks = assets->getTexture("block");
Texture* sprite = assets->getTexture("sprite"); Texture* sprite = assets->getTexture("slot");
if (!Events::_cursor_locked) {
batch->texture(nullptr);
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
batch->rect(0, 0, Window::width, Window::height);
}
batch->color = vec4(1.0f);
batch->texture(sprite); batch->texture(sprite);
batch->sprite(16, 640, 64, 64, 16, 0, vec4(1.0f)); batch->sprite(16, uicamera->fov - 80, 64, 64, 16, 0, vec4(1.0f));
batch->texture(blocks); batch->texture(blocks);
Player* player = level->player;
{
Block* cblock = Block::blocks[player->choosenBlock]; Block* cblock = Block::blocks[player->choosenBlock];
if (cblock->model == BLOCK_MODEL_CUBE){ if (cblock->model == BLOCK_MODEL_CUBE){
batch->blockSprite(24, 648, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); batch->blockSprite(24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f));
} else if (cblock->model == BLOCK_MODEL_GRASS){ } else if (cblock->model == BLOCK_MODEL_GRASS){
batch->sprite(24, 648, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); batch->sprite(24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f));
}
}
if (!Events::_cursor_locked) {
for (unsigned i = 1; i < 256; i++) {
Block* cblock = Block::blocks[i];
if (cblock == nullptr)
break;
int size = 48;
int step = 70;
int x = 24 + (i-1) * step;
int y = uicamera->fov - 72 - 70;
y -= 72 * (x / (Window::width - step));
x %= (Window::width - step);
vec4 tint(1.0f);
int mx = Events::x;
int my = Events::y;
if (mx > x && mx < x + size && my > y && my < y + size) {
tint.r *= 2.0f;
tint.g *= 2.0f;
tint.b *= 2.0f;
if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) {
player->choosenBlock = i;
}
}
if (cblock->model == BLOCK_MODEL_CUBE){
batch->blockSprite(x, y, size, size, 16, cblock->textureFaces, tint);
} else if (cblock->model == BLOCK_MODEL_GRASS){
batch->sprite(x, y, size, size, 16, cblock->textureFaces[3], tint);
}
}
} }
batch->render(); batch->render();
Shader* crosshairShader = assets->getShader("crosshair");
crosshairShader->use();
crosshairShader->uniform1f("u_ar", (float)Window::height / (float)Window::width);
crosshairShader->uniform1f("u_scale", 1.0f / ((float)Window::height / 1000.0f));
crosshair->draw(GL_LINES);
} }

View File

@ -3,17 +3,19 @@
class Batch2D; class Batch2D;
class Camera; class Camera;
class World;
class Level; class Level;
class Assets; class Assets;
class Mesh;
class HudRenderer { class HudRenderer {
Batch2D* batch; Batch2D* batch;
Camera* uicamera; Camera* uicamera;
Mesh* crosshair;
public: public:
HudRenderer(); HudRenderer();
~HudRenderer(); ~HudRenderer();
void draw(World* world, Level* level, Assets* assets, bool devdata, int fps); void draw(Level* level, Assets* assets);
void drawDebug(Level* level, Assets* assets, int fps, bool occlusion);
}; };
#endif /* SRC_HUD_RENDER_H_ */ #endif /* SRC_HUD_RENDER_H_ */

View File

@ -21,8 +21,8 @@ void LightSolver::add(int x, int y, int z, int emission) {
addqueue.push(entry); addqueue.push(entry);
Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z); Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z);
chunk->modified = true; chunk->setModified(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); chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y, entry.z-chunk->z*CHUNK_D, channel, entry.light);
} }
void LightSolver::add(int x, int y, int z) { void LightSolver::add(int x, int y, int z) {
@ -35,7 +35,7 @@ void LightSolver::remove(int x, int y, int z) {
if (chunk == nullptr) if (chunk == nullptr)
return; return;
int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel); int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel);
if (light == 0){ if (light == 0){
return; return;
} }
@ -47,7 +47,7 @@ void LightSolver::remove(int x, int y, int z) {
entry.light = light; entry.light = light;
remqueue.push(entry); 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); chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y, entry.z-chunk->z*CHUNK_D, channel, 0);
} }
void LightSolver::solve(){ void LightSolver::solve(){
@ -78,8 +78,8 @@ void LightSolver::solve(){
nentry.z = z; nentry.z = z;
nentry.light = light; nentry.light = light;
remqueue.push(nentry); remqueue.push(nentry);
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0); chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
chunk->modified = true; chunk->setModified(true);
} }
else if (light >= entry.light){ else if (light >= entry.light){
lightentry nentry; lightentry nentry;
@ -94,7 +94,7 @@ void LightSolver::solve(){
} }
while (!addqueue.empty()){ while (!addqueue.empty()){
lightentry entry = addqueue.front(); const lightentry entry = addqueue.front();
addqueue.pop(); addqueue.pop();
if (entry.light <= 1) if (entry.light <= 1)
@ -110,8 +110,8 @@ void LightSolver::solve(){
voxel* v = chunks->get(x,y,z); voxel* v = chunks->get(x,y,z);
Block* block = Block::blocks[v->id]; Block* block = Block::blocks[v->id];
if (block->lightPassing && light+2 <= entry.light){ 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->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, entry.light-1);
chunk->modified = true; chunk->setModified(true);
lightentry nentry; lightentry nentry;
nentry.x = x; nentry.x = x;
nentry.y = y; nentry.y = y;

View File

@ -35,154 +35,94 @@ void Lighting::clear(){
} }
} }
void Lighting::onChunkLoaded(int cx, int cy, int cz, bool sky){ void Lighting::prebuildSkyLight(int cx, int cz){
Chunk* chunk = chunks->getChunk(cx, cy, cz); Chunk* chunk = chunks->getChunk(cx, cz);
Chunk* chunkUpper = chunks->getChunk(cx, cy+1, cz); int highestPoint = 0;
Chunk* chunkLower = chunks->getChunk(cx, cy-1, cz);
if (chunkLower && sky){
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
int gx = x + cx * CHUNK_W;
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->skyLightPassing)
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 && sky){
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--){ for (int y = CHUNK_H-1;;y--){
if (y < 0){ if (y < 0)
ncy--;
y += CHUNK_H;
}
if (ncy != current->y)
current = chunks->getChunk(cx,ncy,cz);
if (!current)
break; break;
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz); voxel* vox = &(chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);
Block* block = Block::blocks[vox->id]; Block* block = Block::blocks[vox->id];
if (!block->skyLightPassing) if (!block->skyLightPassing) {
if (highestPoint < y)
highestPoint = y;
break; break;
current->lightmap->setS(x,y,z, 15);
current->modified = true;
solverS->add(gx,y+ncy*CHUNK_H,gz);
} }
} else if (light){ chunk->lightmap->setS(x,y,z, 15);
solverS->add(gx,gy+CHUNK_H,gz);
} }
} }
} }
} else if (sky){ if (highestPoint < CHUNK_H-1)
highestPoint++;
chunk->lightmap->highestPoint = highestPoint;
}
void Lighting::buildSkyLight(int cx, int cz){
Chunk* chunk = chunks->getChunk(cx, cz);
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
for (int y = chunk->lightmap->highestPoint; y >= 0; y--){
int gx = x + cx * CHUNK_W; int gx = x + cx * CHUNK_W;
int gz = z + cz * CHUNK_D; int gz = z + cz * CHUNK_D;
int ncy = cy; while (y > 0 && !Block::blocks[chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x].id]->lightPassing) {
y--;
}
if (chunk->lightmap->getS(x, y, z) != 15) {
solverS->add(gx,y+1,gz);
for (; y >= 0; y--){
solverS->add(gx+1,y,gz);
solverS->add(gx-1,y,gz);
solverS->add(gx,y,gz+1);
solverS->add(gx,y,gz-1);
}
}
}
}
}
solverS->solve();
}
void Lighting::onChunkLoaded(int cx, int cz){
const Chunk* chunk = chunks->getChunk(cx, cz);
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->skyLightPassing)
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 y = 0; y < CHUNK_H; y++){
for (unsigned int z = 0; z < CHUNK_D; z++){ for (unsigned int z = 0; z < CHUNK_D; z++){
for (unsigned int x = 0; x < CHUNK_W; x++){ for (unsigned int x = 0; x < CHUNK_W; x++){
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
Block* block = Block::blocks[vox.id]; Block* block = Block::blocks[vox.id];
int gx = x + cx * CHUNK_W;
int gz = z + cz * CHUNK_D;
if (block->emission[0] || block->emission[1] || block->emission[2]){ if (block->emission[0] || block->emission[1] || block->emission[2]){
int gx = x + cx * CHUNK_W; solverR->add(gx,y,gz,block->emission[0]);
int gy = y + cy * CHUNK_H; solverG->add(gx,y,gz,block->emission[1]);
int gz = z + cz * CHUNK_D; solverB->add(gx,y,gz,block->emission[2]);
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;
if (chunks->getLight(x,y,z)){
solverR->add(gx,gy,gz);
solverG->add(gx,gy,gz);
solverB->add(gx,gy,gz);
if (sky)
solverS->add(gx,gy,gz);
} }
} }
} }
} }
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 || z == -1 || z == CHUNK_D))
continue;
int gx = x + cx * CHUNK_W;
int gz = z + cz * CHUNK_D;
if (chunks->getLight(x,y,z)){
solverR->add(gx,y,gz);
solverG->add(gx,y,gz);
solverB->add(gx,y,gz);
solverS->add(gx,y,gz);
}
}
}
}
solverR->solve(); solverR->solve();
solverG->solve(); solverG->solve();
solverB->solve(); solverB->solve();
solverS->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){ void Lighting::onBlockSet(int x, int y, int z, int id){
@ -191,11 +131,9 @@ void Lighting::onBlockSet(int x, int y, int z, int id){
solverR->remove(x,y,z); solverR->remove(x,y,z);
solverG->remove(x,y,z); solverG->remove(x,y,z);
solverB->remove(x,y,z); solverB->remove(x,y,z);
solverR->solve(); solverR->solve();
solverG->solve(); solverG->solve();
solverB->solve(); solverB->solve();
if (chunks->getLight(x,y+1,z, 3) == 0xF){ if (chunks->getLight(x,y+1,z, 3) == 0xF){
for (int i = y; i >= 0; i--){ for (int i = y; i >= 0; i--){
voxel* vox = chunks->get(x,i,z); voxel* vox = chunks->get(x,i,z);
@ -204,14 +142,12 @@ void Lighting::onBlockSet(int x, int y, int z, int id){
solverS->add(x,i,z, 0xF); 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,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-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->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(); solverR->solve();
solverG->solve(); solverG->solve();
solverB->solve(); solverB->solve();

View File

@ -15,7 +15,9 @@ public:
~Lighting(); ~Lighting();
void clear(); void clear();
void onChunkLoaded(int cx, int cy, int cz, bool sky); void prebuildSkyLight(int cx, int cz);
void buildSkyLight(int cx, int cz);
void onChunkLoaded(int cx, int cz);
void onBlockSet(int x, int y, int z, int id); void onBlockSet(int x, int y, int z, int id);
}; };

View File

@ -6,6 +6,7 @@
class Lightmap { class Lightmap {
public: public:
unsigned short* map; unsigned short* map;
int highestPoint = 0;
Lightmap(); Lightmap();
~Lightmap(); ~Lightmap();

View File

@ -102,6 +102,8 @@ int _png_load(const char* file, int* width, int* height){
alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data); 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_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
@ -210,6 +212,8 @@ int _png_load(const char* file, int* pwidth, int* pheight){
alpha, GL_UNSIGNED_BYTE, (GLvoid *) flipped); alpha, GL_UNSIGNED_BYTE, (GLvoid *) flipped);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
pwidth[0] = ihdr.width; pwidth[0] = ihdr.width;

View File

@ -14,6 +14,7 @@ public:
Camera* camera; Camera* camera;
Hitbox* hitbox; Hitbox* hitbox;
bool flight = false; bool flight = false;
bool noclip = false;
int choosenBlock; int choosenBlock;
float camX, camY; float camX, camY;
float cameraShaking = 0.0f; float cameraShaking = 0.0f;

View File

@ -10,7 +10,9 @@
PhysicsSolver::PhysicsSolver(vec3 gravity) : gravity(gravity) { PhysicsSolver::PhysicsSolver(vec3 gravity) : gravity(gravity) {
} }
void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting, float gravityScale) { void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting,
float gravityScale,
bool collisions) {
hitbox->grounded = false; hitbox->grounded = false;
for (unsigned i = 0; i < substeps; i++){ for (unsigned i = 0; i < substeps; i++){
float dt = delta / (float)substeps; float dt = delta / (float)substeps;
@ -25,6 +27,7 @@ void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned s
float px = pos.x; float px = pos.x;
float pz = pos.z; float pz = pos.z;
if (collisions) {
if (vel.x < 0.0){ if (vel.x < 0.0){
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){ for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){ for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
@ -108,6 +111,7 @@ void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned s
} }
} }
} }
}
vel.x *= max(0.0, 1.0 - dt * linear_damping); vel.x *= max(0.0, 1.0 - dt * linear_damping);
vel.z *= max(0.0, 1.0 - dt * linear_damping); vel.z *= max(0.0, 1.0 - dt * linear_damping);

View File

@ -14,7 +14,13 @@ class PhysicsSolver {
vec3 gravity; vec3 gravity;
public: public:
PhysicsSolver(vec3 gravity); PhysicsSolver(vec3 gravity);
void step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting, float gravityScale); void step(Chunks* chunks,
Hitbox* hitbox,
float delta,
unsigned substeps,
bool shifting,
float gravityScale,
bool collisions);
bool isBlockInside(int x, int y, int z, Hitbox* hitbox); bool isBlockInside(int x, int y, int z, Hitbox* hitbox);
}; };

View File

@ -25,7 +25,7 @@
#define CAMERA_SHAKING_OFFSET_Y 0.031f #define CAMERA_SHAKING_OFFSET_Y 0.031f
#define CAMERA_SHAKING_SPEED 1.6f #define CAMERA_SHAKING_SPEED 1.6f
#define CAMERA_SHAKING_DELTA_K 10.0f #define CAMERA_SHAKING_DELTA_K 10.0f
#define FLIGHT_SPEED_MUL 8.0f #define FLIGHT_SPEED_MUL 4.0f
#define CHEAT_SPEED_MUL 5.0f #define CHEAT_SPEED_MUL 5.0f
#define JUMP_FORCE 7.0f #define JUMP_FORCE 7.0f
@ -35,13 +35,6 @@ PlayerController::PlayerController(Level* level) : level(level) {
void PlayerController::update_controls(float delta){ void PlayerController::update_controls(float delta){
Player* player = level->player; Player* player = level->player;
if (Events::jpressed(GLFW_KEY_ESCAPE)){
Window::setShouldClose(true);
}
if (Events::jpressed(GLFW_KEY_TAB)){
Events::toogleCursor();
}
for (int i = 1; i < 10; i++){ for (int i = 1; i < 10; i++){
if (Events::jpressed(GLFW_KEY_0+i)){ if (Events::jpressed(GLFW_KEY_0+i)){
player->choosenBlock = i; player->choosenBlock = i;
@ -65,7 +58,7 @@ void PlayerController::update_controls(float delta){
} }
int substeps = (int)(delta * 1000); int substeps = (int)(delta * 1000);
substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps)); substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps));
level->physics->step(level->chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f); level->physics->step(level->chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f, !player->noclip);
camera->position.x = hitbox->position.x; camera->position.x = hitbox->position.x;
camera->position.y = hitbox->position.y + 0.7f; camera->position.y = hitbox->position.y + 0.7f;
camera->position.z = hitbox->position.z; camera->position.z = hitbox->position.z;
@ -85,18 +78,20 @@ void PlayerController::update_controls(float delta){
camera->position += camera->up * abs(cos(shakeTimer)) * CAMERA_SHAKING_OFFSET_Y * player->cameraShaking; camera->position += camera->up * abs(cos(shakeTimer)) * CAMERA_SHAKING_OFFSET_Y * player->cameraShaking;
camera->position -= min(player->interpVel * 0.05f, 1.0f); camera->position -= min(player->interpVel * 0.05f, 1.0f);
if (Events::jpressed(GLFW_KEY_F)){ if ((Events::jpressed(GLFW_KEY_F) && !player->noclip) ||
(Events::jpressed(GLFW_KEY_N) && player->flight == player->noclip)){
player->flight = !player->flight; player->flight = !player->flight;
if (player->flight){ if (player->flight){
hitbox->velocity.y += 1; hitbox->velocity.y += 1;
hitbox->grounded = false; hitbox->grounded = false;
} }
} }
if (Events::jpressed(GLFW_KEY_N)) {
player->noclip = !player->noclip;
}
// Field of view manipulations // Field of view manipulations
float dt = min(1.0f, delta * ZOOM_SPEED); float dt = min(1.0f, delta * ZOOM_SPEED);
if (dt > 1.0f)
dt = 1.0f;
float zoomValue = 1.0f; float zoomValue = 1.0f;
if (shift){ if (shift){
speed *= CROUCH_SPEED_MUL; speed *= CROUCH_SPEED_MUL;
@ -182,7 +177,8 @@ void PlayerController::update_interaction(){
selectedBlockId = vox->id; selectedBlockId = vox->id;
selectedBlockPosition = iend; selectedBlockPosition = iend;
if (Events::jclicked(GLFW_MOUSE_BUTTON_1) && Block::blocks[vox->id]->breakable){ Block* block = Block::blocks[vox->id];
if (Events::jclicked(GLFW_MOUSE_BUTTON_1) && block->breakable){
int x = (int)iend.x; int x = (int)iend.x;
int y = (int)iend.y; int y = (int)iend.y;
int z = (int)iend.z; int z = (int)iend.z;
@ -193,6 +189,11 @@ void PlayerController::update_interaction(){
int x = (int)(iend.x)+(int)(norm.x); int x = (int)(iend.x)+(int)(norm.x);
int y = (int)(iend.y)+(int)(norm.y); int y = (int)(iend.y)+(int)(norm.y);
int z = (int)(iend.z)+(int)(norm.z); int z = (int)(iend.z)+(int)(norm.z);
if (block->model == BLOCK_MODEL_GRASS){
x = (int)iend.x;
y = (int)iend.y;
z = (int)iend.z;
}
if (!level->physics->isBlockInside(x,y,z, player->hitbox)){ if (!level->physics->isBlockInside(x,y,z, player->hitbox)){
chunks->set(x, y, z, player->choosenBlock); chunks->set(x, y, z, player->choosenBlock);
lighting->onBlockSet(x,y,z, player->choosenBlock); lighting->onBlockSet(x,y,z, player->choosenBlock);

View File

@ -24,6 +24,7 @@ using namespace glm;
#include "graphics/VoxelRenderer.h" #include "graphics/VoxelRenderer.h"
#include "graphics/LineBatch.h" #include "graphics/LineBatch.h"
#include "graphics/Batch2D.h" #include "graphics/Batch2D.h"
#include "graphics/Framebuffer.h"
#include "window/Window.h" #include "window/Window.h"
#include "window/Events.h" #include "window/Events.h"
#include "window/Camera.h" #include "window/Camera.h"
@ -54,13 +55,9 @@ using namespace glm;
#include "hud_render.h" #include "hud_render.h"
#include "player_control.h" #include "player_control.h"
float gravity = 19.6f;
int WIDTH = 1280; int WIDTH = 1280;
int HEIGHT = 720; int HEIGHT = 720;
// Save all world data to files // Save all world data to files
void write_world(World* world, Level* level){ void write_world(World* world, Level* level){
WorldFiles* wfile = world->wfile; WorldFiles* wfile = world->wfile;
@ -68,7 +65,7 @@ void write_world(World* world, Level* level){
for (unsigned int i = 0; i < chunks->volume; i++){ for (unsigned int i = 0; i < chunks->volume; i++){
Chunk* chunk = chunks->chunks[i]; Chunk* chunk = chunks->chunks[i];
if (chunk == nullptr) if (chunk == nullptr || !chunk->isUnsaved())
continue; continue;
wfile->put((const char*)chunk->voxels, chunk->x, chunk->z); wfile->put((const char*)chunk->voxels, chunk->x, chunk->z);
} }
@ -80,14 +77,15 @@ void write_world(World* world, Level* level){
void update_level(World* world, Level* level, float delta, long frame, VoxelRenderer* renderer) { void update_level(World* world, Level* level, float delta, long frame, VoxelRenderer* renderer) {
level->playerController->update_controls(delta); level->playerController->update_controls(delta);
if (Events::_cursor_locked)
level->playerController->update_interaction(); level->playerController->update_interaction();
vec3 position = level->player->hitbox->position; vec3 position = level->player->hitbox->position;
level->chunks->setCenter(world->wfile, position.x, 0, position.z); level->chunks->setCenter(world->wfile, position.x, position.z);
} }
Level* load_level(World* world, Player* player) { Level* load_level(World* world, Player* player) {
Level* level = new Level(world, player, new Chunks(34,1,34, 0,0,0), new PhysicsSolver(vec3(0, -gravity, 0))); Level* level = new Level(world, player, new Chunks(56, 56, 0, 0), new PhysicsSolver(vec3(0, -19.6f, 0)));
world->wfile->readPlayer(player); world->wfile->readPlayer(player);
Camera* camera = player->camera; Camera* camera = player->camera;
@ -96,10 +94,8 @@ Level* load_level(World* world, Player* player) {
return level; return level;
} }
int initialize(Assets*& assets) { int initialize(Assets*& assets) {
Audio::initialize(); Window::initialize(WIDTH, HEIGHT, "VoxelEngine-Cpp v12");
Window::initialize(WIDTH, HEIGHT, "VoxelEngine-Cpp v.12");
Events::initialize(); Events::initialize();
assets = new Assets(); assets = new Assets();
@ -113,6 +109,66 @@ int initialize(Assets*& assets){
return 0; return 0;
} }
void mainloop(Level* level, Assets* assets) {
Camera* camera = level->player->camera;
std::cout << "-- preparing systems" << std::endl;
World* world = level->world;
WorldRenderer worldRenderer(level, assets);
HudRenderer hud;
long frame = 0;
float lastTime = glfwGetTime();
float delta = 0.0f;
bool occlusion = true;
bool devdata = false;
Window::swapInterval(1);
while (!Window::isShouldClose()){
frame++;
float currentTime = glfwGetTime();
delta = currentTime - lastTime;
lastTime = currentTime;
int fps = 1 / delta;
if (Events::jpressed(GLFW_KEY_ESCAPE)){
Window::setShouldClose(true);
}
if (Events::jpressed(GLFW_KEY_TAB)){
Events::toogleCursor();
}
if (Events::jpressed(GLFW_KEY_O)){
occlusion = !occlusion;
}
if (Events::jpressed(GLFW_KEY_F3)){
devdata = !devdata;
}
if (Events::jpressed(GLFW_KEY_F5)){
for (unsigned i = 0; i < level->chunks->volume; i++) {
Chunk* chunk = level->chunks->chunks[i];
if (chunk != nullptr && chunk->isReady()){
chunk->setModified(true);
}
}
}
update_level(world, level, delta, frame, worldRenderer.renderer);
int freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->_buildMeshes(worldRenderer.renderer, frame);
freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->calculateLights();
freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->loadVisible(world->wfile);
worldRenderer.draw(world, camera, occlusion);
hud.draw(level, assets);
if (devdata) {
hud.drawDebug(level, assets, fps, occlusion);
}
Window::swapBuffers();
Events::pullEvents();
}
}
int main() { int main() {
setup_definitions(); setup_definitions();
@ -128,57 +184,12 @@ int main() {
Player* player = new Player(playerPosition, 4.0f, camera); Player* player = new Player(playerPosition, 4.0f, camera);
Level* level = load_level(world, player); Level* level = load_level(world, player);
std::cout << "-- preparing systems" << std::endl;
HudRenderer hud;
WorldRenderer worldRenderer(level);
float lastTime = glfwGetTime();
float delta = 0.0f;
long frame = 0;
bool occlusion = false;
bool devdata = false;
Window::swapInterval(1);
std::cout << "-- initializing finished" << std::endl; std::cout << "-- initializing finished" << std::endl;
while (!Window::isShouldClose()){
frame++;
float currentTime = glfwGetTime();
delta = currentTime - lastTime;
lastTime = currentTime;
int fps = 1 / delta;
if (Events::jpressed(GLFW_KEY_O)){ Audio::initialize();
occlusion = !occlusion; mainloop(level, assets);
} Audio::finalize();
if (Events::jpressed(GLFW_KEY_F3)){
devdata = !devdata;
}
update_level(world, level, delta, frame, worldRenderer.renderer);
int freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->_buildMeshes(worldRenderer.renderer, frame);
freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->loadVisible(world->wfile);
worldRenderer.draw(world, camera, assets, occlusion);
if (level->playerController->selectedBlockId != -1){
Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId];
LineBatch* lineBatch = worldRenderer.lineBatch;
vec3 pos = level->playerController->selectedBlockPosition;
if (selectedBlock->model == 1){
lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f);
} else if (selectedBlock->model == 2){
lineBatch->box(pos.x+0.4f, pos.y+0.3f, pos.z+0.4f, 0.805f,0.805f,0.805f, 0,0,0,0.5f);
}
}
hud.draw(world, level, assets, devdata, fps);
Window::swapBuffers();
Events::pullEvents();
}
std::cout << "-- saving world" << std::endl; std::cout << "-- saving world" << std::endl;
write_world(world, level); write_world(world, level);
@ -187,7 +198,6 @@ int main() {
std::cout << "-- shutting down" << std::endl; std::cout << "-- shutting down" << std::endl;
delete assets; delete assets;
Audio::finalize();
Events::finalize(); Events::finalize();
Window::terminate(); Window::terminate();
return 0; return 0;

View File

@ -2,8 +2,7 @@
#include "voxel.h" #include "voxel.h"
#include "../lighting/Lightmap.h" #include "../lighting/Lightmap.h"
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){
voxels = new voxel[CHUNK_VOL]; voxels = new voxel[CHUNK_VOL];
for (unsigned int i = 0; i < CHUNK_VOL; i++) for (unsigned int i = 0; i < CHUNK_VOL; i++)
voxels[i].id = 1; voxels[i].id = 1;
@ -30,7 +29,7 @@ bool Chunk::isEmpty(){
} }
Chunk* Chunk::clone() const { Chunk* Chunk::clone() const {
Chunk* other = new Chunk(x,y,z); Chunk* other = new Chunk(x,z);
for (int i = 0; i < CHUNK_VOL; i++) for (int i = 0; i < CHUNK_VOL; i++)
other->voxels[i] = voxels[i]; other->voxels[i] = voxels[i];
other->lightmap->set(lightmap); other->lightmap->set(lightmap);

View File

@ -8,6 +8,12 @@
#define CHUNK_D 16 #define CHUNK_D 16
#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D) #define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D)
#define CHUNK_MODIFIED 0x1
#define CHUNK_READY 0x2
#define CHUNK_LOADED 0x4
#define CHUNK_LIGHTED 0x8
#define CHUNK_UNSAVED 0x10
class voxel; class voxel;
class Lightmap; class Lightmap;
@ -16,19 +22,21 @@ struct RenderData {
size_t size; size_t size;
}; };
#define BIT_ON(f,i) do{f|= i;} while(0)
#define BIT_OFF(f,i) do{f&=~(i);} while(0)
#define BITSET(f,i,s) if (s) BIT_ON(f,i); else BIT_OFF(f,i);
class Chunk { class Chunk {
public: public:
int x,y,z; int x, z;
voxel* voxels; voxel* voxels;
Lightmap* lightmap; Lightmap* lightmap;
bool modified = true; int flags = 0;
bool ready = false;
bool loaded = false;
int surrounding = 0; int surrounding = 0;
int references = 1; int references = 1;
RenderData renderData; RenderData renderData;
Chunk(int x, int y, int z); Chunk(int x, int z);
~Chunk(); ~Chunk();
bool isEmpty(); bool isEmpty();
@ -36,6 +44,28 @@ public:
Chunk* clone() const; Chunk* clone() const;
void incref(); void incref();
void decref(); void decref();
// flags getters/setters below
inline bool isUnsaved() const {return flags & CHUNK_UNSAVED;}
inline bool isModified() const {return flags & CHUNK_MODIFIED;}
inline bool isLighted() const {return flags & CHUNK_LIGHTED;}
inline bool isLoaded() const {return flags & CHUNK_LOADED;}
inline bool isReady() const {return flags & CHUNK_READY;}
inline void setUnsaved(bool flag) {BITSET(flags, CHUNK_UNSAVED, flag);}
inline void setModified(bool flag) {BITSET(flags, CHUNK_MODIFIED, flag);}
inline void setLoaded(bool flag) {BITSET(flags, CHUNK_LOADED, flag);}
inline void setLighted(bool flag) {BITSET(flags, CHUNK_LIGHTED, flag);}
inline void setReady(bool flag) {BITSET(flags, CHUNK_READY, flag);}
}; };
#endif /* VOXELS_CHUNK_H_ */ #endif /* VOXELS_CHUNK_H_ */

View File

@ -11,8 +11,8 @@
#include <math.h> #include <math.h>
#include <limits.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){ Chunks::Chunks(int w, int d, int ox, int oz) : w(w), d(d), ox(ox), oz(oz){
volume = w*h*d; volume = w*d;
chunks = new Chunk*[volume]; chunks = new Chunk*[volume];
chunksSecond = new Chunk*[volume]; chunksSecond = new Chunk*[volume];
@ -36,7 +36,6 @@ Chunks::~Chunks(){
voxel* Chunks::get(int x, int y, int z){ voxel* Chunks::get(int x, int y, int z){
x -= ox * CHUNK_W; x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D; z -= oz * CHUNK_D;
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H; int cy = y / CHUNK_H;
@ -44,7 +43,7 @@ voxel* Chunks::get(int x, int y, int z){
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--; if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return nullptr; return nullptr;
Chunk* chunk = chunks[(cy * d + cz) * w + cx]; Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
@ -64,7 +63,6 @@ bool Chunks::isObstacle(int x, int y, int z){
unsigned char Chunks::getLight(int x, int y, int z, int channel){ unsigned char Chunks::getLight(int x, int y, int z, int channel){
x -= ox * CHUNK_W; x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D; z -= oz * CHUNK_D;
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H; int cy = y / CHUNK_H;
@ -72,7 +70,7 @@ unsigned char Chunks::getLight(int x, int y, int z, int channel){
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--; if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0; return 0;
Chunk* chunk = chunks[(cy * d + cz) * w + cx]; Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
@ -85,7 +83,6 @@ unsigned char Chunks::getLight(int x, int y, int z, int channel){
unsigned short Chunks::getLight(int x, int y, int z){ unsigned short Chunks::getLight(int x, int y, int z){
x -= ox * CHUNK_W; x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D; z -= oz * CHUNK_D;
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H; int cy = y / CHUNK_H;
@ -93,7 +90,7 @@ unsigned short Chunks::getLight(int x, int y, int z){
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--; if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0; return 0;
Chunk* chunk = chunks[(cy * d + cz) * w + cx]; Chunk* chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
@ -106,7 +103,6 @@ unsigned short Chunks::getLight(int x, int y, int z){
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
x -= ox * CHUNK_W; x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D; z -= oz * CHUNK_D;
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H; int cy = y / CHUNK_H;
@ -114,48 +110,44 @@ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--; if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return nullptr; return nullptr;
return chunks[(cy * d + cz) * w + cx]; return chunks[(cy * d + cz) * w + cx];
} }
Chunk* Chunks::getChunk(int x, int y, int z){ Chunk* Chunks::getChunk(int x, int z){
x -= ox; x -= ox;
y -= oy;
z -= oz; z -= oz;
if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d) if (x < 0 || z < 0 || x >= w || z >= d)
return nullptr; return nullptr;
return chunks[(y * d + z) * w + x]; return chunks[z * w + x];
} }
void Chunks::set(int x, int y, int z, int id){ void Chunks::set(int x, int y, int z, int id){
x -= ox * CHUNK_W; x -= ox * CHUNK_W;
y -= oy * CHUNK_H;
z -= oz * CHUNK_D; z -= oz * CHUNK_D;
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H; if (y < 0 || y >= CHUNK_H)
return;
int cz = z / CHUNK_D; int cz = z / CHUNK_D;
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) if (cx < 0 || cz < 0 || cx >= w || cz >= d)
return; return;
Chunk* chunk = chunks[(cy * d + cz) * w + cx]; Chunk* chunk = chunks[cz * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
return; return;
int lx = x - cx * CHUNK_W; int lx = x - cx * CHUNK_W;
int ly = y - cy * CHUNK_H;
int lz = z - cz * CHUNK_D; int lz = z - cz * CHUNK_D;
chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx].id = id; chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx].id = id;
chunk->modified = true; chunk->setUnsaved(true);
chunk->setModified(true);
if (lx == 0 && (chunk = getChunk(cx+ox-1, cy+oy, cz+oz))) chunk->modified = true; if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz))) chunk->setModified(true);
if (ly == 0 && (chunk = getChunk(cx+ox, cy+oy-1, cz+oz))) chunk->modified = true; if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1))) chunk->setModified(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 (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz))) chunk->setModified(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, cz+oz+1))) chunk->setModified(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) { voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, vec3& iend) {
@ -246,48 +238,42 @@ voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, v
return nullptr; return nullptr;
} }
void Chunks::setCenter(WorldFiles* worldFiles, int x, int y, int z) { void Chunks::setCenter(WorldFiles* worldFiles, int x, int z) {
int cx = x / CHUNK_W; int cx = x / CHUNK_W;
int cy = y / CHUNK_H;
int cz = z / CHUNK_D; int cz = z / CHUNK_D;
cx -= ox; cx -= ox;
cy -= oy;
cz -= oz; cz -= oz;
if (x < 0) cx--; if (x < 0) cx--;
if (y < 0) cy--;
if (z < 0) cz--; if (z < 0) cz--;
cx -= w/2; cx -= w/2;
cy -= h/2;
cz -= d/2; cz -= d/2;
if (cx != 0 || cy != 0 || cz != 0) if (cx | cz) {
translate(worldFiles, cx,cy,cz); translate(worldFiles, cx,cz);
}
} }
void Chunks::translate(WorldFiles* worldFiles, int dx, int dy, int dz){ void Chunks::translate(WorldFiles* worldFiles, int dx, int dz){
for (unsigned int i = 0; i < volume; i++){ for (unsigned int i = 0; i < volume; i++){
chunksSecond[i] = nullptr; chunksSecond[i] = nullptr;
meshesSecond[i] = nullptr; meshesSecond[i] = nullptr;
} }
for (unsigned int y = 0; y < h; y++){ for (int z = 0; z < d; z++){
for (unsigned int z = 0; z < d; z++){ for (int x = 0; x < w; x++){
for (unsigned int x = 0; x < w; x++){ Chunk* chunk = chunks[z * w + x];
Chunk* chunk = chunks[(y * d + z) * w + x];
int nx = x - dx; int nx = x - dx;
int ny = y - dy;
int nz = z - dz; int nz = z - dz;
if (chunk == nullptr) if (chunk == nullptr)
continue; continue;
Mesh* mesh = meshes[(y * d + z) * w + x]; Mesh* mesh = meshes[z * w + x];
if (nx < 0 || ny < 0 || nz < 0 || nx >= w || ny >= h || nz >= d){ if (nx < 0 || nz < 0 || nx >= w || nz >= d){
worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z); worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z);
chunk->decref(); chunk->decref();
delete mesh; delete mesh;
chunksCount--; chunksCount--;
continue; continue;
} }
meshesSecond[(ny * d + nz) * w + nx] = mesh; meshesSecond[nz * w + nx] = mesh;
chunksSecond[(ny * d + nz) * w + nx] = chunk; chunksSecond[nz * w + nx] = chunk;
}
} }
} }
Chunk** ctemp = chunks; Chunk** ctemp = chunks;
@ -299,26 +285,22 @@ void Chunks::translate(WorldFiles* worldFiles, int dx, int dy, int dz){
meshesSecond = mtemp; meshesSecond = mtemp;
ox += dx; ox += dx;
oy += dy;
oz += dz; oz += dz;
} }
void Chunks::_setOffset(int x, int y, int z){ void Chunks::_setOffset(int x, int z){
ox = x; ox = x;
oy = y;
oz = z; oz = z;
} }
bool Chunks::putChunk(Chunk* chunk) { bool Chunks::putChunk(Chunk* chunk) {
int x = chunk->x; int x = chunk->x;
int y = chunk->y;
int z = chunk->z; int z = chunk->z;
x -= ox; x -= ox;
y -= oy;
z -= oz; z -= oz;
if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d) if (x < 0 || z < 0 || x >= w || z >= d)
return false; return false;
chunks[(y * d + z) * w + x] = chunk; chunks[z * w + x] = chunk;
chunksCount++; chunksCount++;
return true; return true;
} }

View File

@ -21,15 +21,15 @@ public:
Mesh** meshesSecond; Mesh** meshesSecond;
size_t volume; size_t volume;
size_t chunksCount; size_t chunksCount;
unsigned int w,h,d; int w,d;
int ox,oy,oz; int ox,oz;
Chunks(int w, int h, int d, int ox, int oy, int oz); Chunks(int w, int d, int ox, int oz);
~Chunks(); ~Chunks();
bool putChunk(Chunk* chunk); bool putChunk(Chunk* chunk);
Chunk* getChunk(int x, int y, int z); Chunk* getChunk(int x, int z);
Chunk* getChunkByVoxel(int x, int y, int z); Chunk* getChunkByVoxel(int x, int y, int z);
voxel* get(int x, int y, int z); voxel* get(int x, int y, int z);
unsigned short getLight(int x, int y, int z); unsigned short getLight(int x, int y, int z);
@ -40,10 +40,10 @@ public:
bool isObstacle(int x, int y, int z); bool isObstacle(int x, int y, int z);
// does not move chunks inside // does not move chunks inside
void _setOffset(int x, int y, int z); void _setOffset(int x, int z);
void setCenter(WorldFiles* worldFiles, int x, int y, int z); void setCenter(WorldFiles* worldFiles, int x, int z);
void translate(WorldFiles* worldFiles, int x, int y, int z); void translate(WorldFiles* worldFiles, int x, int z);
void clear(bool freeMemory); void clear(bool freeMemory);
}; };

View File

@ -48,50 +48,78 @@ int ChunksController::countFreeLoaders(){
bool ChunksController::loadVisible(WorldFiles* worldFiles){ bool ChunksController::loadVisible(WorldFiles* worldFiles){
const int w = chunks->w; const int w = chunks->w;
const int h = chunks->h;
const int d = chunks->d; const int d = chunks->d;
const int ox = chunks->ox; const int ox = chunks->ox;
const int oy = chunks->oy;
const int oz = chunks->oz; const int oz = chunks->oz;
int nearX = 0; int nearX = 0;
int nearY = 0;
int nearZ = 0; int nearZ = 0;
int minDistance = (w/2)*(w/2); int minDistance = (w/2)*(w/2);
for (int y = 0; y < h; y++){
for (int z = 2; z < d-2; z++){ for (int z = 2; z < d-2; z++){
for (int x = 2; x < w-2; x++){ for (int x = 2; x < w-2; x++){
int index = (y * d + z) * w + x; int index = z * w + x;
Chunk* chunk = chunks->chunks[index]; Chunk* chunk = chunks->chunks[index];
if (chunk != nullptr){ if (chunk != nullptr){
int surrounding = 0; int surrounding = 0;
for (int oz = -1; oz <= 1; oz++){ for (int oz = -1; oz <= 1; oz++){
for (int ox = -1; ox <= 1; ox++){ for (int ox = -1; ox <= 1; ox++){
Chunk* other = chunks->getChunk(chunk->x+ox, chunk->y, chunk->z+oz); Chunk* other = chunks->getChunk(chunk->x+ox, chunk->z+oz);
if (other != nullptr && other->ready) surrounding++; if (other != nullptr && other->isReady()) surrounding++;
} }
} }
chunk->surrounding = surrounding; chunk->surrounding = surrounding;
continue; continue;
} }
int lx = x - w / 2; int lx = x - w / 2;
int ly = y - h / 2;
int lz = z - d / 2; int lz = z - d / 2;
int distance = (lx * lx + ly * ly + lz * lz); int distance = (lx * lx + lz * lz);
if (distance < minDistance){ if (distance < minDistance){
minDistance = distance; minDistance = distance;
nearX = x; nearX = x;
nearY = y;
nearZ = z; nearZ = z;
} }
} }
} }
}
int index = (nearY * d + nearZ) * w + nearX; int index = nearZ * w + nearX;
Chunk* chunk = chunks->chunks[index]; Chunk* chunk = chunks->chunks[index];
if (chunk != nullptr) if (chunk != nullptr)
return false; return false;
ChunksLoader* freeLoader = getFreeLoader();
if (freeLoader == nullptr)
return false;
chunk = new Chunk(nearX+ox, nearZ+oz);
if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels))
chunk->setLoaded(true);
chunks->putChunk(chunk);
Chunk* closes[9];
for (int i = 0; i < 9; i++)
closes[i] = nullptr;
for (size_t j = 0; j < chunks->volume; j++){
Chunk* other = chunks->chunks[j];
if (other == nullptr)
continue;
if (!other->isReady())
continue;
int ox = other->x - chunk->x;
int oz = other->z - chunk->z;
if (abs(ox) > 1 || abs(oz) > 1)
continue;
ox += 1;
oz += 1;
closes[oz * 3 + ox] = other;
}
freeLoader->load(chunk, (Chunk**)closes);
return true;
}
ChunksLoader* ChunksController::getFreeLoader() {
ChunksLoader* freeLoader = nullptr; ChunksLoader* freeLoader = nullptr;
for (int i = 0; i < loadersCount; i++){ for (int i = 0; i < loadersCount; i++){
ChunksLoader* loader = loaders[i]; ChunksLoader* loader = loaders[i];
@ -101,49 +129,69 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
freeLoader = loader; freeLoader = loader;
break; break;
} }
return freeLoader;
}
void ChunksController::calculateLights() {
ChunksLoader* freeLoader = getFreeLoader();
if (freeLoader == nullptr) if (freeLoader == nullptr)
return false; return;
chunk = new Chunk(nearX+ox,nearY+oy,nearZ+oz); const int w = chunks->w;
if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels)) const int d = chunks->d;
chunk->loaded = true; int nearX = 0;
int nearZ = 0;
chunks->putChunk(chunk); int minDistance = INT_MAX;
for (int z = 1; z < d-1; z++){
Chunk* closes[27]; for (int x = 1; x < w-1; x++){
for (int i = 0; i < 27; i++) int index = z * w + x;
Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr)
continue;
if (chunk->isLighted() || chunk->surrounding < MIN_SURROUNDING){
continue;
}
int lx = x - w / 2;
int lz = z - d / 2;
int distance = (lx * lx + lz * lz);
if (distance < minDistance){
minDistance = distance;
nearX = x;
nearZ = z;
}
}
}
int index = nearZ * w + nearX;
Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr)
return;
Chunk* closes[9];
for (int i = 0; i < 9; i++)
closes[i] = nullptr; closes[i] = nullptr;
for (size_t j = 0; j < chunks->volume; j++){ for (size_t j = 0; j < chunks->volume; j++){
Chunk* other = chunks->chunks[j]; Chunk* other = chunks->chunks[j];
if (other == nullptr) if (other == nullptr)
continue; continue;
if (!other->ready)
continue;
int ox = other->x - chunk->x; int ox = other->x - chunk->x;
int oy = other->y - chunk->y;
int oz = other->z - chunk->z; int oz = other->z - chunk->z;
if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1) if (abs(ox) > 1|| abs(oz) > 1)
continue; continue;
ox += 1; ox += 1;
oy += 1;
oz += 1; oz += 1;
closes[(oy * 3 + oz) * 3 + ox] = other; closes[oz * 3 + ox] = other;
} }
freeLoader->load(chunk, (Chunk**)closes); freeLoader->lights(chunk, (Chunk**)closes);
return true;
} }
bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) {
const int w = chunks->w; const int w = chunks->w;
const int h = chunks->h;
const int d = chunks->d; const int d = chunks->d;
for (int y = 0; y < h; y++){
for (int z = 1; z < d-1; z++){ for (int z = 1; z < d-1; z++){
for (int x = 1; x < w-1; x++){ for (int x = 1; x < w-1; x++){
int index = (y * d + z) * w + x; int index = z * w + x;
Chunk* chunk = chunks->chunks[index]; Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr) if (chunk == nullptr)
continue; continue;
@ -158,95 +206,75 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) {
} }
} }
} }
} ChunksLoader* freeLoader = getFreeLoader();
ChunksLoader* freeLoader = nullptr;
for (int i = 0; i < loadersCount; i++){
ChunksLoader* loader = loaders[i];
if (loader->isBusy()){
continue;
}
freeLoader = loader;
break;
}
if (freeLoader == nullptr) if (freeLoader == nullptr)
return false; return false;
int nearX = 0; int nearX = 0;
int nearY = 0;
int nearZ = 0; int nearZ = 0;
int minDistance = INT_MAX; int minDistance = INT_MAX;
for (int y = 0; y < h; y++){
for (int z = 1; z < d-1; z++){ for (int z = 1; z < d-1; z++){
for (int x = 1; x < w-1; x++){ for (int x = 1; x < w-1; x++){
int index = (y * d + z) * w + x; int index = z * w + x;
Chunk* chunk = chunks->chunks[index]; Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr) if (chunk == nullptr)
continue; continue;
Mesh* mesh = chunks->meshes[index]; Mesh* mesh = chunks->meshes[index];
if (mesh != nullptr && !chunk->modified) if (mesh != nullptr && !chunk->isModified())
continue; continue;
if (!chunk->ready || chunk->surrounding < MIN_SURROUNDING){ if (!chunk->isReady() || !chunk->isLighted() || chunk->surrounding < MIN_SURROUNDING){
continue; continue;
} }
int lx = x - w / 2; int lx = x - w / 2;
int ly = y - h / 2;
int lz = z - d / 2; int lz = z - d / 2;
int distance = (lx * lx + ly * ly + lz * lz); int distance = (lx * lx + lz * lz);
if (distance < minDistance){ if (distance < minDistance){
minDistance = distance; minDistance = distance;
nearX = x; nearX = x;
nearY = y;
nearZ = z; nearZ = z;
} }
} }
} }
} int index = nearZ * w + nearX;
int index = (nearY * d + nearZ) * w + nearX;
Chunk* chunk = chunks->chunks[index]; Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr){ if (chunk == nullptr){
return false; return false;
} }
Mesh* mesh = chunks->meshes[index]; Mesh* mesh = chunks->meshes[index];
if (mesh == nullptr || chunk->modified){ if (mesh == nullptr || chunk->isModified()){
Chunk* closes[27]; if (chunk->renderData.vertices != nullptr) {
return false;
}
Chunk* closes[9];
if (chunk->isEmpty()){ if (chunk->isEmpty()){
chunks->meshes[index] = nullptr; chunks->meshes[index] = nullptr;
return false; return false;
} }
chunk->modified = false;
for (int i = 0; i < 27; i++) for (int i = 0; i < 9; i++)
closes[i] = nullptr; closes[i] = nullptr;
for (size_t j = 0; j < chunks->volume; j++){ for (size_t j = 0; j < chunks->volume; j++){
Chunk* other = chunks->chunks[j]; Chunk* other = chunks->chunks[j];
if (other == nullptr) if (other == nullptr)
continue; continue;
if (!other->ready)
continue;
int ox = other->x - chunk->x; int ox = other->x - chunk->x;
int oy = other->y - chunk->y;
int oz = other->z - chunk->z; int oz = other->z - chunk->z;
if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1) if (abs(ox) > 1 || abs(oz) > 1)
continue; continue;
ox += 1; ox += 1;
oy += 1;
oz += 1; oz += 1;
closes[(oy * 3 + oz) * 3 + ox] = other; if ((!other->isReady() || !other->isLighted()) && other != chunk)
return false;
closes[oz * 3 + ox] = other;
} }
if (chunk->renderData.vertices == nullptr){ chunk->setModified(false);
chunk->renderData.vertices = (float*)1; chunk->renderData.vertices = (float*)1;
freeLoader->render(chunk, (Chunk**)closes); freeLoader->render(chunk, (Chunk**)closes);
return true; return true;
} }
//mesh = renderer->render(chunk, (const Chunk**)closes);
//chunks->meshes[index] = mesh;
}
return false; return false;
} }

View File

@ -18,8 +18,10 @@ public:
ChunksController(World* world, Chunks* chunks, Lighting* lighting); ChunksController(World* world, Chunks* chunks, Lighting* lighting);
~ChunksController(); ~ChunksController();
ChunksLoader* getFreeLoader();
int countFreeLoaders(); int countFreeLoaders();
bool loadVisible(WorldFiles* worldFiles); bool loadVisible(WorldFiles* worldFiles);
void calculateLights();
bool _buildMeshes(VoxelRenderer* renderer, int tick); bool _buildMeshes(VoxelRenderer* renderer, int tick);
}; };

View File

@ -12,10 +12,10 @@
#include <iostream> #include <iostream>
#define CLOSES_C 27 #define SURROUNDINGS_C 9
void ChunksLoader::_thread(){ void ChunksLoader::_thread(){
Chunks chunks(3,3,3, -1,-1,-1); Chunks chunks(3, 3, -1, -1);
Lighting lighting(&chunks); Lighting lighting(&chunks);
VoxelRenderer renderer; VoxelRenderer renderer;
while (state != OFF){ while (state != OFF){
@ -24,9 +24,9 @@ void ChunksLoader::_thread(){
continue; continue;
} }
Chunk* chunk = current; Chunk* chunk = current;
chunks._setOffset(chunk->x-1, chunk->y-1, chunk->z-1); chunks._setOffset(chunk->x-1, chunk->z-1);
for (size_t i = 0; i < CLOSES_C; i++){ for (size_t i = 0; i < SURROUNDINGS_C; i++){
Chunk* other = closes[i]; Chunk* other = surroundings[i];
if (other){ if (other){
chunks.putChunk(other); chunks.putChunk(other);
} }
@ -34,8 +34,9 @@ void ChunksLoader::_thread(){
if (state == LOAD){ if (state == LOAD){
chunks.putChunk(chunk); chunks.putChunk(chunk);
if (!chunk->loaded){ if (!chunk->isLoaded()){
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z, world->seed); WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, world->seed);
chunk->setUnsaved(true);
} }
for (size_t i = 0; i < CHUNK_VOL; i++){ for (size_t i = 0; i < CHUNK_VOL; i++){
@ -44,11 +45,17 @@ void ChunksLoader::_thread(){
chunk->voxels[i].id = 11; chunk->voxels[i].id = 11;
} }
} }
lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true); lighting.prebuildSkyLight(chunk->x, chunk->z);
}
else if (state == LIGHTS) {
lighting.buildSkyLight(chunk->x, chunk->z);
lighting.onChunkLoaded(chunk->x, chunk->z);
chunk->setLighted(true);
} }
else if (state == RENDER){ else if (state == RENDER){
chunk->setModified(false);
size_t size; size_t size;
renderer.render(chunk, (const Chunk**)(closes.load()), size); renderer.render(chunk, (const Chunk**)(surroundings.load()), size);
float* vertices = new float[size]; float* vertices = new float[size];
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
vertices[i] = renderer.buffer[i]; vertices[i] = renderer.buffer[i];
@ -57,33 +64,33 @@ void ChunksLoader::_thread(){
} }
chunks.clear(false); chunks.clear(false);
for (int i = 0; i < CLOSES_C; i++){ for (int i = 0; i < SURROUNDINGS_C; i++){
Chunk* other = closes[i]; Chunk* other = surroundings[i];
if (other) if (other)
other->decref(); other->decref();
} }
chunk->ready = true; chunk->setReady(true);
current = nullptr; current = nullptr;
chunk->decref(); chunk->decref();
} }
} }
void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode){ void ChunksLoader::perform(Chunk* chunk, Chunk** surroundings_passed, LoaderMode mode){
if (isBusy()){ if (isBusy()){
std::cerr << "performing while busy" << std::endl; std::cerr << "performing while busy" << std::endl;
return; return;
} }
chunk->incref(); chunk->incref();
if (closes == nullptr){ if (surroundings == nullptr){
closes = new Chunk*[CLOSES_C]; surroundings = new Chunk*[SURROUNDINGS_C];
} }
for (int i = 0; i < CLOSES_C; i++){ for (int i = 0; i < SURROUNDINGS_C; i++){
Chunk* other = closes_passed[i]; Chunk* other = surroundings_passed[i];
if (other == nullptr) if (other == nullptr)
closes[i] = nullptr; surroundings[i] = nullptr;
else { else {
other->incref(); other->incref();
closes[i] = other; surroundings[i] = other;
} }
} }
current = chunk; current = chunk;
@ -94,6 +101,10 @@ void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){
perform(chunk, closes_passed, LOAD); perform(chunk, closes_passed, LOAD);
} }
void ChunksLoader::lights(Chunk* chunk, Chunk** closes_passed){
perform(chunk, closes_passed, LIGHTS);
}
void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){ void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){
perform(chunk, closes_passed, RENDER); perform(chunk, closes_passed, RENDER);
} }

View File

@ -14,7 +14,7 @@ class Chunk;
class World; class World;
enum LoaderMode { enum LoaderMode {
OFF, IDLE, LOAD, RENDER, OFF, IDLE, LOAD, LIGHTS, RENDER,
}; };
class ChunksLoader final { class ChunksLoader final {
@ -22,7 +22,7 @@ private:
std::thread loaderThread; std::thread loaderThread;
void _thread(); void _thread();
std::atomic<Chunk*> current {nullptr}; std::atomic<Chunk*> current {nullptr};
std::atomic<Chunk**> closes {nullptr}; std::atomic<Chunk**> surroundings {nullptr};
std::atomic<LoaderMode> state {IDLE}; std::atomic<LoaderMode> state {IDLE};
World* world; World* world;
@ -41,6 +41,7 @@ public:
} }
void load(Chunk* chunk, Chunk** closes_passed); void load(Chunk* chunk, Chunk** closes_passed);
void lights(Chunk* chunk, Chunk** closes_passed);
void render(Chunk* chunk, Chunk** closes_passed); void render(Chunk* chunk, Chunk** closes_passed);
void stop(){ void stop(){

View File

@ -2,6 +2,7 @@
#include "voxel.h" #include "voxel.h"
#include "Chunk.h" #include "Chunk.h"
#include <iostream>
#include <math.h> #include <math.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/noise.hpp> #include <glm/gtc/noise.hpp>
@ -9,6 +10,8 @@
#include "../maths/FastNoiseLite.h" #include "../maths/FastNoiseLite.h"
#include <time.h> #include <time.h>
#include "../declarations.h"
class PseudoRandom { class PseudoRandom {
unsigned short seed; unsigned short seed;
public: public:
@ -64,7 +67,7 @@ float calc_height_faster(fnl_state *noise, int real_x, int real_z){
height *= 64.0f; height *= 64.0f;
return height; return height;
} }
#include <iostream>
int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights, int real_x, int real_y, int real_z, int tileSize){ int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights, int real_x, int real_y, int real_z, int tileSize){
const int tileX = floor((double)real_x/(double)tileSize); const int tileX = floor((double)real_x/(double)tileSize);
const int tileY = floor((double)real_z/(double)tileSize); const int tileY = floor((double)real_z/(double)tileSize);
@ -92,18 +95,14 @@ int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights,
return 0; return 0;
} }
void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz, int seed){ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
fnl_state noise = fnlCreateState(); fnl_state noise = fnlCreateState();
noise.noise_type = FNL_NOISE_OPENSIMPLEX2; noise.noise_type = FNL_NOISE_OPENSIMPLEX2;
noise.seed = seed * 60617077 % 25896307; noise.seed = seed * 60617077 % 25896307;
PseudoRandom randomtree; PseudoRandom randomtree;
// PseudoRandom random;
float heights[CHUNK_VOL]; float heights[CHUNK_VOL];
// std::cout << calc_height(&noise, cx, cy) << "\n";
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
for (int x = 0; x < CHUNK_W; x++){ for (int x = 0; x < CHUNK_W; x++){
int real_x = x + cx * CHUNK_W; int real_x = x + cx * CHUNK_W;
@ -120,14 +119,14 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz, int seed){
float height = heights[z*CHUNK_W+x]; float height = heights[z*CHUNK_W+x];
for (int y = 0; y < CHUNK_H; y++){ for (int y = 0; y < CHUNK_H; y++){
int real_y = y + cy * CHUNK_H; int real_y = y;
int id = real_y < 55 ? 9 : 0; int id = real_y < 55 ? BLOCK_WATER : BLOCK_AIR;
if ((real_y == (int)height) && (54 < real_y)) if ((real_y == (int)height) && (54 < real_y)) {
id = 2; id = BLOCK_GRASS_BLOCK;
else if (real_y < (height - 6)){ } else if (real_y < (height - 6)){
id = 8; id = BLOCK_STONE;
} else if (real_y < height){ } else if (real_y < height){
id = 1; id = BLOCK_DIRT;
} else { } else {
int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 16); int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 16);
if (tree) { if (tree) {
@ -139,15 +138,15 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz, int seed){
} }
} }
if ( ((height - (1.5 - 0.2 * pow(height - 54, 4))) < real_y) && (real_y < height)){ if ( ((height - (1.5 - 0.2 * pow(height - 54, 4))) < real_y) && (real_y < height)){
id = 10; id = BLOCK_SAND;
} }
if (real_y <= 2) if (real_y <= 2)
id = 11; id = BLOCK_BEDROCK;
if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 56000)){ if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 56000)){
id = 12; id = BLOCK_GRASS;
} }
if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 64000)){ if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 64000)){
id = 13; id = BLOCK_FLOWER;
} }
voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id; voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id;
} }

View File

@ -5,7 +5,7 @@ class voxel;
class WorldGenerator { class WorldGenerator {
public: public:
static void generate(voxel* voxels, int x, int y, int z, int seed); static void generate(voxel* voxels, int x, int z, int seed);
}; };
#endif /* VOXELS_WORLDGENERATOR_H_ */ #endif /* VOXELS_WORLDGENERATOR_H_ */

View File

@ -1,10 +1,3 @@
/*
* Camera.cpp
*
* Created on: Feb 11, 2020
* Author: MihailRis
*/
#include "Camera.h" #include "Camera.h"
#include "Window.h" #include "Window.h"
@ -36,7 +29,10 @@ void Camera::rotate(float x, float y, float z){
} }
mat4 Camera::getProjection(){ mat4 Camera::getProjection(){
float aspect = (float)Window::width / (float)Window::height; float aspect = this->aspect;
if (aspect == 0.0f){
aspect = (float)Window::width / (float)Window::height;
}
if (perspective) if (perspective)
return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f); return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f);
else else
@ -50,5 +46,5 @@ mat4 Camera::getView(){
if (perspective) if (perspective)
return glm::lookAt(position, position+front, up); return glm::lookAt(position, position+front, up);
else else
return glm::mat4(1.0f); return glm::translate(glm::mat4(1.0f), position);
} }

View File

@ -1,10 +1,3 @@
/*
* Camera.h
*
* Created on: Feb 11, 2020
* Author: MihailRis
*/
#ifndef WINDOW_CAMERA_H_ #ifndef WINDOW_CAMERA_H_
#define WINDOW_CAMERA_H_ #define WINDOW_CAMERA_H_
@ -25,6 +18,7 @@ public:
mat4 rotation; mat4 rotation;
bool perspective = true; bool perspective = true;
bool flipped = false; bool flipped = false;
float aspect = 0.0f;
Camera(vec3 position, float fov); Camera(vec3 position, float fov);
void rotate(float x, float y, float z); void rotate(float x, float y, float z);

View File

@ -41,6 +41,10 @@ int Window::initialize(int width, int height, const char* title){
return 0; return 0;
} }
void Window::viewport(int x, int y, int width, int height){
glViewport(x, y, width, height);
}
void Window::setCursorMode(int mode){ void Window::setCursorMode(int mode){
glfwSetInputMode(window, GLFW_CURSOR, mode); glfwSetInputMode(window, GLFW_CURSOR, mode);
} }

View File

@ -11,6 +11,7 @@ public:
static int initialize(int width, int height, const char* title); static int initialize(int width, int height, const char* title);
static void terminate(); static void terminate();
static void viewport(int x, int y, int width, int height);
static void setCursorMode(int mode); static void setCursorMode(int mode);
static bool isShouldClose(); static bool isShouldClose();
static void setShouldClose(bool flag); static void setShouldClose(bool flag);

View File

@ -4,6 +4,7 @@
#include "../player_control.h" #include "../player_control.h"
Level::Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics) : Level::Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics) :
world(world),
player(player), player(player),
chunks(chunks), chunks(chunks),
physics(physics) { physics(physics) {

View File

@ -11,6 +11,7 @@ class PlayerController;
class Level { class Level {
public: public:
World* world;
Player* player; Player* player;
Chunks* chunks; Chunks* chunks;
PhysicsSolver* physics; PhysicsSolver* physics;

View File

@ -1,5 +1,6 @@
#include "world_render.h" #include "world_render.h"
#include <iostream>
#include "graphics/VoxelRenderer.h" #include "graphics/VoxelRenderer.h"
#include "window/Window.h" #include "window/Window.h"
@ -11,38 +12,24 @@
#include "graphics/Batch3D.h" #include "graphics/Batch3D.h"
#include "voxels/Chunks.h" #include "voxels/Chunks.h"
#include "voxels/Chunk.h" #include "voxels/Chunk.h"
#include "voxels/Block.h"
#include "world/World.h" #include "world/World.h"
#include "world/Level.h" #include "world/Level.h"
#include "objects/Player.h"
#include "Assets.h" #include "Assets.h"
#include "player_control.h"
float _camera_cx; float _camera_cx;
float _camera_cz; float _camera_cz;
Mesh *crosshair; WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) {
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
};
WorldRenderer::WorldRenderer(Level* level) {
this->level = level;
crosshair = new Mesh(vertices, 4, attrs);
lineBatch = new LineBatch(4096); lineBatch = new LineBatch(4096);
batch3d = new Batch3D(1024); batch3d = new Batch3D(1024);
renderer = new VoxelRenderer(); renderer = new VoxelRenderer();
} }
WorldRenderer::~WorldRenderer() { WorldRenderer::~WorldRenderer() {
delete crosshair; delete batch3d;
delete lineBatch; delete lineBatch;
delete renderer; delete renderer;
} }
@ -50,71 +37,71 @@ WorldRenderer::~WorldRenderer() {
Chunks* _chunks = nullptr; Chunks* _chunks = nullptr;
bool chunks_distance_compare(size_t i, size_t j) { bool chunks_distance_compare(size_t i, size_t j) {
Chunks* chunks = _chunks; Chunk* a = _chunks->chunks[i];
Chunk* a = chunks->chunks[i]; Chunk* b = _chunks->chunks[j];
Chunk* b = chunks->chunks[j]; return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz) >
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz)
>
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz)); (b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
} }
void WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
Chunk* chunk = level->chunks->chunks[index]; Chunk* chunk = level->chunks->chunks[index];
Mesh* mesh = level->chunks->meshes[index]; Mesh* mesh = level->chunks->meshes[index];
if (mesh == nullptr) if (mesh == nullptr)
return; return false;
// Simple frustum culling (culling chunks behind the camera in 2D - XZ) // Simple frustum culling
if (occlusion){ if (occlusion){
const float cameraX = camera->position.x; float y = camera->position.y+camera->front.y * CHUNK_H * 0.5f;
const float cameraZ = camera->position.z; if (y < 0.0f)
const float camDirX = camera->dir.x; y = 0.0f;
const float camDirZ = camera->dir.z; if (y > CHUNK_H)
y = CHUNK_H;
bool unoccluded = false; vec3 v = vec3(chunk->x*CHUNK_W, y, chunk->z*CHUNK_D)-camera->position;
do { if (v.x*v.x+v.z*v.z > (CHUNK_W*3)*(CHUNK_W*3)) {
if ((chunk->x*CHUNK_W-cameraX)*camDirX + (chunk->z*CHUNK_D-cameraZ)*camDirZ >= 0.0){ if (dot(camera->front, v) < 0.0f){
unoccluded = true; break; return true;
} }
if (((chunk->x+1)*CHUNK_W-cameraX)*camDirX + (chunk->z*CHUNK_D-cameraZ)*camDirZ >= 0.0){
unoccluded = true; break;
} }
if (((chunk->x+1)*CHUNK_W-cameraX)*camDirX + ((chunk->z+1)*CHUNK_D-cameraZ)*camDirZ >= 0.0){
unoccluded = true; break;
}
if ((chunk->x*CHUNK_W-cameraX)*camDirX + ((chunk->z+1)*CHUNK_D-cameraZ)*camDirZ >= 0.0){
unoccluded = true; break;
}
} while (false);
if (!unoccluded)
return;
} }
mat4 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)); mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W+0.5f, 0.5f, chunk->z*CHUNK_D+0.5f));
shader->uniformMatrix("u_model", model); shader->uniformMatrix("u_model", model);
mesh->draw(GL_TRIANGLES); mesh->draw(GL_TRIANGLES);
return false;
} }
void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occlusion){
void WorldRenderer::draw(World* world, Camera* camera, bool occlusion){
Chunks* chunks = level->chunks; Chunks* chunks = level->chunks;
glClearColor(0.7f,0.81f,1.0f,1); vec4 skyColor(0.7f, 0.81f, 1.0f, 1.0f);
glClearColor(skyColor.r, skyColor.g, skyColor.b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Window::viewport(0, 0, Window::width, Window::height);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
Texture* texture = assets->getTexture("block"); Texture* texture = assets->getTexture("block");
Shader* shader = assets->getShader("main"); Shader* shader = assets->getShader("main");
Shader* crosshairShader = assets->getShader("crosshair");
Shader* linesShader = assets->getShader("lines"); Shader* linesShader = assets->getShader("lines");
shader->use(); shader->use();
shader->uniformMatrix("u_proj", camera->getProjection()); shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView()); shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", 1.6f); shader->uniform1f("u_gamma", 1.6f);
shader->uniform3f("u_skyLightColor", 2.2f,2.2f,2.2f); shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f);
shader->uniform3f("u_fogColor", 0.7f,0.81f,1.0f); shader->uniform3f("u_fogColor", skyColor.r,skyColor.g,skyColor.b);
shader->uniform1f("u_fogFactor", 0.03f); shader->uniform1f("u_fogFactor", 0.025f);
shader->uniform3f("u_cameraPos", camera->position.x,camera->position.y,camera->position.z); shader->uniform3f("u_cameraPos", camera->position.x,camera->position.y,camera->position.z);
Block* cblock = Block::blocks[level->player->choosenBlock];
shader->uniform3f("u_torchlightColor",
cblock->emission[0] / 15.0f,
cblock->emission[1] / 15.0f,
cblock->emission[2] / 15.0f);
shader->uniform1f("u_torchlightDistance", 6.0f);
shader->uniform1f("u_fogFactor", 0.025f);
texture->bind(); texture->bind();
std::vector<size_t> indices; std::vector<size_t> indices;
@ -136,8 +123,9 @@ void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occl
std::sort(indices.begin(), indices.end(), chunks_distance_compare); std::sort(indices.begin(), indices.end(), chunks_distance_compare);
int occludedChunks = 0;
for (size_t i = 0; i < indices.size(); i++){ for (size_t i = 0; i < indices.size(); i++){
drawChunk(indices[i], camera, shader, occlusion); occludedChunks += drawChunk(indices[i], camera, shader, occlusion);
} }
shader->uniformMatrix("u_model", mat4(1.0f)); shader->uniformMatrix("u_model", mat4(1.0f));
@ -145,11 +133,6 @@ void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occl
// draw 3D stuff here // draw 3D stuff here
batch3d->render(); batch3d->render();
crosshairShader->use();
crosshairShader->uniform1f("u_ar", (float)Window::height / (float)Window::width);
crosshairShader->uniform1f("u_scale", 1.0f / ((float)Window::height / 1000.0f));
crosshair->draw(GL_LINES);
linesShader->use(); linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView()); linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView());
glLineWidth(2.0f); glLineWidth(2.0f);
@ -157,4 +140,14 @@ void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occl
lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f, camera->position.z+0.01f, 0, 0, 1, 1); lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f, camera->position.z+0.01f, 0, 0, 1, 1);
lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f+0.01f, camera->position.z, 0, 1, 0, 1); lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f+0.01f, camera->position.z, 0, 1, 0, 1);
lineBatch->render(); lineBatch->render();
if (level->playerController->selectedBlockId != -1){
Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId];
vec3 pos = level->playerController->selectedBlockPosition;
if (selectedBlock->model == 1){
lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f);
} else if (selectedBlock->model == 2){
lineBatch->box(pos.x+0.4f, pos.y+0.3f, pos.z+0.4f, 0.805f,0.805f,0.805f, 0,0,0,0.5f);
}
}
} }

View File

@ -21,21 +21,23 @@ class LineBatch;
class Batch3D; class Batch3D;
class VoxelRenderer; class VoxelRenderer;
class Shader; class Shader;
class Texture;
class Framebuffer;
class WorldRenderer { class WorldRenderer {
Batch3D *batch3d; Batch3D *batch3d;
Assets* assets;
Level* level; Level* level;
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
void drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
public: public:
VoxelRenderer *renderer; VoxelRenderer *renderer;
LineBatch *lineBatch; LineBatch *lineBatch;
WorldRenderer(Level* level); WorldRenderer(Level* level, Assets* assets);
~WorldRenderer(); ~WorldRenderer();
void draw(World* world, Camera* camera, Assets* assets, bool occlusion); void draw(World* world, Camera* camera, bool occlusion);
}; };