diff --git a/Debug/src/graphics/subdir.mk b/Debug/src/graphics/subdir.mk index 73d9da31..743d753c 100644 --- a/Debug/src/graphics/subdir.mk +++ b/Debug/src/graphics/subdir.mk @@ -11,6 +11,9 @@ CPP_SRCS += \ ../src/graphics/Mesh.cpp \ ../src/graphics/Shader.cpp \ ../src/graphics/Texture.cpp \ +../src/graphics/Sprite.cpp \ +../src/graphics/UVRegion.cpp \ +../src/graphics/Framebuffer.cpp \ ../src/graphics/VoxelRenderer.cpp OBJS += \ @@ -21,6 +24,9 @@ OBJS += \ ./src/graphics/Mesh.o \ ./src/graphics/Shader.o \ ./src/graphics/Texture.o \ +./src/graphics/Sprite.o \ +./src/graphics/UVRegion.o \ +./src/graphics/Framebuffer.o \ ./src/graphics/VoxelRenderer.o CPP_DEPS += \ @@ -31,6 +37,9 @@ CPP_DEPS += \ ./src/graphics/Mesh.d \ ./src/graphics/Shader.d \ ./src/graphics/Texture.d \ +./src/graphics/Sprite.d \ +./src/graphics/UVRegion.d \ +./src/graphics/Framebuffer.d \ ./src/graphics/VoxelRenderer.d diff --git a/Debug/src/subdir.mk b/Debug/src/subdir.mk index 68c2121d..60c123c4 100644 --- a/Debug/src/subdir.mk +++ b/Debug/src/subdir.mk @@ -8,6 +8,7 @@ CPP_SRCS += \ ../src/player_control.cpp \ ../src/hud_render.cpp \ ../src/world_render.cpp \ +../src/declarations.cpp \ ../src/voxel_engine.cpp OBJS += \ @@ -15,6 +16,7 @@ OBJS += \ ./src/player_control.o \ ./src/hud_render.o \ ./src/world_render.o \ +./src/declarations.o \ ./src/voxel_engine.o CPP_DEPS += \ @@ -22,6 +24,7 @@ CPP_DEPS += \ ./src/player_control.d \ ./src/hud_render.d \ ./src/world_render.d \ +./src/declarations.d \ ./src/voxel_engine.d diff --git a/res/block.png b/res/block.png index eb0535cd..e7c090d1 100644 Binary files a/res/block.png and b/res/block.png differ diff --git a/res/img.png b/res/img.png index f7704de1..63e4fba6 100644 Binary files a/res/img.png and b/res/img.png differ diff --git a/res/main.glslf b/res/main.glslf index 9f56df09..9127e7ac 100644 --- a/res/main.glslf +++ b/res/main.glslf @@ -11,10 +11,11 @@ uniform float u_fogFactor; void main(){ vec4 tex_color = texture(u_texture0, a_texCoord); - //if (tex_color.a < 0.5) - // discard; - float depth = (a_distance/256.0)*(a_distance/256.0)*256.0/6; + float depth = (a_distance/256.0); 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.a = alpha; } diff --git a/res/main.glslv b/res/main.glslv index 8f3e237e..98a7acc3 100644 --- a/res/main.glslv +++ b/res/main.glslv @@ -15,12 +15,19 @@ uniform vec3 u_skyLightColor; uniform vec3 u_cameraPos; uniform float u_gamma; +uniform vec3 u_torchlightColor; +uniform float u_torchlightDistance; + void main(){ 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); - a_color = vec4(pow(v_light.rgb, vec3(u_gamma)),1.0f); + vec4 modelpos = u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0); + 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_color.rgb += u_skyLightColor * v_light.a*0.5; - a_distance = length(viewmodelpos); + a_color.rgb += u_skyLightColor * v_light.a; + a_distance = pow(length(viewmodelpos), 1.5); gl_Position = u_proj * viewmodelpos; } diff --git a/res/sprite.png b/res/slot.png similarity index 100% rename from res/sprite.png rename to res/slot.png diff --git a/res/ui.glslv b/res/ui.glslv index a9110954..2b65d101 100644 --- a/res/ui.glslv +++ b/res/ui.glslv @@ -12,5 +12,5 @@ uniform mat4 u_projview; void main(){ a_textureCoord = v_textureCoord; 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); } diff --git a/src/audio/Audio.cpp b/src/audio/Audio.cpp index 1dec8ff8..5562d2e9 100644 --- a/src/audio/Audio.cpp +++ b/src/audio/Audio.cpp @@ -15,7 +15,7 @@ std::vector Audio::freesources; std::vector Audio::allbuffers; std::vector Audio::freebuffers; -bool ALSource::setBuffer(ALBuffer* buffer){ +bool ALSource::setBuffer(ALBuffer* buffer) { alSourcei(id, AL_BUFFER, buffer->id); return alCheck(); } @@ -25,17 +25,23 @@ bool ALSource::play(){ return alCheck(); } -bool ALSource::setPosition(glm::vec3 position){ +bool ALSource::isPlaying() { + int state; + alGetSourcei(id, AL_SOURCE_STATE, &state); + return state == AL_PLAYING; +} + +bool ALSource::setPosition(glm::vec3 position) { alSource3f(id, AL_POSITION, position.x, position.y, position.z); return alCheck(); } -bool ALSource::setVelocity(glm::vec3 velocity){ +bool ALSource::setVelocity(glm::vec3 velocity) { alSource3f(id, AL_VELOCITY, velocity.x, velocity.y, velocity.z); return alCheck(); } -bool ALSource::setLoop(bool loop){ +bool ALSource::setLoop(bool loop) { alSourcei(id, AL_LOOPING, AL_TRUE ? loop : AL_FALSE); return alCheck(); } @@ -51,13 +57,13 @@ bool ALSource::setPitch(float pitch) { return alCheck(); } -bool ALBuffer::load(int format, const char* data, int size, int freq){ +bool ALBuffer::load(int format, const char* data, int size, int freq) { alBufferData(id, format, data, size, freq); return alCheck(); } -bool Audio::initialize(){ +bool Audio::initialize() { device = alcOpenDevice(nullptr); if (device == nullptr) return false; @@ -84,7 +90,9 @@ bool Audio::initialize(){ void Audio::finalize(){ for (ALSource* source : allsources){ - alSourceStop(source->id); alCheck(); + if (source->isPlaying()){ + alSourceStop(source->id); alCheck(); + } alDeleteSources(1, &source->id); alCheck(); } @@ -168,7 +176,7 @@ bool Audio::get_available_devices(std::vector& devicesVec){ 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 }; alListener3f(AL_POSITION, position.x, position.y, position.z); diff --git a/src/audio/Audio.h b/src/audio/Audio.h index 9861c0bb..af0663f3 100644 --- a/src/audio/Audio.h +++ b/src/audio/Audio.h @@ -16,6 +16,7 @@ struct ALSource { ALuint id; ALSource(ALuint id) : id(id) {} + bool isPlaying(); bool setPosition(glm::vec3 position); bool setVelocity(glm::vec3 velocity); bool setBuffer(ALBuffer* buffer); @@ -54,7 +55,7 @@ public: static void finalize(); static bool get_available_devices(std::vector& 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); }; diff --git a/src/declarations.cpp b/src/declarations.cpp new file mode 100644 index 00000000..ddb6bd1d --- /dev/null +++ b/src/declarations.cpp @@ -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 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; +} diff --git a/src/declarations.h b/src/declarations.h index 03491fd7..13ff14be 100644 --- a/src/declarations.h +++ b/src/declarations.h @@ -2,164 +2,29 @@ #define DECLARATIONS_H #include -#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 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 diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index f9ae26ba..84388a72 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -19,6 +19,9 @@ union { #define SECTION_POSITION 1 #define SECTION_ROTATION 2 +#define SECTION_FLAGS 3 +#define PLAYER_FLAG_FLIGHT 0x1 +#define PLAYER_FLAG_NOCLIP 0x2 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); } -void float2Bytes(float fvalue, char* dest, unsigned int offset){ +void floatToBytes(float fvalue, char* dest, unsigned int offset){ uint32_t value = *((uint32_t*)&fvalue); dest[offset] = (char) (value >> 24 & 255); dest[offset+1] = (char) (value >> 16 & 255); @@ -58,15 +61,15 @@ WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : direc WorldFiles::~WorldFiles(){ delete[] mainBufferIn; delete[] mainBufferOut; - std::unordered_map::iterator it; + std::unordered_map::iterator it; for (it = regions.begin(); it != regions.end(); it++){ - char** region = it->second; - if (region == nullptr) + WorldRegion region = it->second; + if (region.chunksData == nullptr) continue; for (unsigned int i = 0; i < REGION_VOL; i++){ - delete[] region[i]; + delete[] region.chunksData[i]; } - delete[] region; + delete[] region.chunksData; } regions.clear(); } @@ -82,17 +85,17 @@ void WorldFiles::put(const char* chunkData, int x, int y){ _tempcoords._coords[0] = regionX; _tempcoords._coords[1] = regionY; - char** region = regions[_tempcoords._key]; - if (region == nullptr){ - region = new char*[REGION_VOL]; + WorldRegion& region = regions[_tempcoords._key]; + region.unsaved = true; + if (region.chunksData == nullptr){ + region.chunksData = new char*[REGION_VOL]; for (unsigned int i = 0; i < REGION_VOL; i++) - region[i] = nullptr; - regions[_tempcoords._key] = region; + region.chunksData[i] = nullptr; } - char* targetChunk = region[localY * REGION_SIZE + localX]; + char* targetChunk = region.chunksData[localY * REGION_SIZE + localX]; if (targetChunk == nullptr){ targetChunk = new char[CHUNK_VOL]; - region[localY * REGION_SIZE + localX] = targetChunk; + region.chunksData[localY * REGION_SIZE + localX] = targetChunk; totalCompressed += CHUNK_VOL; } 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[1] = regionY; - char** region = regions[_tempcoords._key]; - if (region == nullptr) + WorldRegion& region = regions[_tempcoords._key]; + if (region.chunksData == nullptr) return readChunk(x,y,out); - char* chunk = region[chunkIndex]; + char* chunk = region.chunksData[chunkIndex]; if (chunk == nullptr) return readChunk(x,y,out); 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(){ - std::unordered_map::iterator it; + std::unordered_map::iterator it; for (it = regions.begin(); it != regions.end(); it++){ - if (it->second == nullptr) + if (it->second.chunksData == nullptr || !it->second.unsaved) continue; int x; int y; 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); } } 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; size_t offset = 0; dst[offset++] = SECTION_POSITION; - float2Bytes(position.x, dst, offset); offset += 4; - float2Bytes(position.y, dst, offset); offset += 4; - float2Bytes(position.z, dst, offset); offset += 4; + floatToBytes(position.x, dst, offset); offset += 4; + floatToBytes(position.y, dst, offset); offset += 4; + floatToBytes(position.z, dst, offset); offset += 4; dst[offset++] = SECTION_ROTATION; - float2Bytes(player->camX, dst, offset); offset += 4; - float2Bytes(player->camY, dst, offset); offset += 4; + floatToBytes(player->camX, 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)); } @@ -227,6 +234,13 @@ bool WorldFiles::readPlayer(Player* player) { player->camX = bytes2Float(data, offset); offset += 4; player->camY = bytes2Float(data, offset); offset += 4; 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; diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 9ee11778..93d50db0 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -12,15 +12,15 @@ class Player; #define REGION_SIZE (1 << (REGION_SIZE_BIT)) #define REGION_VOL ((REGION_SIZE) * (REGION_SIZE)) -/* Требование: - * - высота мира = 1 чанк (любых размеров) - * Пример: - * - CHUNK_W = 16, CHUNK_H = 128, CHUNK_D = 16 - * */ +struct WorldRegion { + char** chunksData; + bool unsaved; +}; + class WorldFiles { public: static unsigned long totalCompressed; - std::unordered_map regions; + std::unordered_map regions; std::string directory; char* mainBufferIn; char* mainBufferOut; diff --git a/src/files/files.cpp b/src/files/files.cpp index 2344128b..783faa2a 100644 --- a/src/files/files.cpp +++ b/src/files/files.cpp @@ -69,16 +69,17 @@ unsigned int decompressRLE(const char* src, unsigned int length, char* dst, unsi unsigned int calcRLE(const char* src, unsigned int length) { unsigned int offset = 0; - unsigned int counter = 1; + unsigned int counter = 0; char c = src[0]; for (unsigned int i = 0; i < length; i++){ char cnext = src[i]; - if (cnext != c || counter == 256){ + if (cnext != c || counter == 255){ offset += 2; c = cnext; counter = 0; + } else { + counter++; } - counter++; } return offset + 2; } @@ -86,19 +87,20 @@ unsigned int calcRLE(const char* src, unsigned int length) { // max result size = length * 2; returns compressed length unsigned int compressRLE(const char* src, unsigned int length, char* dst) { unsigned int offset = 0; - unsigned int counter = 1; + unsigned int counter = 0; char c = src[0]; for (unsigned int i = 1; i < length; i++){ char cnext = src[i]; - if (cnext != c || counter == 256){ - dst[offset++] = counter-1; + if (cnext != c || counter == 255){ + dst[offset++] = counter; dst[offset++] = c; c = cnext; counter = 0; + } else { + counter++; } - counter++; } - dst[offset++] = counter-1; + dst[offset++] = counter; dst[offset++] = c; return offset; } diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index 4cde0087..acb9f2ec 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -1,6 +1,7 @@ #include "Batch2D.h" #include "Mesh.h" #include "Texture.h" +#include "Sprite.h" #include @@ -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); } +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){ float scale = 1.0f / (float)atlasRes; 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 uf = (index[0] % atlasRes) * 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(); - vec2 points[7] = {vec2(x+(w*0.5f), y+(h*0.5f)), - vec2(x, y+(h*0.25f)), - vec2(x+(w*0.5f), y), - vec2(x+w, y+(h*0.25f)), - vec2(x+w, y+(h*0.75f)), - vec2(x+(w*0.5f), y+h), - vec2(x, y+(h*0.75f))}; + float ar = 0.88f; + float ox = x + (w * 0.5f); + float sx = w * 0.5f * ar; + vec2 points[7] = {vec2(ox, y+(h*0.5f)), + vec2(ox-sx, y+(h*0.25f)), + vec2(ox, y), + 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(uu+scale, vu), diff --git a/src/graphics/Batch2D.h b/src/graphics/Batch2D.h index 814305f9..0c9b69e8 100644 --- a/src/graphics/Batch2D.h +++ b/src/graphics/Batch2D.h @@ -4,16 +4,18 @@ #include #include +#include "UVRegion.h" + using namespace glm; class Mesh; class Texture; +class Sprite; class Batch2D { float* buffer; size_t capacity; size_t offset; - glm::vec4 color; Mesh* mesh; size_t index; @@ -28,13 +30,23 @@ class Batch2D { float r, float g, float b, float a); public: + glm::vec4 color; + Batch2D(size_t capacity); ~Batch2D(); void begin(); void texture(Texture* texture); 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 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, float u, float v, float tx, float ty, diff --git a/src/graphics/Batch3D.cpp b/src/graphics/Batch3D.cpp index 40c91cb6..2531969a 100644 --- a/src/graphics/Batch3D.cpp +++ b/src/graphics/Batch3D.cpp @@ -7,7 +7,7 @@ #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[] = { 3, 2, 4, 0 //null terminator }; diff --git a/src/graphics/Font.cpp b/src/graphics/Font.cpp index 96d9c30e..3e881503 100644 --- a/src/graphics/Font.cpp +++ b/src/graphics/Font.cpp @@ -19,9 +19,9 @@ int Font::getGlyphWidth(char c) { case '.': case ',': case ':': - case ';': return 3; - case 't': return 5; - case ' ': return 3; + case ';': return 7; + case 't': return 8; + case ' ': return 7; } return 7; } @@ -75,7 +75,7 @@ void Font::draw(Batch2D* batch, std::wstring text, int x, int y, int style) { 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){ next = charpage; diff --git a/src/graphics/Framebuffer.cpp b/src/graphics/Framebuffer.cpp new file mode 100644 index 00000000..287be8e5 --- /dev/null +++ b/src/graphics/Framebuffer.cpp @@ -0,0 +1,37 @@ +#include "Framebuffer.h" + +#include +#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); +} diff --git a/src/graphics/Framebuffer.h b/src/graphics/Framebuffer.h new file mode 100644 index 00000000..3fd889f2 --- /dev/null +++ b/src/graphics/Framebuffer.h @@ -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_ */ diff --git a/src/graphics/Sprite.cpp b/src/graphics/Sprite.cpp new file mode 100644 index 00000000..3b0ca50f --- /dev/null +++ b/src/graphics/Sprite.cpp @@ -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() { +} + diff --git a/src/graphics/Sprite.h b/src/graphics/Sprite.h new file mode 100644 index 00000000..5d10038e --- /dev/null +++ b/src/graphics/Sprite.h @@ -0,0 +1,29 @@ +#ifndef SRC_GRAPHICS_SPRITE_H_ +#define SRC_GRAPHICS_SPRITE_H_ + +#include +#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_ */ diff --git a/src/graphics/UVRegion.cpp b/src/graphics/UVRegion.cpp new file mode 100644 index 00000000..3f421522 --- /dev/null +++ b/src/graphics/UVRegion.cpp @@ -0,0 +1 @@ +#include "UVRegion.h" diff --git a/src/graphics/UVRegion.h b/src/graphics/UVRegion.h new file mode 100644 index 00000000..a59f6c30 --- /dev/null +++ b/src/graphics/UVRegion.h @@ -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_ */ diff --git a/src/graphics/VoxelRenderer.cpp b/src/graphics/VoxelRenderer.cpp index 7e17d676..7e9ed7fc 100644 --- a/src/graphics/VoxelRenderer.cpp +++ b/src/graphics/VoxelRenderer.cpp @@ -12,7 +12,7 @@ #define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) #define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) #define IS_CHUNK(X,Y,Z) (GET_CHUNK(X,Y,Z) != nullptr) -#define GET_CHUNK(X,Y,Z) (chunks[((CDIV(Y, CHUNK_H)+1) * 3 + CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1]) +#define 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 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(){ } -inline void _renderBlock(std::vector& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ - unsigned int id = vox.id; - - if (!id){ - return; - } - +inline void _renderBlock(std::vector& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){ float l; float uvsize = 1.0f/16.0f; @@ -61,10 +55,10 @@ inline void _renderBlock(std::vector& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[3]); - float lr = LIGHT(x,y+1,z, 0) / 15.0f; - float lg = LIGHT(x,y+1,z, 1) / 15.0f; - float lb = LIGHT(x,y+1,z, 2) / 15.0f; - float ls = LIGHT(x,y+1,z, 3) / 15.0f; + const float lr = LIGHT(x,y+1,z, 0) / 15.0f; + const float lg = LIGHT(x,y+1,z, 1) / 15.0f; + const float lb = LIGHT(x,y+1,z, 2) / 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 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& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[2]); - float lr = LIGHT(x,y-1,z, 0) / 15.0f; - float lg = LIGHT(x,y-1,z, 1) / 15.0f; - float lb = LIGHT(x,y-1,z, 2) / 15.0f; - float ls = LIGHT(x,y-1,z, 3) / 15.0f; + const float lr = LIGHT(x,y-1,z, 0) / 15.0f; + const float lg = LIGHT(x,y-1,z, 1) / 15.0f; + const float lb = LIGHT(x,y-1,z, 2) / 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 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& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[1]); - float lr = LIGHT(x+1,y,z, 0) / 15.0f; - float lg = LIGHT(x+1,y,z, 1) / 15.0f; - float lb = LIGHT(x+1,y,z, 2) / 15.0f; - float ls = LIGHT(x+1,y,z, 3) / 15.0f; + const float lr = LIGHT(x+1,y,z, 0) / 15.0f; + const float lg = LIGHT(x+1,y,z, 1) / 15.0f; + const float lb = LIGHT(x+1,y,z, 2) / 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 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& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[0]); - float lr = LIGHT(x-1,y,z, 0) / 15.0f; - float lg = LIGHT(x-1,y,z, 1) / 15.0f; - float lb = LIGHT(x-1,y,z, 2) / 15.0f; - float ls = LIGHT(x-1,y,z, 3) / 15.0f; + const float lr = LIGHT(x-1,y,z, 0) / 15.0f; + const float lg = LIGHT(x-1,y,z, 1) / 15.0f; + const float lb = LIGHT(x-1,y,z, 2) / 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 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& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[5]); - float lr = LIGHT(x,y,z+1, 0) / 15.0f; - float lg = LIGHT(x,y,z+1, 1) / 15.0f; - float lb = LIGHT(x,y,z+1, 2) / 15.0f; - float ls = LIGHT(x,y,z+1, 3) / 15.0f; + const float lr = LIGHT(x,y,z+1, 0) / 15.0f; + const float lg = LIGHT(x,y,z+1, 1) / 15.0f; + const float lb = LIGHT(x,y,z+1, 2) / 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 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& buffer, int x, int y, int z, const SETUP_UV(block->textureFaces[4]); - float lr = LIGHT(x,y,z-1, 0) / 15.0f; - float lg = LIGHT(x,y,z-1, 1) / 15.0f; - float lb = LIGHT(x,y,z-1, 2) / 15.0f; - float ls = LIGHT(x,y,z-1, 3) / 15.0f; + const float lr = LIGHT(x,y,z-1, 0) / 15.0f; + const float lg = LIGHT(x,y,z-1, 1) / 15.0f; + const float lb = LIGHT(x,y,z-1, 2) / 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 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& buffer, int x, int y, int z, const } } +inline void _renderBlockShadeless(std::vector& 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& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ @@ -304,101 +372,88 @@ inline void _renderXBlock(std::vector& buffer, int x, int y, int z, const return; } - float l; float uvsize = 1.0f/16.0f; - float lr = LIGHT(x,y,z, 0) / 15.0f; - float lg = LIGHT(x,y,z, 1) / 15.0f; - float lb = LIGHT(x,y,z, 2) / 15.0f; - float ls = LIGHT(x,y,z, 3) / 15.0f; + float lr = LIGHT(x,y,z, 0) / 15.0f; + float lg = LIGHT(x,y,z, 1) / 15.0f; + float lb = LIGHT(x,y,z, 2) / 15.0f; + float ls = LIGHT(x,y,z, 3) / 15.0f; - float lr0 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; - float lr1 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; - float lr2 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; - float lr3 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; - float lr4 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; - float lr5 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; - float lr6 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; - float lr7 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; + float lr0 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; + float lr1 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; + float lr2 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; + float lr3 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; + float lr4 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; + float lr5 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; + float lr6 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f; + float lr7 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f; - float lg0 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; - float lg1 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; - float lg2 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; - float lg3 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; - float lg4 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; - float lg5 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; - float lg6 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; - float lg7 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; + float lg0 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; + float lg1 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; + float lg2 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; + float lg3 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; + float lg4 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; + float lg5 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; + float lg6 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f; + float lg7 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f; - float lb0 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; - float lb1 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; - float lb2 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; - float lb3 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; - float lb4 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; - float lb5 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; - float lb6 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; - float lb7 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; + float lb0 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; + float lb1 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; + float lb2 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; + float lb3 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; + float lb4 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; + float lb5 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; + float lb6 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f; + float lb7 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f; - float ls0 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; - float ls1 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f; - float ls2 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f; - float ls3 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; - float ls4 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; - float ls5 = (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 ls0 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; + float ls1 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f; + float ls2 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f; + float ls3 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; + float ls4 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f; + float ls5 = (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; + {SETUP_UV(block->textureFaces[1]); - l = 0.95f; + 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,v2, lr1,lg1,lb1,ls1); + VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr2,lg2,lb2,ls2); - {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, 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, u2,v1, lr0,lg0,lb0,ls0); - 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, u1,v2, lr2,lg2,lb2,ls2); + {SETUP_UV(block->textureFaces[0]); - 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, 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);} - - - l = 0.85f; + 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, u2,v2, lr1,lg1,lb1,ls1); + VERTEX(index, x-0.5f+xs, y+0.5f, z-0.5f+zs, u1,v2, lr2,lg2,lb2,ls2); - {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, 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, u1,v1, lr0,lg0,lb0,ls0); - 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, u1,v2, lr2,lg2,lb2,ls2); + {SETUP_UV(block->textureFaces[5]); - 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, 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);} - - - l = 0.9f; + 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, u2,v2, lr5,lg5,lb5,ls5); + VERTEX(index, x-0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr6,lg6,lb6,ls6); - {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, 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, u1,v1, lr4,lg4,lb4,ls4); - 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, u1,v2, lr6,lg6,lb6,ls6); + {SETUP_UV(block->textureFaces[4]); - 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, 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,v1, lr4,lg4,lb4,ls4); + 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, u1,v2, lr6,lg6,lb6,ls6); - - l = 0.8f; - - {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,v2, lr5,lg5,lb5,ls5); - VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u1,v2, lr6,lg6,lb6,ls6); - - 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, u1,v2, lr6,lg6,lb6,ls6); - VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr7,lg7,lb7,ls7);} + 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, u1,v2, lr6,lg6,lb6,ls6); + VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr7,lg7,lb7,ls7);} } const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& size){ @@ -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 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 || vox.id == 4 || vox.id == 12 || vox.id == 13) 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 x = 0; x < 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) 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 x = 0; x < 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; _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 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 != 4) continue; - _renderBlock(buffer, x, y, z, chunks, vox, index); + _renderBlock(buffer, x, y, z, chunks, vox.id, index); } } } diff --git a/src/graphics/VoxelRenderer.h b/src/graphics/VoxelRenderer.h index 84e38238..3e1d545c 100644 --- a/src/graphics/VoxelRenderer.h +++ b/src/graphics/VoxelRenderer.h @@ -12,6 +12,7 @@ class Chunk; class VoxelRenderer { public: std::vector buffer; + unsigned char lights[27 * 4]; VoxelRenderer(); ~VoxelRenderer(); diff --git a/src/hud_render.cpp b/src/hud_render.cpp index 78da460a..62894d66 100644 --- a/src/hud_render.cpp +++ b/src/hud_render.cpp @@ -1,12 +1,15 @@ #include "hud_render.h" #include +#include #include "Assets.h" #include "graphics/Shader.h" #include "graphics/Batch2D.h" #include "graphics/Font.h" +#include "graphics/Mesh.h" #include "window/Camera.h" #include "window/Window.h" +#include "window/Events.h" #include "voxels/Chunks.h" #include "voxels/Block.h" #include "world/World.h" @@ -15,6 +18,19 @@ 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); uicamera = new Camera(glm::vec3(), Window::height / 1.0f); uicamera->perspective = false; @@ -22,48 +38,103 @@ HudRenderer::HudRenderer() { } HudRenderer::~HudRenderer() { + delete crosshair; delete batch; delete uicamera; } - -void HudRenderer::draw(World* world, Level* level, Assets* assets, bool devdata, int fps){ +void HudRenderer::drawDebug(Level* level, Assets* assets, int fps, bool occlusion){ Chunks* chunks = level->chunks; Player* player = level->player; + Font* font = assets->getFont("normal"); + + Shader* uishader = assets->getShader("ui"); + uishader->use(); + uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView()); + batch->color = vec4(1.0f); + batch->begin(); + 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.y), 50, 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, std::to_wstring(fps), 44, 42, STYLE_OUTLINE); + font->draw(batch, L"occlusion: "+std::to_wstring(occlusion), 16, 54, STYLE_OUTLINE); + 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()); - // Draw debug info - Font* font = assets->getFont("normal"); - batch->begin(); - if (devdata){ - 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.y), 50, 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, std::to_wstring(fps), 40, 42, STYLE_OUTLINE); - } - batch->render(); - // Chosen block preview 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->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); - Block* cblock = Block::blocks[player->choosenBlock]; - if (cblock->model == BLOCK_MODEL_CUBE){ - batch->blockSprite(24, 648, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); - } else if (cblock->model == BLOCK_MODEL_GRASS){ - batch->sprite(24, 648, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); + Player* player = level->player; + { + Block* cblock = Block::blocks[player->choosenBlock]; + if (cblock->model == BLOCK_MODEL_CUBE){ + batch->blockSprite(24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); + } else if (cblock->model == BLOCK_MODEL_GRASS){ + 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(); + + 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); } diff --git a/src/hud_render.h b/src/hud_render.h index e07d36a1..08984627 100644 --- a/src/hud_render.h +++ b/src/hud_render.h @@ -3,17 +3,19 @@ class Batch2D; class Camera; -class World; class Level; class Assets; +class Mesh; class HudRenderer { - Batch2D *batch; - Camera *uicamera; + Batch2D* batch; + Camera* uicamera; + Mesh* crosshair; public: 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_ */ diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index b4f22bd6..07070a05 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -21,8 +21,8 @@ void LightSolver::add(int x, int y, int z, int emission) { addqueue.push(entry); Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z); - chunk->modified = true; - chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, entry.light); + chunk->setModified(true); + 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) { @@ -35,7 +35,7 @@ void LightSolver::remove(int x, int y, int z) { if (chunk == nullptr) return; - int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel); + int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel); if (light == 0){ return; } @@ -47,7 +47,7 @@ void LightSolver::remove(int x, int y, int z) { entry.light = light; remqueue.push(entry); - chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, 0); + chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y, entry.z-chunk->z*CHUNK_D, channel, 0); } void LightSolver::solve(){ @@ -78,8 +78,8 @@ void LightSolver::solve(){ nentry.z = z; nentry.light = light; remqueue.push(nentry); - chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0); - chunk->modified = true; + chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); + chunk->setModified(true); } else if (light >= entry.light){ lightentry nentry; @@ -94,7 +94,7 @@ void LightSolver::solve(){ } while (!addqueue.empty()){ - lightentry entry = addqueue.front(); + const lightentry entry = addqueue.front(); addqueue.pop(); if (entry.light <= 1) @@ -110,8 +110,8 @@ void LightSolver::solve(){ voxel* v = chunks->get(x,y,z); Block* block = Block::blocks[v->id]; if (block->lightPassing && light+2 <= entry.light){ - chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, entry.light-1); - chunk->modified = true; + chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, entry.light-1); + chunk->setModified(true); lightentry nentry; nentry.x = x; nentry.y = y; diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index b1fe4f80..5a036d76 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -35,154 +35,94 @@ void Lighting::clear(){ } } -void Lighting::onChunkLoaded(int cx, int cy, int cz, bool sky){ - Chunk* chunk = chunks->getChunk(cx, cy, cz); - Chunk* chunkUpper = chunks->getChunk(cx, cy+1, cz); - Chunk* chunkLower = chunks->getChunk(cx, cy-1, cz); - if (chunkLower && sky){ - for (int z = 0; z < CHUNK_D; z++){ - for (int x = 0; x < CHUNK_W; x++){ +void Lighting::prebuildSkyLight(int cx, int cz){ + Chunk* chunk = chunks->getChunk(cx, cz); + int highestPoint = 0; + for (int z = 0; z < CHUNK_D; z++){ + for (int x = 0; x < CHUNK_W; x++){ + for (int y = CHUNK_H-1;;y--){ + if (y < 0) + break; + voxel* vox = &(chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]); + Block* block = Block::blocks[vox->id]; + if (!block->skyLightPassing) { + if (highestPoint < y) + highestPoint = y; + break; + } + chunk->lightmap->setS(x,y,z, 15); + } + } + } + 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 x = 0; x < CHUNK_W; x++){ + for (int y = chunk->lightmap->highestPoint; y >= 0; y--){ 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); + 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); } } } } } - 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; + solverS->solve(); +} - int light = chunkUpper->lightmap->getS(x,0,z); +void Lighting::onChunkLoaded(int cx, int cz){ + const Chunk* chunk = chunks->getChunk(cx, cz); - Chunk* current = chunk; - if (light == 15){ - for (int y = CHUNK_H-1;;y--){ - if (y < 0){ - ncy--; - y += CHUNK_H; - } - if (ncy != current->y) - current = chunks->getChunk(cx,ncy,cz); - if (!current) - break; - voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz); - Block* block = Block::blocks[vox->id]; - if (!block->skyLightPassing) - break; - current->lightmap->setS(x,y,z, 15); - current->modified = true; - solverS->add(gx,y+ncy*CHUNK_H,gz); - } - } else if (light){ - solverS->add(gx,gy+CHUNK_H,gz); - } - } - } - } else if (sky){ - for (int z = 0; z < CHUNK_D; z++){ - for (int x = 0; x < CHUNK_W; x++){ - int gx = x + cx * CHUNK_W; - int gz = z + cz * CHUNK_D; - int ncy = cy; - - Chunk* current = chunk; - for (int y = CHUNK_H-1;;y--){ - if (y < 0){ - ncy--; - y += CHUNK_H; - } - if (ncy != current->y) - current = chunks->getChunk(cx,ncy,cz); - if (!current) - break; - voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz); - Block* block = Block::blocks[vox->id]; - if (!block->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 z = 0; z < CHUNK_D; z++){ for (unsigned int x = 0; x < CHUNK_W; x++){ voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; Block* block = Block::blocks[vox.id]; - if (block->emission[0] || block->emission[1] || block->emission[2]){ - int gx = x + cx * CHUNK_W; - int gy = y + cy * CHUNK_H; - int gz = z + cz * CHUNK_D; - solverR->add(gx,gy,gz,block->emission[0]); - solverG->add(gx,gy,gz,block->emission[1]); - solverB->add(gx,gy,gz,block->emission[2]); - } - } - } - } - for (int y = -1; y <= CHUNK_H; y++){ - for (int z = -1; z <= CHUNK_D; z++){ - for (int x = -1; x <= CHUNK_W; x++){ - if (!(x == -1 || x == CHUNK_W || y == -1 || y == CHUNK_H || z == -1 || z == CHUNK_D)) - continue; int gx = x + cx * CHUNK_W; - int gy = y + cy * CHUNK_H; int gz = z + cz * CHUNK_D; - 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); + if (block->emission[0] || block->emission[1] || block->emission[2]){ + solverR->add(gx,y,gz,block->emission[0]); + solverG->add(gx,y,gz,block->emission[1]); + solverB->add(gx,y,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 || 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(); solverG->solve(); solverB->solve(); solverS->solve(); - - Chunk* other; - other = chunks->getChunk(cx-1,cy,cz); if (other) other->modified = true; - other = chunks->getChunk(cx+1,cy,cz); if (other) other->modified = true; - other = chunks->getChunk(cx,cy-1,cz); if (other) other->modified = true; - other = chunks->getChunk(cx,cy+1,cz); if (other) other->modified = true; - other = chunks->getChunk(cx,cy,cz-1); if (other) other->modified = true; - other = chunks->getChunk(cx,cy,cz+1); if (other) other->modified = true; } void Lighting::onBlockSet(int x, int y, int z, int id){ @@ -191,11 +131,9 @@ void Lighting::onBlockSet(int x, int y, int z, int id){ solverR->remove(x,y,z); solverG->remove(x,y,z); solverB->remove(x,y,z); - solverR->solve(); solverG->solve(); solverB->solve(); - if (chunks->getLight(x,y+1,z, 3) == 0xF){ for (int i = y; i >= 0; i--){ voxel* vox = chunks->get(x,i,z); @@ -204,14 +142,12 @@ void Lighting::onBlockSet(int x, int y, int z, int id){ solverS->add(x,i,z, 0xF); } } - solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z); solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z); solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z); solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z); solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1); solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1); - solverR->solve(); solverG->solve(); solverB->solve(); diff --git a/src/lighting/Lighting.h b/src/lighting/Lighting.h index ebbb2173..e1caf777 100644 --- a/src/lighting/Lighting.h +++ b/src/lighting/Lighting.h @@ -15,7 +15,9 @@ public: ~Lighting(); 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); }; diff --git a/src/lighting/Lightmap.h b/src/lighting/Lightmap.h index bee5c5e7..c0ca007a 100644 --- a/src/lighting/Lightmap.h +++ b/src/lighting/Lightmap.h @@ -6,6 +6,7 @@ class Lightmap { public: unsigned short* map; + int highestPoint = 0; Lightmap(); ~Lightmap(); diff --git a/src/loaders/png_loading.cpp b/src/loaders/png_loading.cpp index 0a02b04a..7757b564 100644 --- a/src/loaders/png_loading.cpp +++ b/src/loaders/png_loading.cpp @@ -102,6 +102,8 @@ int _png_load(const char* file, int* width, int* height){ alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); glGenerateMipmap(GL_TEXTURE_2D); 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); 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_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); pwidth[0] = ihdr.width; diff --git a/src/objects/Player.h b/src/objects/Player.h index 2147458f..af7a9fe7 100644 --- a/src/objects/Player.h +++ b/src/objects/Player.h @@ -14,6 +14,7 @@ public: Camera* camera; Hitbox* hitbox; bool flight = false; + bool noclip = false; int choosenBlock; float camX, camY; float cameraShaking = 0.0f; diff --git a/src/physics/PhysicsSolver.cpp b/src/physics/PhysicsSolver.cpp index bab04f0b..dac915df 100644 --- a/src/physics/PhysicsSolver.cpp +++ b/src/physics/PhysicsSolver.cpp @@ -10,7 +10,9 @@ 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; for (unsigned i = 0; i < substeps; i++){ float dt = delta / (float)substeps; @@ -25,85 +27,87 @@ void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned s float px = pos.x; float pz = pos.z; - if (vel.x < 0.0){ - 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++){ - int x = floor(pos.x-half.x-E); - if (chunks->isObstacle(x,y,z)){ - vel.x *= 0.0; - pos.x = x + 1 + half.x + E; - break; + if (collisions) { + if (vel.x < 0.0){ + 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++){ + int x = floor(pos.x-half.x-E); + if (chunks->isObstacle(x,y,z)){ + vel.x *= 0.0; + pos.x = x + 1 + half.x + E; + break; + } } } } - } - if (vel.x > 0.0){ - 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++){ - int x = floor(pos.x+half.x+E); - if (chunks->isObstacle(x,y,z)){ - vel.x *= 0.0; - pos.x = x - half.x - E; - break; + if (vel.x > 0.0){ + 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++){ + int x = floor(pos.x+half.x+E); + if (chunks->isObstacle(x,y,z)){ + vel.x *= 0.0; + pos.x = x - half.x - E; + break; + } } } } - } - if (vel.z < 0.0){ - for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){ + if (vel.z < 0.0){ + for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){ + for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ + int z = floor(pos.z-half.z-E); + if (chunks->isObstacle(x,y,z)){ + vel.z *= 0.0; + pos.z = z + 1 + half.z + E; + break; + } + } + } + } + + if (vel.z > 0.0){ + for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){ + for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ + int z = floor(pos.z+half.z+E); + if (chunks->isObstacle(x,y,z)){ + vel.z *= 0.0; + pos.z = z - half.z - E; + break; + } + } + } + } + + if (vel.y < 0.0){ for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ - int z = floor(pos.z-half.z-E); - if (chunks->isObstacle(x,y,z)){ - vel.z *= 0.0; - pos.z = z + 1 + half.z + E; - break; + bool broken = false; + for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){ + int y = floor(pos.y-half.y-E); + if (chunks->isObstacle(x,y,z)){ + vel.y *= 0.0; + pos.y = y + 1 + half.y; + int f = DEFAULT_FRICTION; + vel.x *= max(0.0, 1.0 - dt * f); + vel.z *= max(0.0, 1.0 - dt * f); + hitbox->grounded = true; + broken = true; + break; + } } + if (broken) + break; } } - } - - if (vel.z > 0.0){ - for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){ + if (vel.y > 0.0){ for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ - int z = floor(pos.z+half.z+E); - if (chunks->isObstacle(x,y,z)){ - vel.z *= 0.0; - pos.z = z - half.z - E; - break; - } - } - } - } - - if (vel.y < 0.0){ - for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ - bool broken = false; - for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){ - int y = floor(pos.y-half.y-E); - if (chunks->isObstacle(x,y,z)){ - vel.y *= 0.0; - pos.y = y + 1 + half.y; - int f = DEFAULT_FRICTION; - vel.x *= max(0.0, 1.0 - dt * f); - vel.z *= max(0.0, 1.0 - dt * f); - hitbox->grounded = true; - broken = true; - break; - } - } - if (broken) - break; - } - } - if (vel.y > 0.0){ - for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){ - for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){ - int y = floor(pos.y+half.y+E); - if (chunks->isObstacle(x,y,z)){ - vel.y *= 0.0; - pos.y = y - half.y - E; - break; + for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){ + int y = floor(pos.y+half.y+E); + if (chunks->isObstacle(x,y,z)){ + vel.y *= 0.0; + pos.y = y - half.y - E; + break; + } } } } diff --git a/src/physics/PhysicsSolver.h b/src/physics/PhysicsSolver.h index 469d73a8..f2302b34 100644 --- a/src/physics/PhysicsSolver.h +++ b/src/physics/PhysicsSolver.h @@ -14,7 +14,13 @@ class PhysicsSolver { vec3 gravity; public: 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); }; diff --git a/src/player_control.cpp b/src/player_control.cpp index 7772f097..59fbe276 100644 --- a/src/player_control.cpp +++ b/src/player_control.cpp @@ -25,7 +25,7 @@ #define CAMERA_SHAKING_OFFSET_Y 0.031f #define CAMERA_SHAKING_SPEED 1.6f #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 JUMP_FORCE 7.0f @@ -35,13 +35,6 @@ PlayerController::PlayerController(Level* level) : level(level) { void PlayerController::update_controls(float delta){ 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++){ if (Events::jpressed(GLFW_KEY_0+i)){ player->choosenBlock = i; @@ -65,7 +58,7 @@ void PlayerController::update_controls(float delta){ } int substeps = (int)(delta * 1000); 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.y = hitbox->position.y + 0.7f; 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 -= 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; if (player->flight){ hitbox->velocity.y += 1; hitbox->grounded = false; } } + if (Events::jpressed(GLFW_KEY_N)) { + player->noclip = !player->noclip; + } // Field of view manipulations float dt = min(1.0f, delta * ZOOM_SPEED); - if (dt > 1.0f) - dt = 1.0f; float zoomValue = 1.0f; if (shift){ speed *= CROUCH_SPEED_MUL; @@ -182,7 +177,8 @@ void PlayerController::update_interaction(){ selectedBlockId = vox->id; 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 y = (int)iend.y; int z = (int)iend.z; @@ -193,6 +189,11 @@ void PlayerController::update_interaction(){ int x = (int)(iend.x)+(int)(norm.x); int y = (int)(iend.y)+(int)(norm.y); 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)){ chunks->set(x, y, z, player->choosenBlock); lighting->onBlockSet(x,y,z, player->choosenBlock); diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index a24b3e92..bfb13c67 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -24,6 +24,7 @@ using namespace glm; #include "graphics/VoxelRenderer.h" #include "graphics/LineBatch.h" #include "graphics/Batch2D.h" +#include "graphics/Framebuffer.h" #include "window/Window.h" #include "window/Events.h" #include "window/Camera.h" @@ -54,13 +55,9 @@ using namespace glm; #include "hud_render.h" #include "player_control.h" - -float gravity = 19.6f; - int WIDTH = 1280; int HEIGHT = 720; - // Save all world data to files void write_world(World* world, Level* level){ WorldFiles* wfile = world->wfile; @@ -68,7 +65,7 @@ void write_world(World* world, Level* level){ for (unsigned int i = 0; i < chunks->volume; i++){ Chunk* chunk = chunks->chunks[i]; - if (chunk == nullptr) + if (chunk == nullptr || !chunk->isUnsaved()) continue; wfile->put((const char*)chunk->voxels, chunk->x, chunk->z); } @@ -78,16 +75,17 @@ void write_world(World* world, Level* level){ world->wfile->writePlayer(level->player); } -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_interaction(); + if (Events::_cursor_locked) + level->playerController->update_interaction(); 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* 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); Camera* camera = player->camera; @@ -96,10 +94,8 @@ Level* load_level(World* world, Player* player) { return level; } - -int initialize(Assets*& assets){ - Audio::initialize(); - Window::initialize(WIDTH, HEIGHT, "VoxelEngine-Cpp v.12"); +int initialize(Assets*& assets) { + Window::initialize(WIDTH, HEIGHT, "VoxelEngine-Cpp v12"); Events::initialize(); assets = new Assets(); @@ -113,6 +109,66 @@ int initialize(Assets*& assets){ 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() { setup_definitions(); @@ -128,57 +184,12 @@ int main() { Player* player = new Player(playerPosition, 4.0f, camera); 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; - while (!Window::isShouldClose()){ - frame++; - float currentTime = glfwGetTime(); - delta = currentTime - lastTime; - lastTime = currentTime; - int fps = 1 / delta; - if (Events::jpressed(GLFW_KEY_O)){ - occlusion = !occlusion; - } - if (Events::jpressed(GLFW_KEY_F3)){ - devdata = !devdata; - } + Audio::initialize(); + mainloop(level, assets); + Audio::finalize(); - 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; write_world(world, level); @@ -187,7 +198,6 @@ int main() { std::cout << "-- shutting down" << std::endl; delete assets; - Audio::finalize(); Events::finalize(); Window::terminate(); return 0; diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index 5bf9006e..52debffe 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -2,8 +2,7 @@ #include "voxel.h" #include "../lighting/Lightmap.h" - -Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){ +Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){ voxels = new voxel[CHUNK_VOL]; for (unsigned int i = 0; i < CHUNK_VOL; i++) voxels[i].id = 1; @@ -30,7 +29,7 @@ bool Chunk::isEmpty(){ } 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++) other->voxels[i] = voxels[i]; other->lightmap->set(lightmap); diff --git a/src/voxels/Chunk.h b/src/voxels/Chunk.h index 2c37fed9..1ff29b7a 100644 --- a/src/voxels/Chunk.h +++ b/src/voxels/Chunk.h @@ -8,6 +8,12 @@ #define CHUNK_D 16 #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 Lightmap; @@ -16,19 +22,21 @@ struct RenderData { 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 { public: - int x,y,z; + int x, z; voxel* voxels; Lightmap* lightmap; - bool modified = true; - bool ready = false; - bool loaded = false; + int flags = 0; int surrounding = 0; int references = 1; RenderData renderData; - Chunk(int x, int y, int z); + Chunk(int x, int z); ~Chunk(); bool isEmpty(); @@ -36,6 +44,28 @@ public: Chunk* clone() const; void incref(); 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_ */ diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index ce255800..b16aecd5 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -11,8 +11,8 @@ #include #include -Chunks::Chunks(int w, int h, int d, int ox, int oy, int oz) : w(w), h(h), d(d), ox(ox), oy(oy), oz(oz){ - volume = w*h*d; +Chunks::Chunks(int w, int d, int ox, int oz) : w(w), d(d), ox(ox), oz(oz){ + volume = w*d; chunks = new Chunk*[volume]; chunksSecond = new Chunk*[volume]; @@ -36,7 +36,6 @@ Chunks::~Chunks(){ voxel* Chunks::get(int x, int y, int z){ x -= ox * CHUNK_W; - y -= oy * CHUNK_H; z -= oz * CHUNK_D; int cx = x / CHUNK_W; int cy = y / CHUNK_H; @@ -44,7 +43,7 @@ voxel* Chunks::get(int x, int y, int z){ if (x < 0) cx--; if (y < 0) cy--; if (z < 0) cz--; - if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) + if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return nullptr; Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 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){ x -= ox * CHUNK_W; - y -= oy * CHUNK_H; z -= oz * CHUNK_D; int cx = x / CHUNK_W; 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 (y < 0) cy--; 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; Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 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){ x -= ox * CHUNK_W; - y -= oy * CHUNK_H; z -= oz * CHUNK_D; int cx = x / CHUNK_W; int cy = y / CHUNK_H; @@ -93,7 +90,7 @@ unsigned short Chunks::getLight(int x, int y, int z){ if (x < 0) cx--; if (y < 0) cy--; if (z < 0) cz--; - if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) + if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return 0; Chunk* chunk = chunks[(cy * d + cz) * w + cx]; 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){ x -= ox * CHUNK_W; - y -= oy * CHUNK_H; z -= oz * CHUNK_D; int cx = x / CHUNK_W; int cy = y / CHUNK_H; @@ -114,48 +110,44 @@ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ if (x < 0) cx--; if (y < 0) cy--; if (z < 0) cz--; - if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) + if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return nullptr; 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; - y -= oy; 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 chunks[(y * d + z) * w + x]; + return chunks[z * w + x]; } void Chunks::set(int x, int y, int z, int id){ x -= ox * CHUNK_W; - y -= oy * CHUNK_H; z -= oz * CHUNK_D; int cx = x / CHUNK_W; - int cy = y / CHUNK_H; + if (y < 0 || y >= CHUNK_H) + return; int cz = z / CHUNK_D; if (x < 0) cx--; - if (y < 0) cy--; if (z < 0) cz--; - if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d) + if (cx < 0 || cz < 0 || cx >= w || cz >= d) return; - Chunk* chunk = chunks[(cy * d + cz) * w + cx]; + Chunk* chunk = chunks[cz * w + cx]; if (chunk == nullptr) return; int lx = x - cx * CHUNK_W; - int ly = y - cy * CHUNK_H; int lz = z - cz * CHUNK_D; - chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx].id = id; - chunk->modified = true; + chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx].id = id; + chunk->setUnsaved(true); + chunk->setModified(true); - if (lx == 0 && (chunk = getChunk(cx+ox-1, cy+oy, cz+oz))) chunk->modified = true; - if (ly == 0 && (chunk = getChunk(cx+ox, cy+oy-1, cz+oz))) chunk->modified = true; - if (lz == 0 && (chunk = getChunk(cx+ox, cy+oy, cz+oz-1))) chunk->modified = true; + if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz))) chunk->setModified(true); + if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1))) chunk->setModified(true); - if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cy+oy, cz+oz))) chunk->modified = true; - if (ly == CHUNK_H-1 && (chunk = getChunk(cx+ox, cy+oy+1, cz+oz))) chunk->modified = true; - if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cy+oy, cz+oz+1))) chunk->modified = true; + if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz))) chunk->setModified(true); + if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1))) chunk->setModified(true); } 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; } -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 cy = y / CHUNK_H; int cz = z / CHUNK_D; cx -= ox; - cy -= oy; cz -= oz; if (x < 0) cx--; - if (y < 0) cy--; if (z < 0) cz--; cx -= w/2; - cy -= h/2; cz -= d/2; - if (cx != 0 || cy != 0 || cz != 0) - translate(worldFiles, cx,cy,cz); + if (cx | 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++){ chunksSecond[i] = nullptr; meshesSecond[i] = nullptr; } - for (unsigned int y = 0; y < h; y++){ - for (unsigned int z = 0; z < d; z++){ - for (unsigned int x = 0; x < w; x++){ - Chunk* chunk = chunks[(y * d + z) * w + x]; - int nx = x - dx; - int ny = y - dy; - int nz = z - dz; - if (chunk == nullptr) - continue; - Mesh* mesh = meshes[(y * d + z) * w + x]; - if (nx < 0 || ny < 0 || nz < 0 || nx >= w || ny >= h || nz >= d){ - worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z); - chunk->decref(); - delete mesh; - chunksCount--; - continue; - } - meshesSecond[(ny * d + nz) * w + nx] = mesh; - chunksSecond[(ny * d + nz) * w + nx] = chunk; + for (int z = 0; z < d; z++){ + for (int x = 0; x < w; x++){ + Chunk* chunk = chunks[z * w + x]; + int nx = x - dx; + int nz = z - dz; + if (chunk == nullptr) + continue; + Mesh* mesh = meshes[z * w + x]; + if (nx < 0 || nz < 0 || nx >= w || nz >= d){ + worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z); + chunk->decref(); + delete mesh; + chunksCount--; + continue; } + meshesSecond[nz * w + nx] = mesh; + chunksSecond[nz * w + nx] = chunk; } } Chunk** ctemp = chunks; @@ -299,26 +285,22 @@ void Chunks::translate(WorldFiles* worldFiles, int dx, int dy, int dz){ meshesSecond = mtemp; ox += dx; - oy += dy; oz += dz; } -void Chunks::_setOffset(int x, int y, int z){ +void Chunks::_setOffset(int x, int z){ ox = x; - oy = y; oz = z; } bool Chunks::putChunk(Chunk* chunk) { int x = chunk->x; - int y = chunk->y; int z = chunk->z; x -= ox; - y -= oy; 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; - chunks[(y * d + z) * w + x] = chunk; + chunks[z * w + x] = chunk; chunksCount++; return true; } diff --git a/src/voxels/Chunks.h b/src/voxels/Chunks.h index c9c70bea..5b5f9a3a 100644 --- a/src/voxels/Chunks.h +++ b/src/voxels/Chunks.h @@ -21,15 +21,15 @@ public: Mesh** meshesSecond; size_t volume; size_t chunksCount; - unsigned int w,h,d; - int ox,oy,oz; + int w,d; + 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(); 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); voxel* get(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); // 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 translate(WorldFiles* worldFiles, int x, int y, int z); + void setCenter(WorldFiles* worldFiles, int x, int z); + void translate(WorldFiles* worldFiles, int x, int z); void clear(bool freeMemory); }; diff --git a/src/voxels/ChunksController.cpp b/src/voxels/ChunksController.cpp index 96b2cac4..1ca47b52 100644 --- a/src/voxels/ChunksController.cpp +++ b/src/voxels/ChunksController.cpp @@ -48,117 +48,78 @@ int ChunksController::countFreeLoaders(){ bool ChunksController::loadVisible(WorldFiles* worldFiles){ const int w = chunks->w; - const int h = chunks->h; const int d = chunks->d; const int ox = chunks->ox; - const int oy = chunks->oy; const int oz = chunks->oz; int nearX = 0; - int nearY = 0; int nearZ = 0; int minDistance = (w/2)*(w/2); - for (int y = 0; y < h; y++){ - for (int z = 2; z < d-2; z++){ - for (int x = 2; x < w-2; x++){ - int index = (y * d + z) * w + x; - Chunk* chunk = chunks->chunks[index]; - if (chunk != nullptr){ - int surrounding = 0; - for (int oz = -1; oz <= 1; oz++){ - for (int ox = -1; ox <= 1; ox++){ - Chunk* other = chunks->getChunk(chunk->x+ox, chunk->y, chunk->z+oz); - if (other != nullptr && other->ready) surrounding++; - } + for (int z = 2; z < d-2; z++){ + for (int x = 2; x < w-2; x++){ + int index = z * w + x; + Chunk* chunk = chunks->chunks[index]; + if (chunk != nullptr){ + int surrounding = 0; + for (int oz = -1; oz <= 1; oz++){ + for (int ox = -1; ox <= 1; ox++){ + Chunk* other = chunks->getChunk(chunk->x+ox, chunk->z+oz); + if (other != nullptr && other->isReady()) surrounding++; } - chunk->surrounding = surrounding; - continue; - } - int lx = x - w / 2; - int ly = y - h / 2; - int lz = z - d / 2; - int distance = (lx * lx + ly * ly + lz * lz); - if (distance < minDistance){ - minDistance = distance; - nearX = x; - nearY = y; - nearZ = z; } + chunk->surrounding = 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 = (nearY * d + nearZ) * w + nearX; + int index = nearZ * w + nearX; Chunk* chunk = chunks->chunks[index]; if (chunk != nullptr) return false; - ChunksLoader* freeLoader = nullptr; - for (int i = 0; i < loadersCount; i++){ - ChunksLoader* loader = loaders[i]; - if (loader->isBusy()){ - continue; - } - freeLoader = loader; - break; - } + ChunksLoader* freeLoader = getFreeLoader(); if (freeLoader == nullptr) return false; - chunk = new Chunk(nearX+ox,nearY+oy,nearZ+oz); + + chunk = new Chunk(nearX+ox, nearZ+oz); if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels)) - chunk->loaded = true; + chunk->setLoaded(true); chunks->putChunk(chunk); - Chunk* closes[27]; - for (int i = 0; i < 27; i++) + 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->ready) + if (!other->isReady()) continue; int ox = other->x - chunk->x; - int oy = other->y - chunk->y; int oz = other->z - chunk->z; - if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1) + if (abs(ox) > 1 || abs(oz) > 1) continue; ox += 1; - oy += 1; oz += 1; - closes[(oy * 3 + oz) * 3 + ox] = other; + closes[oz * 3 + ox] = other; } freeLoader->load(chunk, (Chunk**)closes); return true; } -bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { - const int w = chunks->w; - const int h = chunks->h; - const int d = chunks->d; - - for (int y = 0; y < h; y++){ - for (int z = 1; z < d-1; z++){ - for (int x = 1; x < w-1; x++){ - int index = (y * d + z) * w + x; - Chunk* chunk = chunks->chunks[index]; - if (chunk == nullptr) - continue; - if (chunk->renderData.vertices > (void*)1){ - const int chunk_attrs[] = {3,2,4, 0}; - Mesh* mesh = new Mesh(chunk->renderData.vertices, chunk->renderData.size / CHUNK_VERTEX_SIZE, chunk_attrs); - if (chunks->meshes[index]) - delete chunks->meshes[index]; - chunks->meshes[index] = mesh; - delete[] chunk->renderData.vertices; - chunk->renderData.vertices = nullptr; - } - } - } - } +ChunksLoader* ChunksController::getFreeLoader() { ChunksLoader* freeLoader = nullptr; for (int i = 0; i < loadersCount; i++){ ChunksLoader* loader = loaders[i]; @@ -168,85 +129,152 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { freeLoader = loader; break; } + return freeLoader; +} + +void ChunksController::calculateLights() { + ChunksLoader* freeLoader = getFreeLoader(); + if (freeLoader == nullptr) + return; + const int w = chunks->w; + const int d = chunks->d; + int nearX = 0; + int nearZ = 0; + int minDistance = INT_MAX; + for (int z = 1; z < d-1; z++){ + for (int x = 1; x < w-1; x++){ + 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; + for (size_t j = 0; j < chunks->volume; j++){ + Chunk* other = chunks->chunks[j]; + if (other == nullptr) + 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->lights(chunk, (Chunk**)closes); +} + +bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { + const int w = chunks->w; + const int d = chunks->d; + + for (int z = 1; z < d-1; z++){ + for (int x = 1; x < w-1; x++){ + int index = z * w + x; + Chunk* chunk = chunks->chunks[index]; + if (chunk == nullptr) + continue; + if (chunk->renderData.vertices > (void*)1){ + const int chunk_attrs[] = {3,2,4, 0}; + Mesh* mesh = new Mesh(chunk->renderData.vertices, chunk->renderData.size / CHUNK_VERTEX_SIZE, chunk_attrs); + if (chunks->meshes[index]) + delete chunks->meshes[index]; + chunks->meshes[index] = mesh; + delete[] chunk->renderData.vertices; + chunk->renderData.vertices = nullptr; + } + } + } + ChunksLoader* freeLoader = getFreeLoader(); if (freeLoader == nullptr) return false; int nearX = 0; - int nearY = 0; int nearZ = 0; int minDistance = INT_MAX; - for (int y = 0; y < h; y++){ - for (int z = 1; z < d-1; z++){ - for (int x = 1; x < w-1; x++){ - int index = (y * d + z) * w + x; - Chunk* chunk = chunks->chunks[index]; - if (chunk == nullptr) - continue; - Mesh* mesh = chunks->meshes[index]; - if (mesh != nullptr && !chunk->modified) - continue; - if (!chunk->ready || chunk->surrounding < MIN_SURROUNDING){ - continue; - } - int lx = x - w / 2; - int ly = y - h / 2; - int lz = z - d / 2; - int distance = (lx * lx + ly * ly + lz * lz); - if (distance < minDistance){ - minDistance = distance; - nearX = x; - nearY = y; - nearZ = z; - } + for (int z = 1; z < d-1; z++){ + for (int x = 1; x < w-1; x++){ + int index = z * w + x; + Chunk* chunk = chunks->chunks[index]; + if (chunk == nullptr) + continue; + Mesh* mesh = chunks->meshes[index]; + if (mesh != nullptr && !chunk->isModified()) + continue; + if (!chunk->isReady() || !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 = (nearY * d + nearZ) * w + nearX; - - + int index = nearZ * w + nearX; Chunk* chunk = chunks->chunks[index]; if (chunk == nullptr){ return false; } Mesh* mesh = chunks->meshes[index]; - if (mesh == nullptr || chunk->modified){ - Chunk* closes[27]; + if (mesh == nullptr || chunk->isModified()){ + if (chunk->renderData.vertices != nullptr) { + return false; + } + Chunk* closes[9]; if (chunk->isEmpty()){ chunks->meshes[index] = nullptr; return false; } - chunk->modified = false; - for (int i = 0; i < 27; i++) + + 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->ready) - continue; int ox = other->x - chunk->x; - int oy = other->y - chunk->y; int oz = other->z - chunk->z; - if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1) + if (abs(ox) > 1 || abs(oz) > 1) continue; ox += 1; - oy += 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->renderData.vertices = (float*)1; - freeLoader->render(chunk, (Chunk**)closes); - - return true; - } - //mesh = renderer->render(chunk, (const Chunk**)closes); - //chunks->meshes[index] = mesh; + chunk->setModified(false); + chunk->renderData.vertices = (float*)1; + freeLoader->render(chunk, (Chunk**)closes); + return true; } return false; } diff --git a/src/voxels/ChunksController.h b/src/voxels/ChunksController.h index 9212e207..d9315f00 100644 --- a/src/voxels/ChunksController.h +++ b/src/voxels/ChunksController.h @@ -18,8 +18,10 @@ public: ChunksController(World* world, Chunks* chunks, Lighting* lighting); ~ChunksController(); + ChunksLoader* getFreeLoader(); int countFreeLoaders(); bool loadVisible(WorldFiles* worldFiles); + void calculateLights(); bool _buildMeshes(VoxelRenderer* renderer, int tick); }; diff --git a/src/voxels/ChunksLoader.cpp b/src/voxels/ChunksLoader.cpp index 0b41241d..f688a70a 100644 --- a/src/voxels/ChunksLoader.cpp +++ b/src/voxels/ChunksLoader.cpp @@ -12,10 +12,10 @@ #include -#define CLOSES_C 27 +#define SURROUNDINGS_C 9 void ChunksLoader::_thread(){ - Chunks chunks(3,3,3, -1,-1,-1); + Chunks chunks(3, 3, -1, -1); Lighting lighting(&chunks); VoxelRenderer renderer; while (state != OFF){ @@ -24,9 +24,9 @@ void ChunksLoader::_thread(){ continue; } Chunk* chunk = current; - chunks._setOffset(chunk->x-1, chunk->y-1, chunk->z-1); - for (size_t i = 0; i < CLOSES_C; i++){ - Chunk* other = closes[i]; + chunks._setOffset(chunk->x-1, chunk->z-1); + for (size_t i = 0; i < SURROUNDINGS_C; i++){ + Chunk* other = surroundings[i]; if (other){ chunks.putChunk(other); } @@ -34,8 +34,9 @@ void ChunksLoader::_thread(){ if (state == LOAD){ chunks.putChunk(chunk); - if (!chunk->loaded){ - WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z, world->seed); + if (!chunk->isLoaded()){ + WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, world->seed); + chunk->setUnsaved(true); } for (size_t i = 0; i < CHUNK_VOL; i++){ @@ -44,11 +45,17 @@ void ChunksLoader::_thread(){ 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){ + chunk->setModified(false); size_t size; - renderer.render(chunk, (const Chunk**)(closes.load()), size); + renderer.render(chunk, (const Chunk**)(surroundings.load()), size); float* vertices = new float[size]; for (size_t i = 0; i < size; i++) vertices[i] = renderer.buffer[i]; @@ -57,33 +64,33 @@ void ChunksLoader::_thread(){ } chunks.clear(false); - for (int i = 0; i < CLOSES_C; i++){ - Chunk* other = closes[i]; + for (int i = 0; i < SURROUNDINGS_C; i++){ + Chunk* other = surroundings[i]; if (other) other->decref(); } - chunk->ready = true; + chunk->setReady(true); current = nullptr; chunk->decref(); } } -void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode){ +void ChunksLoader::perform(Chunk* chunk, Chunk** surroundings_passed, LoaderMode mode){ if (isBusy()){ std::cerr << "performing while busy" << std::endl; return; } chunk->incref(); - if (closes == nullptr){ - closes = new Chunk*[CLOSES_C]; + if (surroundings == nullptr){ + surroundings = new Chunk*[SURROUNDINGS_C]; } - for (int i = 0; i < CLOSES_C; i++){ - Chunk* other = closes_passed[i]; + for (int i = 0; i < SURROUNDINGS_C; i++){ + Chunk* other = surroundings_passed[i]; if (other == nullptr) - closes[i] = nullptr; + surroundings[i] = nullptr; else { other->incref(); - closes[i] = other; + surroundings[i] = other; } } current = chunk; @@ -94,6 +101,10 @@ void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){ 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){ perform(chunk, closes_passed, RENDER); } diff --git a/src/voxels/ChunksLoader.h b/src/voxels/ChunksLoader.h index 37c623fd..876b0c8c 100644 --- a/src/voxels/ChunksLoader.h +++ b/src/voxels/ChunksLoader.h @@ -14,7 +14,7 @@ class Chunk; class World; enum LoaderMode { - OFF, IDLE, LOAD, RENDER, + OFF, IDLE, LOAD, LIGHTS, RENDER, }; class ChunksLoader final { @@ -22,7 +22,7 @@ private: std::thread loaderThread; void _thread(); std::atomic current {nullptr}; - std::atomic closes {nullptr}; + std::atomic surroundings {nullptr}; std::atomic state {IDLE}; World* world; @@ -41,6 +41,7 @@ public: } void load(Chunk* chunk, Chunk** closes_passed); + void lights(Chunk* chunk, Chunk** closes_passed); void render(Chunk* chunk, Chunk** closes_passed); void stop(){ diff --git a/src/voxels/WorldGenerator.cpp b/src/voxels/WorldGenerator.cpp index c2a0f047..1664bbda 100644 --- a/src/voxels/WorldGenerator.cpp +++ b/src/voxels/WorldGenerator.cpp @@ -2,6 +2,7 @@ #include "voxel.h" #include "Chunk.h" +#include #include #include #include @@ -9,6 +10,8 @@ #include "../maths/FastNoiseLite.h" #include +#include "../declarations.h" + class PseudoRandom { unsigned short seed; public: @@ -64,7 +67,7 @@ float calc_height_faster(fnl_state *noise, int real_x, int real_z){ height *= 64.0f; return height; } -#include + 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 tileY = floor((double)real_z/(double)tileSize); @@ -92,18 +95,14 @@ int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights, 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(); noise.noise_type = FNL_NOISE_OPENSIMPLEX2; noise.seed = seed * 60617077 % 25896307; - PseudoRandom randomtree; - // PseudoRandom random; float heights[CHUNK_VOL]; - // std::cout << calc_height(&noise, cx, cy) << "\n"; - for (int z = 0; z < CHUNK_D; z++){ for (int x = 0; x < CHUNK_W; x++){ 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]; for (int y = 0; y < CHUNK_H; y++){ - int real_y = y + cy * CHUNK_H; - int id = real_y < 55 ? 9 : 0; - if ((real_y == (int)height) && (54 < real_y)) - id = 2; - else if (real_y < (height - 6)){ - id = 8; + int real_y = y; + int id = real_y < 55 ? BLOCK_WATER : BLOCK_AIR; + if ((real_y == (int)height) && (54 < real_y)) { + id = BLOCK_GRASS_BLOCK; + } else if (real_y < (height - 6)){ + id = BLOCK_STONE; } else if (real_y < height){ - id = 1; + id = BLOCK_DIRT; } else { int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 16); 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)){ - id = 10; + id = BLOCK_SAND; } if (real_y <= 2) - id = 11; + id = BLOCK_BEDROCK; 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)){ - id = 13; + id = BLOCK_FLOWER; } voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id; } diff --git a/src/voxels/WorldGenerator.h b/src/voxels/WorldGenerator.h index ae164319..0b910441 100644 --- a/src/voxels/WorldGenerator.h +++ b/src/voxels/WorldGenerator.h @@ -5,7 +5,7 @@ class voxel; class WorldGenerator { 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_ */ diff --git a/src/window/Camera.cpp b/src/window/Camera.cpp index 1fe9b77c..2cebfa35 100644 --- a/src/window/Camera.cpp +++ b/src/window/Camera.cpp @@ -1,10 +1,3 @@ -/* - * Camera.cpp - * - * Created on: Feb 11, 2020 - * Author: MihailRis - */ - #include "Camera.h" #include "Window.h" @@ -36,7 +29,10 @@ void Camera::rotate(float x, float y, float z){ } 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) return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f); else @@ -50,5 +46,5 @@ mat4 Camera::getView(){ if (perspective) return glm::lookAt(position, position+front, up); else - return glm::mat4(1.0f); + return glm::translate(glm::mat4(1.0f), position); } diff --git a/src/window/Camera.h b/src/window/Camera.h index 28aabe94..3e82bac3 100644 --- a/src/window/Camera.h +++ b/src/window/Camera.h @@ -1,10 +1,3 @@ -/* - * Camera.h - * - * Created on: Feb 11, 2020 - * Author: MihailRis - */ - #ifndef WINDOW_CAMERA_H_ #define WINDOW_CAMERA_H_ @@ -25,6 +18,7 @@ public: mat4 rotation; bool perspective = true; bool flipped = false; + float aspect = 0.0f; Camera(vec3 position, float fov); void rotate(float x, float y, float z); diff --git a/src/window/Window.cpp b/src/window/Window.cpp index a761631e..9031edc7 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -41,6 +41,10 @@ int Window::initialize(int width, int height, const char* title){ return 0; } +void Window::viewport(int x, int y, int width, int height){ + glViewport(x, y, width, height); +} + void Window::setCursorMode(int mode){ glfwSetInputMode(window, GLFW_CURSOR, mode); } diff --git a/src/window/Window.h b/src/window/Window.h index b54e1a58..dfce56b6 100644 --- a/src/window/Window.h +++ b/src/window/Window.h @@ -11,6 +11,7 @@ public: static int initialize(int width, int height, const char* title); static void terminate(); + static void viewport(int x, int y, int width, int height); static void setCursorMode(int mode); static bool isShouldClose(); static void setShouldClose(bool flag); diff --git a/src/world/Level.cpp b/src/world/Level.cpp index a04e722f..d85df92e 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -4,6 +4,7 @@ #include "../player_control.h" Level::Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics) : + world(world), player(player), chunks(chunks), physics(physics) { diff --git a/src/world/Level.h b/src/world/Level.h index 6abb74c1..47728e2a 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -11,6 +11,7 @@ class PlayerController; class Level { public: + World* world; Player* player; Chunks* chunks; PhysicsSolver* physics; diff --git a/src/world_render.cpp b/src/world_render.cpp index 660da4c4..48209214 100644 --- a/src/world_render.cpp +++ b/src/world_render.cpp @@ -1,5 +1,6 @@ #include "world_render.h" +#include #include "graphics/VoxelRenderer.h" #include "window/Window.h" @@ -11,38 +12,24 @@ #include "graphics/Batch3D.h" #include "voxels/Chunks.h" #include "voxels/Chunk.h" +#include "voxels/Block.h" #include "world/World.h" #include "world/Level.h" +#include "objects/Player.h" #include "Assets.h" +#include "player_control.h" float _camera_cx; float _camera_cz; -Mesh *crosshair; - -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); +WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) { lineBatch = new LineBatch(4096); batch3d = new Batch3D(1024); renderer = new VoxelRenderer(); } WorldRenderer::~WorldRenderer() { - delete crosshair; + delete batch3d; delete lineBatch; delete renderer; } @@ -50,71 +37,71 @@ WorldRenderer::~WorldRenderer() { Chunks* _chunks = nullptr; bool chunks_distance_compare(size_t i, size_t j) { - Chunks* chunks = _chunks; - Chunk* a = chunks->chunks[i]; - 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) - > + Chunk* a = _chunks->chunks[i]; + 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) > (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]; Mesh* mesh = level->chunks->meshes[index]; if (mesh == nullptr) - return; + return false; - // Simple frustum culling (culling chunks behind the camera in 2D - XZ) + // Simple frustum culling if (occlusion){ - const float cameraX = camera->position.x; - const float cameraZ = camera->position.z; - const float camDirX = camera->dir.x; - const float camDirZ = camera->dir.z; - - bool unoccluded = false; - do { - if ((chunk->x*CHUNK_W-cameraX)*camDirX + (chunk->z*CHUNK_D-cameraZ)*camDirZ >= 0.0){ - unoccluded = true; break; + float y = camera->position.y+camera->front.y * CHUNK_H * 0.5f; + if (y < 0.0f) + y = 0.0f; + if (y > CHUNK_H) + y = CHUNK_H; + vec3 v = vec3(chunk->x*CHUNK_W, y, chunk->z*CHUNK_D)-camera->position; + if (v.x*v.x+v.z*v.z > (CHUNK_W*3)*(CHUNK_W*3)) { + if (dot(camera->front, v) < 0.0f){ + 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); 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; - 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); + + Window::viewport(0, 0, Window::width, Window::height); + glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); Texture* texture = assets->getTexture("block"); Shader* shader = assets->getShader("main"); - Shader* crosshairShader = assets->getShader("crosshair"); Shader* linesShader = assets->getShader("lines"); shader->use(); shader->uniformMatrix("u_proj", camera->getProjection()); shader->uniformMatrix("u_view", camera->getView()); shader->uniform1f("u_gamma", 1.6f); - shader->uniform3f("u_skyLightColor", 2.2f,2.2f,2.2f); - shader->uniform3f("u_fogColor", 0.7f,0.81f,1.0f); - shader->uniform1f("u_fogFactor", 0.03f); + shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f); + shader->uniform3f("u_fogColor", skyColor.r,skyColor.g,skyColor.b); + shader->uniform1f("u_fogFactor", 0.025f); 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(); std::vector 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); + int occludedChunks = 0; 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)); @@ -145,11 +133,6 @@ void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occl // draw 3D stuff here 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->uniformMatrix("u_projview", camera->getProjection()*camera->getView()); 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+0.01f, camera->position.z, 0, 1, 0, 1); 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); + } + } } diff --git a/src/world_render.h b/src/world_render.h index 124caf8b..d237ed29 100644 --- a/src/world_render.h +++ b/src/world_render.h @@ -21,21 +21,23 @@ class LineBatch; class Batch3D; class VoxelRenderer; class Shader; +class Texture; +class Framebuffer; class WorldRenderer { Batch3D *batch3d; + Assets* assets; Level* level; - - void drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); + bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); public: VoxelRenderer *renderer; LineBatch *lineBatch; - WorldRenderer(Level* level); + WorldRenderer(Level* level, Assets* assets); ~WorldRenderer(); - void draw(World* world, Camera* camera, Assets* assets, bool occlusion); + void draw(World* world, Camera* camera, bool occlusion); };