world-wide commit to ruin everything

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

View File

@ -11,6 +11,9 @@ CPP_SRCS += \
../src/graphics/Mesh.cpp \
../src/graphics/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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 793 B

View File

@ -11,10 +11,11 @@ uniform float u_fogFactor;
void main(){
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;
}

View File

@ -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;
}

View File

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -12,5 +12,5 @@ uniform mat4 u_projview;
void main(){
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);
}

View File

@ -15,7 +15,7 @@ std::vector<ALSource*> Audio::freesources;
std::vector<ALBuffer*> Audio::allbuffers;
std::vector<ALBuffer*> 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<std::string>& 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);

View File

@ -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<std::string>& devicesVec);
static void setOrientation(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
static void setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
};

154
src/declarations.cpp Normal file
View File

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

View File

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

View File

@ -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<long, char**>::iterator it;
std::unordered_map<long, WorldRegion>::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<long, char**>::iterator it;
std::unordered_map<long, WorldRegion>::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;

View File

@ -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<long, char**> regions;
std::unordered_map<long, WorldRegion> regions;
std::string directory;
char* mainBufferIn;
char* mainBufferOut;

View File

@ -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;
}

View File

@ -1,6 +1,7 @@
#include "Batch2D.h"
#include "Mesh.h"
#include "Texture.h"
#include "Sprite.h"
#include <GL/glew.h>
@ -86,6 +87,116 @@ void Batch2D::rect(float x, float y, float w, float h){
vertex(x+w, y+h, 1, 1, r,g,b,a);
}
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),

View File

@ -4,16 +4,18 @@
#include <stdlib.h>
#include <glm/glm.hpp>
#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,

View File

@ -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
};

View File

@ -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;

View File

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

View File

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

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

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

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

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

View File

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

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

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

View File

@ -12,7 +12,7 @@
#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X))
#define LOCAL(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<float>& 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<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
float l;
float uvsize = 1.0f/16.0f;
@ -61,10 +55,10 @@ inline void _renderBlock(std::vector<float>& 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<float>& 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<float>& 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<float>& 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<float>& 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<float>& 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<float>& buffer, int x, int y, int z, const
}
}
inline void _renderBlockShadeless(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
float l;
float uvsize = 1.0f/16.0f;
Block* block = Block::blocks[id];
unsigned char group = block->drawGroup;
if (!IS_BLOCKED(x,y+1,z,group)){
SETUP_UV(block->textureFaces[3]);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, 1,1,1,0);
}
if (!IS_BLOCKED(x,y-1,z,group)){
SETUP_UV(block->textureFaces[2]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x+1,y,z,group)){
SETUP_UV(block->textureFaces[1]);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
}
if (!IS_BLOCKED(x-1,y,z,group)){
SETUP_UV(block->textureFaces[0]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x,y,z+1,group)){
SETUP_UV(block->textureFaces[5]);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
}
if (!IS_BLOCKED(x,y,z-1,group)){
SETUP_UV(block->textureFaces[4]);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
}
}
inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){
@ -304,101 +372,88 @@ inline void _renderXBlock(std::vector<float>& 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);
}
}
}

View File

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

View File

@ -1,12 +1,15 @@
#include "hud_render.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#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);
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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();

View File

@ -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);
};

View File

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

View File

@ -102,6 +102,8 @@ int _png_load(const char* file, int* width, int* height){
alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data);
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;

View File

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

View File

@ -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;
}
}
}
}

View File

@ -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);
};

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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_ */

View File

@ -11,8 +11,8 @@
#include <math.h>
#include <limits.h>
Chunks::Chunks(int w, int h, int d, int ox, int oy, int oz) : w(w), h(h), d(d), ox(ox), oy(oy), oz(oz){
volume = w*h*d;
Chunks::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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -12,10 +12,10 @@
#include <iostream>
#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);
}

View File

@ -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<Chunk*> current {nullptr};
std::atomic<Chunk**> closes {nullptr};
std::atomic<Chunk**> surroundings {nullptr};
std::atomic<LoaderMode> 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(){

View File

@ -2,6 +2,7 @@
#include "voxel.h"
#include "Chunk.h"
#include <iostream>
#include <math.h>
#include <glm/glm.hpp>
#include <glm/gtc/noise.hpp>
@ -9,6 +10,8 @@
#include "../maths/FastNoiseLite.h"
#include <time.h>
#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 <iostream>
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;
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

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

View File

@ -1,5 +1,6 @@
#include "world_render.h"
#include <iostream>
#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<size_t> indices;
@ -136,8 +123,9 @@ void WorldRenderer::draw(World* world, Camera* camera, Assets* assets, bool occl
std::sort(indices.begin(), indices.end(), chunks_distance_compare);
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);
}
}
}

View File

@ -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);
};