diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bfc3f09e..82186ad0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,4 +43,4 @@ endif() target_link_libraries(${PROJECT_NAME} ${LIBS} glfw OpenGL::GL ${OPENAL_LIBRARY} GLEW::GLEW ${PNGLIB}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/build) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/Assets.cpp b/src/Assets.cpp index 64f7d6b51..c0666a241 100644 --- a/src/Assets.cpp +++ b/src/Assets.cpp @@ -18,8 +18,11 @@ Assets::~Assets() { } } -Texture* Assets::getTexture(std::string name){ - return textures[name]; +Texture* Assets::getTexture(std::string name) const { + auto found = textures.find(name); + if (found == textures.end()) + return nullptr; + return found->second; } void Assets::store(Texture* texture, std::string name){ @@ -27,8 +30,11 @@ void Assets::store(Texture* texture, std::string name){ } -Shader* Assets::getShader(std::string name){ - return shaders[name]; +Shader* Assets::getShader(std::string name) const{ + auto found = shaders.find(name); + if (found == shaders.end()) + return nullptr; + return found->second; } void Assets::store(Shader* shader, std::string name){ @@ -36,8 +42,11 @@ void Assets::store(Shader* shader, std::string name){ } -Font* Assets::getFont(std::string name){ - return fonts[name]; +Font* Assets::getFont(std::string name) const { + auto found = fonts.find(name); + if (found == fonts.end()) + return nullptr; + return found->second; } void Assets::store(Font* font, std::string name){ diff --git a/src/Assets.h b/src/Assets.h index 3dc9fa5d9..61fd9d5b9 100644 --- a/src/Assets.h +++ b/src/Assets.h @@ -14,13 +14,13 @@ class Assets { std::unordered_map fonts; public: ~Assets(); - Texture* getTexture(std::string name); + Texture* getTexture(std::string name) const; void store(Texture* texture, std::string name); - Shader* getShader(std::string name); + Shader* getShader(std::string name) const; void store(Shader* shader, std::string name); - Font* getFont(std::string name); + Font* getFont(std::string name) const; void store(Font* font, std::string name); }; diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 000000000..fc0ae25f4 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,17 @@ +#ifndef SRC_CONSTANTS_H_ +#define SRC_CONSTANTS_H_ + +#include "typedefs.h" + +#define CHUNK_W 16 +#define CHUNK_H 256 +#define CHUNK_D 16 +#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D) + +#define BLOCK_VOID (blockid_t)((2 << (sizeof(blockid_t)*8)) - 1) + +inline uint vox_index(int x, int y, int z, int w, int d) { + return (y * d + z) * w + x; +} + +#endif // SRC_CONSTANTS_H_ \ No newline at end of file diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index b4c621025..681b2896c 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -4,12 +4,10 @@ #include "../window/Camera.h" #include "../objects/Player.h" #include "../physics/Hitbox.h" +#include "../voxels/voxel.h" #include "../voxels/Chunk.h" - -union { - long _key; - int _coords[2]; -} _tempcoords; +#include "../typedefs.h" +#include "../voxmaths.h" #include #include @@ -22,21 +20,25 @@ union { #define SECTION_FLAGS 3 #define PLAYER_FLAG_FLIGHT 0x1 #define PLAYER_FLAG_NOCLIP 0x2 +#define CHUNK_DATA_LEN (CHUNK_VOL*sizeof(voxel)) + +using glm::ivec2; +using glm::vec3; -unsigned long WorldFiles::totalCompressed = 0; +int64_t WorldFiles::totalCompressed = 0; -int bytes2Int(const unsigned char* src, unsigned int offset){ +int bytes2Int(const ubyte* src, size_t offset){ return (src[offset] << 24) | (src[offset+1] << 16) | (src[offset+2] << 8) | (src[offset+3]); } -void int2Bytes(int value, char* dest, unsigned int offset){ +void int2Bytes(int value, ubyte* dest, size_t offset){ dest[offset] = (char) (value >> 24 & 255); dest[offset+1] = (char) (value >> 16 & 255); dest[offset+2] = (char) (value >> 8 & 255); dest[offset+3] = (char) (value >> 0 & 255); } -void floatToBytes(float fvalue, char* dest, unsigned int offset){ +void floatToBytes(float fvalue, ubyte* dest, size_t offset){ uint32_t value = *((uint32_t*)&fvalue); dest[offset] = (char) (value >> 24 & 255); dest[offset+1] = (char) (value >> 16 & 255); @@ -44,8 +46,7 @@ void floatToBytes(float fvalue, char* dest, unsigned int offset){ dest[offset+3] = (char) (value >> 0 & 255); } -float bytes2Float(char* srcs, unsigned int offset){ - unsigned char* src = (unsigned char*) srcs; +float bytes2Float(ubyte* src, uint offset){ uint32_t value = ((src[offset] << 24) | (src[offset+1] << 16) | (src[offset+2] << 8) | @@ -54,15 +55,14 @@ float bytes2Float(char* srcs, unsigned int offset){ } WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : directory(directory){ - mainBufferIn = new char[CHUNK_VOL*2]; - mainBufferOut = new char[mainBufferCapacity]; + mainBufferIn = new ubyte[CHUNK_DATA_LEN]; + mainBufferOut = new ubyte[mainBufferCapacity]; } WorldFiles::~WorldFiles(){ delete[] mainBufferIn; delete[] mainBufferOut; - std::unordered_map::iterator it; - for (it = regions.begin(); it != regions.end(); it++){ + for (auto it = regions.begin(); it != regions.end(); it++){ WorldRegion region = it->second; if (region.chunksData == nullptr) continue; @@ -74,31 +74,35 @@ WorldFiles::~WorldFiles(){ regions.clear(); } -void WorldFiles::put(const char* chunkData, int x, int y){ +void WorldFiles::put(const ubyte* chunkData, int x, int y){ assert(chunkData != nullptr); - int regionX = x >> REGION_SIZE_BIT; - int regionY = y >> REGION_SIZE_BIT; + int regionX = floordiv(x, REGION_SIZE); + int regionY = floordiv(y, REGION_SIZE); - int localX = x - (regionX << REGION_SIZE_BIT); - int localY = y - (regionY << REGION_SIZE_BIT); + int localX = x - (regionX * REGION_SIZE); + int localY = y - (regionY * REGION_SIZE); - _tempcoords._coords[0] = regionX; - _tempcoords._coords[1] = regionY; - 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.chunksData[i] = nullptr; + ivec2 key(regionX, regionY); + + auto found = regions.find(key); + if (found == regions.end()) { + ubyte** chunksData = new ubyte*[REGION_VOL]; + for (uint i = 0; i < REGION_VOL; i++) { + chunksData[i] = nullptr; + } + regions[key] = { chunksData, true }; } - char* targetChunk = region.chunksData[localY * REGION_SIZE + localX]; + + WorldRegion& region = regions[key]; + region.unsaved = true; + ubyte* targetChunk = region.chunksData[localY * REGION_SIZE + localX]; if (targetChunk == nullptr){ - targetChunk = new char[CHUNK_VOL]; + targetChunk = new ubyte[CHUNK_DATA_LEN]; region.chunksData[localY * REGION_SIZE + localX] = targetChunk; - totalCompressed += CHUNK_VOL; + totalCompressed += CHUNK_DATA_LEN; } - for (unsigned int i = 0; i < CHUNK_VOL; i++) + for (uint i = 0; i < CHUNK_DATA_LEN; i++) targetChunk[i] = chunkData[i]; } @@ -111,44 +115,46 @@ std::string WorldFiles::getPlayerFile() { return directory + "/player.bin"; } -bool WorldFiles::getChunk(int x, int y, char* out){ +bool WorldFiles::getChunk(int x, int y, ubyte* out){ assert(out != nullptr); - int regionX = x >> REGION_SIZE_BIT; - int regionY = y >> REGION_SIZE_BIT; + int regionX = floordiv(x, REGION_SIZE); + int regionY = floordiv(y, REGION_SIZE); + + int localX = x - (regionX * REGION_SIZE); + int localY = y - (regionY * REGION_SIZE); - int localX = x - (regionX << REGION_SIZE_BIT); - int localY = y - (regionY << REGION_SIZE_BIT); int chunkIndex = localY * REGION_SIZE + localX; assert(chunkIndex >= 0 && chunkIndex < REGION_VOL); - _tempcoords._coords[0] = regionX; - _tempcoords._coords[1] = regionY; + ivec2 key(regionX, regionY); - WorldRegion& region = regions[_tempcoords._key]; - if (region.chunksData == nullptr) - return readChunk(x,y,out); + auto found = regions.find(key); + if (found == regions.end()) { + return readChunk(x, y, out); + } - char* chunk = region.chunksData[chunkIndex]; + WorldRegion& region = found->second; + ubyte* chunk = region.chunksData[chunkIndex]; if (chunk == nullptr) return readChunk(x,y,out); - for (unsigned int i = 0; i < CHUNK_VOL; i++) + for (uint i = 0; i < CHUNK_DATA_LEN; i++) out[i] = chunk[i]; return true; } -bool WorldFiles::readChunk(int x, int y, char* out){ +bool WorldFiles::readChunk(int x, int y, ubyte* out){ assert(out != nullptr); - int regionX = x >> REGION_SIZE_BIT; - int regionY = y >> REGION_SIZE_BIT; + int regionX = floordiv(x, REGION_SIZE); + int regionY = floordiv(y, REGION_SIZE); + + int localX = x - (regionX * REGION_SIZE); + int localY = y - (regionY * REGION_SIZE); - int localX = x - (regionX << REGION_SIZE_BIT); - int localY = y - (regionY << REGION_SIZE_BIT); int chunkIndex = localY * REGION_SIZE + localX; std::string filename = getRegionFile(regionX, regionY); - std::ifstream input(filename, std::ios::binary); if (!input.is_open()){ return false; @@ -166,35 +172,31 @@ bool WorldFiles::readChunk(int x, int y, char* out){ } input.seekg(offset); input.read((char*)(&offset), 4); - size_t compressedSize = bytes2Int((const unsigned char*)(&offset), 0); - - input.read(mainBufferIn, compressedSize); + size_t compressedSize = bytes2Int((const ubyte*)(&offset), 0); + input.read((char*)mainBufferIn, compressedSize); input.close(); - decompressRLE((unsigned char*)mainBufferIn, compressedSize, (unsigned char*)out, CHUNK_VOL); + decompressRLE((ubyte*)mainBufferIn, compressedSize, (ubyte*)out, CHUNK_DATA_LEN); return true; } void WorldFiles::write(){ - std::unordered_map::iterator it; - for (it = regions.begin(); it != regions.end(); it++){ + for (auto it = regions.begin(); it != regions.end(); it++){ if (it->second.chunksData == nullptr || !it->second.unsaved) continue; - int x; - int y; - longToCoords(x,y, it->first); + ivec2 key = it->first; - unsigned int size = writeRegion(mainBufferOut, x,y, it->second.chunksData); - write_binary_file(getRegionFile(x,y), mainBufferOut, size); + unsigned int size = writeRegion(mainBufferOut, key.x, key.y, it->second.chunksData); + write_binary_file(getRegionFile(key.x, key.y), (const char*)mainBufferOut, size); } } void WorldFiles::writePlayer(Player* player){ - char dst[1+3*4 + 1+2*4 + 1+1]; + ubyte dst[1+3*4 + 1+2*4 + 1+1]; - glm::vec3 position = player->hitbox->position; + vec3 position = player->hitbox->position; size_t offset = 0; dst[offset++] = SECTION_POSITION; @@ -215,12 +217,12 @@ void WorldFiles::writePlayer(Player* player){ bool WorldFiles::readPlayer(Player* player) { size_t length = 0; - char* data = read_binary_file(getPlayerFile(), length); + ubyte* data = (ubyte*)read_binary_file(getPlayerFile(), length); if (data == nullptr){ std::cerr << "could not to read player.bin (ignored)" << std::endl; return false; } - glm::vec3 position = player->hitbox->position; + vec3 position = player->hitbox->position; size_t offset = 0; while (offset < length){ char section = data[offset++]; @@ -248,21 +250,19 @@ bool WorldFiles::readPlayer(Player* player) { return true; } -unsigned int WorldFiles::writeRegion(char* out, int x, int y, char** region){ - unsigned int offset = REGION_VOL * 4; - for (unsigned int i = 0; i < offset; i++) +uint WorldFiles::writeRegion(ubyte* out, int x, int y, ubyte** region){ + uint offset = REGION_VOL * 4; + for (uint i = 0; i < offset; i++) out[i] = 0; - char* compressed = new char[CHUNK_VOL*2]; + ubyte* compressed = new ubyte[CHUNK_DATA_LEN]; for (int i = 0; i < REGION_VOL; i++){ - char* chunk = region[i]; + ubyte* chunk = region[i]; if (chunk == nullptr){ - chunk = new char[CHUNK_VOL]; - assert((((i % REGION_SIZE) + x * REGION_SIZE) >> REGION_SIZE_BIT) == x); - assert((((i / REGION_SIZE) + y * REGION_SIZE) >> REGION_SIZE_BIT) == y); + chunk = new ubyte[CHUNK_DATA_LEN]; if (readChunk((i % REGION_SIZE) + x * REGION_SIZE, (i / REGION_SIZE) + y * REGION_SIZE, chunk)){ region[i] = chunk; - totalCompressed += CHUNK_VOL; + totalCompressed += CHUNK_DATA_LEN; } else { delete[] chunk; chunk = nullptr; @@ -274,21 +274,15 @@ unsigned int WorldFiles::writeRegion(char* out, int x, int y, char** region){ } else { int2Bytes(offset, out, i*4); - unsigned int compressedSize = compressRLE((unsigned char*)chunk, CHUNK_VOL, (unsigned char*)compressed); + uint compressedSize = compressRLE(chunk, CHUNK_DATA_LEN, compressed); int2Bytes(compressedSize, out, offset); offset += 4; - for (unsigned int j = 0; j < compressedSize; j++) + for (uint j = 0; j < compressedSize; j++) out[offset++] = compressed[j]; } } delete[] compressed; return offset; } - -void longToCoords(int& x, int& y, long key) { - _tempcoords._key = key; - x = _tempcoords._coords[0]; - y = _tempcoords._coords[1]; -} diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 70ebc55b6..20628d955 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -4,6 +4,13 @@ #include #include #include + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/gtx/hash.hpp" + +#include "../typedefs.h" + class Player; #define REGION_SIZE_BIT 5 @@ -11,28 +18,27 @@ class Player; #define REGION_VOL ((REGION_SIZE) * (REGION_SIZE)) struct WorldRegion { - char** chunksData; + ubyte** chunksData; bool unsaved; }; class WorldFiles { public: - static unsigned long totalCompressed; - std::unordered_map regions; + static int64_t totalCompressed; + std::unordered_map regions; std::string directory; - char* mainBufferIn; - char* mainBufferOut; + ubyte* mainBufferIn; + ubyte* mainBufferOut; WorldFiles(std::string directory, size_t mainBufferCapacity); ~WorldFiles(); - void put(const char* chunkData, int x, int y); + void put(const ubyte* chunkData, int x, int y); bool readPlayer(Player* player); - bool readChunk(int x, int y, char* out); - bool getChunk(int x, int y, char* out); - void readRegion(char* fileContent); - unsigned int writeRegion(char* out, int x, int y, char** region); + bool readChunk(int x, int y, ubyte* out); + bool getChunk(int x, int y, ubyte* out); + uint writeRegion(ubyte* out, int x, int y, ubyte** region); void writePlayer(Player* player); void write(); @@ -40,6 +46,4 @@ class WorldFiles { std::string getPlayerFile(); }; -extern void longToCoords(int& x, int& y, long key); - #endif /* FILES_WORLDFILES_H_ */ diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index c0029d3ad..41e65030e 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -8,8 +8,8 @@ #define VERTEX_SIZE 8 Batch2D::Batch2D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 1.0f){ - const int attrs[] = { - 2, 2, 4, 0 //null terminator + const vattr attrs[] = { + {2}, {2}, {4}, {0} }; buffer = new float[capacity * VERTEX_SIZE]; diff --git a/src/graphics/Batch3D.cpp b/src/graphics/Batch3D.cpp index 2531969a1..57b38c7d2 100644 --- a/src/graphics/Batch3D.cpp +++ b/src/graphics/Batch3D.cpp @@ -8,8 +8,8 @@ #define VERTEX_SIZE 9 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 + const vattr attrs[] = { + {3}, {2}, {4}, {0} }; buffer = new float[capacity * VERTEX_SIZE]; diff --git a/src/graphics/BlocksRenderer.cpp b/src/graphics/BlocksRenderer.cpp new file mode 100644 index 000000000..d6c06a7a0 --- /dev/null +++ b/src/graphics/BlocksRenderer.cpp @@ -0,0 +1,352 @@ +#include "BlocksRenderer.h" + +#include + +#include "Mesh.h" +#include "UVRegion.h" +#include "../constants.h" +#include "../voxels/Block.h" +#include "../voxels/Chunk.h" +#include "../voxels/VoxelsVolume.h" +#include "../voxels/ChunksStorage.h" +#include "../lighting/Lightmap.h" + +using glm::ivec3; +using glm::vec3; +using glm::vec4; + +#define VERTEX_SIZE 9 + +BlocksRenderer::BlocksRenderer(size_t capacity) : offset(0), capacity(capacity) { + buffer = new float[capacity]; + voxelsBuffer = new VoxelsVolume(CHUNK_W + 2, CHUNK_H, CHUNK_D + 2); +} + + +BlocksRenderer::~BlocksRenderer() { + delete voxelsBuffer; + delete[] buffer; +} + +void BlocksRenderer::vertex(vec3 coord, + float u, float v, + vec4 light) { + buffer[offset++] = coord.x; + buffer[offset++] = coord.y; + buffer[offset++] = coord.z; + + buffer[offset++] = u; + buffer[offset++] = v; + + buffer[offset++] = light.r; + buffer[offset++] = light.g; + buffer[offset++] = light.b; + buffer[offset++] = light.a; +} + +void BlocksRenderer::face(vec3 coord, float w, float h, + const vec3 axisX, + const vec3 axisY, + const UVRegion& region, + const vec4 lights[4], + const vec4 tint) { + if (offset + VERTEX_SIZE * 6 > capacity) { + overflow = true; + return; + } + vertex(coord, region.u1, region.v1, lights[0] * tint); + vertex(coord + axisX * w, region.u2, region.v1, lights[1] * tint); + vertex(coord + axisX * w + axisY * h, region.u2, region.v2, lights[2] * tint); + + vertex(coord, region.u1, region.v1, lights[0] * tint); + vertex(coord + axisX * w + axisY * h, region.u2, region.v2, lights[2] * tint); + vertex(coord + axisY * h, region.u1, region.v2, lights[3] * tint); +} + +void BlocksRenderer::face(vec3 coord, float w, float h, + const vec3 axisX, + const vec3 axisY, + const UVRegion& region, + const vec4 lights[4], + const vec4 tint, + bool rotated) { + if (offset + VERTEX_SIZE * 6 > capacity) { + overflow = true; + return; + } + if (rotated) { + vertex(coord, region.u2, region.v1, lights[0] * tint); + vertex(coord + axisX * w, region.u2, region.v2, lights[1] * tint); + vertex(coord + axisX * w + axisY * h, region.u1, region.v2, lights[2] * tint); + + vertex(coord, region.u2, region.v1, lights[0] * tint); + vertex(coord + axisX * w + axisY * h, region.u1, region.v2, lights[2] * tint); + vertex(coord + axisY * h, region.u1, region.v1, lights[3] * tint); + } + else { + vertex(coord, region.u1, region.v1, lights[0] * tint); + vertex(coord + axisX * w, region.u2, region.v1, lights[1] * tint); + vertex(coord + axisX * w + axisY * h, region.u2, region.v2, lights[2] * tint); + + vertex(coord, region.u1, region.v1, lights[0] * tint); + vertex(coord + axisX * w + axisY * h, region.u2, region.v2, lights[2] * tint); + vertex(coord + axisY * h, region.u1, region.v2, lights[3] * tint); + } +} + +void BlocksRenderer::cube(vec3 coord, vec3 size, const UVRegion texfaces[6]) { + vec4 lights[]{ vec4(),vec4(),vec4(),vec4() }; + + face(coord, size.x, size.y, vec3(1, 0, 0), vec3(0, 1, 0), texfaces[0], lights); + face(coord + vec3(size.x, 0, -size.z), size.x, size.y, vec3(-1, 0, 0), vec3(0, 1, 0), texfaces[1], lights); + + face(coord + vec3(0, size.y, 0), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, -1), texfaces[2], lights); + face(coord + vec3(0, 0, -size.z), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, 1), texfaces[3], lights); + + face(coord + vec3(0, 0, -size.z), size.z, size.y, vec3(0, 0, 1), vec3(0, 1, 0), texfaces[4], lights); + face(coord + vec3(size.x, 0, 0), size.z, size.y, vec3(0, 0, -1), vec3(0, 1, 0), texfaces[5], lights); +} + +constexpr vec4 do_tint(float value) { + return vec4(value, value, value, 1.0f); +} + +void BlocksRenderer::blockCube(int x, int y, int z, vec3 size, const UVRegion texfaces[6], ubyte group) { + vec4 lights[]{ vec4(1.0f), vec4(1.0f), vec4(1.0f), vec4(1.0f) }; + if (isOpen(x, y, z + 1, group)) { + face(vec3(x, y, z), size.x, size.y, vec3(1, 0, 0), vec3(0, 1, 0), texfaces[5], lights, do_tint(0.9f)); + } + if (isOpen(x, y, z - 1, group)) { + face(vec3(x + size.x, y, z - size.z), size.x, size.y, vec3(-1, 0, 0), vec3(0, 1, 0), texfaces[4], lights, vec4(1.0f)); + } + + if (isOpen(x, y + 1, z, group)) { + face(vec3(x, y + size.y, z), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, -1), texfaces[3], lights); + } + + if (isOpen(x, y - 1, z, group)) { + face(vec3(x, y, z - size.z), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, 1), texfaces[2], lights, vec4(1.0f)); + } + + if (isOpen(x - 1, y, z, group)) { + face(vec3(x, y, z - size.z), size.z, size.y, vec3(0, 0, 1), vec3(0, 1, 0), texfaces[0], lights, vec4(1.0f)); + } + if (isOpen(x + 1, y, z, group)) { + face(vec3(x + size.x, y, z), size.z, size.y, vec3(0, 0, -1), vec3(0, 1, 0), texfaces[1], lights, vec4(1.0f)); + } +} + +void BlocksRenderer::blockXSprite(int x, int y, int z, vec3 size, const UVRegion texface1, const UVRegion texface2, float spread) { + vec4 lights[]{ + pickSoftLight(x, y, z, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x + 1, y, z, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x + 1, y + 1, z, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x, y + 1, z, {1, 0, 0}, {0, 1, 0}) }; + + int rand = ((x * z + y) ^ (z * y - x)) * (z + y); + + float xs = ((float)(char)rand / 512) * spread; + float zs = ((float)(char)(rand >> 8) / 512) * spread; + + const float w = size.x/1.41f; + face(vec3(x + xs + (1.0 - w) * 0.5f, y, + z + zs - 1 + (1.0 - w) * 0.5f), w, size.y, + vec3(1.0f, 0, 1.0f), vec3(0, 1, 0), texface1, lights, do_tint(0.9f)); + face(vec3(x + xs - (1.0 - w) * 0.5f + 1, y, + z + zs - (1.0 - w) * 0.5f), w, size.y, + vec3(-1.0f, 0, -1.0f), vec3(0, 1, 0), texface1, lights, do_tint(0.9f)); + + face(vec3(x + xs + (1.0 - w) * 0.5f, y, + z + zs - (1.0 - w) * 0.5f), w, size.y, + vec3(1.0f, 0, -1.0f), vec3(0, 1, 0), texface2, lights, do_tint(0.9f)); + face(vec3(x + xs - (1.0 - w) * 0.5f + 1, y, + z + zs + (1.0 - w) * 0.5f - 1), w, size.y, + vec3(-1.0f, 0, 1.0f), vec3(0, 1, 0), texface2, lights, do_tint(0.9f)); +} + +void BlocksRenderer::blockCubeShaded(int x, int y, int z, vec3 size, const UVRegion texfaces_[6], const Block* block, ubyte states) { + ubyte group = block->drawGroup; + UVRegion texfaces[6]; + int rot = 0; + + for (int i = 0; i < 6; i++) { + texfaces[i] = texfaces_[i]; + } + + if (block->rotatable) { + if (states == 0x31) { + rot = 1; + texfaces[0] = texfaces_[2]; + texfaces[1] = texfaces_[3]; + texfaces[2] = texfaces_[0]; + texfaces[3] = texfaces_[1]; + } + else if (states == 0x32) { + rot = 2; + } + else if (states == 0x33) { + rot = 3; + texfaces[2] = texfaces_[4]; + texfaces[3] = texfaces_[5]; + texfaces[4] = texfaces_[2]; + texfaces[5] = texfaces_[3]; + } + } + if (isOpen(x, y, z + 1, group)) { + vec4 lights[]{ + pickSoftLight(x, y, z + 1, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x + 1, y, z + 1, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x + 1, y + 1, z + 1, {1, 0, 0}, {0, 1, 0}), + pickSoftLight(x, y + 1, z + 1, {1, 0, 0}, {0, 1, 0}) }; + face(vec3(x, y, z), size.x, size.y, vec3(1, 0, 0), vec3(0, 1, 0), texfaces[5], lights, do_tint(0.9f), rot == 1); + } + if (isOpen(x, y, z - 1, group)) { + vec4 lights[]{ + pickSoftLight(x, y, z - 1, {-1, 0, 0}, {0, 1, 0}), + pickSoftLight(x - 1, y, z - 1, {-1, 0, 0}, {0, 1, 0}), + pickSoftLight(x - 1, y + 1, z - 1, {-1, 0, 0}, {0, 1, 0}), + pickSoftLight(x, y + 1, z - 1, {-1, 0, 0}, {0, 1, 0}) }; + face(vec3(x + size.x, y, z - size.z), size.x, size.y, vec3(-1, 0, 0), vec3(0, 1, 0), texfaces[4], lights, do_tint(0.75f), rot == 1); + } + + if (isOpen(x, y + 1, z, group)) { + vec4 lights[]{ + pickSoftLight(x, y + 1, z + 1, {1, 0, 0}, {0, 0, 1}), + pickSoftLight(x + 1, y + 1, z + 1, {1, 0, 0}, {0, 0, 1}), + pickSoftLight(x + 1, y + 1, z, {1, 0, 0}, {0, 0, 1}), + pickSoftLight(x, y + 1, z, {1, 0, 0}, {0, 0, 1}) }; + + face(vec3(x, y + size.y, z), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, -1), texfaces[3], lights, vec4(1.0f), rot == 1); + } + + if (isOpen(x, y - 1, z, group)) { + vec4 lights[]{ + pickSoftLight(x, y - 1, z - 1, {1, 0, 0}, {0, 0, -1}), + pickSoftLight(x + 1, y - 1, z - 1, {1, 0, 0}, {0, 0,-1}), + pickSoftLight(x + 1, y - 1, z, {1, 0, 0}, {0, 0, -1}), + pickSoftLight(x, y - 1, z, {1, 0, 0}, {0, 0, -1}) }; + face(vec3(x, y, z - size.z), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, 1), texfaces[2], lights, do_tint(0.6f), rot == 1); + } + + if (isOpen(x - 1, y, z, group)) { + vec4 lights[]{ + pickSoftLight(x - 1, y, z - 1, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x - 1, y, z, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x - 1, y + 1, z, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x - 1, y + 1, z - 1, {0, 0, -1}, {0, 1, 0}) }; + face(vec3(x, y, z - size.z), size.z, size.y, vec3(0, 0, 1), vec3(0, 1, 0), texfaces[0], lights, do_tint(0.7f), rot == 3); + } + if (isOpen(x + 1, y, z, group)) { + vec4 lights[]{ + pickSoftLight(x + 1, y, z, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x + 1, y, z - 1, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x + 1, y + 1, z - 1, {0, 0, -1}, {0, 1, 0}), + pickSoftLight(x + 1, y + 1, z, {0, 0, -1}, {0, 1, 0}) }; + face(vec3(x + size.x, y, z), size.z, size.y, vec3(0, 0, -1), vec3(0, 1, 0), texfaces[1], lights, do_tint(0.8f), rot == 3); + } +} + +// Does block allow to see other blocks sides (is it transparent) +bool BlocksRenderer::isOpen(int x, int y, int z, ubyte group) const { + blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); + if (id == BLOCK_VOID) + return false; + const Block& block = *Block::blocks[id]; + if (block.drawGroup != group) { + return true; + } + return !id; +} + +bool BlocksRenderer::isOpenForLight(int x, int y, int z) const { + blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); + if (id == BLOCK_VOID) + return false; + const Block& block = *Block::blocks[id]; + if (block.lightPassing) { + return true; + } + return !id; +} + +vec4 BlocksRenderer::pickLight(int x, int y, int z) const { + if (isOpenForLight(x, y, z)) { + light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); + return vec4(Lightmap::extract(light, 0) / 15.0f, + Lightmap::extract(light, 1) / 15.0f, + Lightmap::extract(light, 2) / 15.0f, + Lightmap::extract(light, 3) / 15.0f); + } + else { + return vec4(0.0f); + } +} + +vec4 BlocksRenderer::pickSoftLight(int x, int y, int z, ivec3 right, ivec3 up) const { + return (pickLight(x - right.x - up.x, y - right.y - up.y, z - right.z - up.z) + + pickLight(x - up.x, y - up.y, z - up.z) + + pickLight(x, y, z) + + pickLight(x - right.x, y - right.y, z - right.z)) * 0.25f; +} + +// Get texture atlas UV region for block face +inline UVRegion uvfor(const Block& def, uint face, int atlas_size) { + float uvsize = 1.0f / (float)atlas_size; + const uint id = def.textureFaces[face]; + float u = (id % atlas_size) * uvsize; + float v = 1.0f - (id / atlas_size + 1) * uvsize; + return UVRegion(u, v, u + uvsize, v + uvsize); +} + +void BlocksRenderer::render(const voxel* voxels, int atlas_size) { + for (ubyte group = 0; group < 8; group++) { + for (uint y = 0; y < CHUNK_H; y++) { + for (uint z = 0; z < CHUNK_D; z++) { + for (uint x = 0; x < CHUNK_W; x++) { + const voxel& vox = voxels[((y * CHUNK_D) + z) * CHUNK_W + x]; + blockid_t id = vox.id; + const Block& def = *Block::blocks[id]; + if (!id || def.drawGroup != group) + continue; + const UVRegion texfaces[6]{ uvfor(def, 0, atlas_size), uvfor(def, 1, atlas_size), + uvfor(def, 2, atlas_size), uvfor(def, 3, atlas_size), + uvfor(def, 4, atlas_size), uvfor(def, 5, atlas_size) }; + switch (def.model) { + case BLOCK_MODEL_CUBE: + if (*((light_t*)&def.emission)) { + blockCube(x, y, z, vec3(1, 1, 1), texfaces, def.drawGroup); + } + else { + blockCubeShaded(x, y, z, vec3(1, 1, 1), texfaces, &def, vox.states); + } + break; + case BLOCK_MODEL_X_SPRITE: { + blockXSprite(x, y, z, vec3(1, 1, 1), texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); + break; + } + } + if (overflow) + return; + } + } + } + } +} + +Mesh* BlocksRenderer::render(const Chunk* chunk, int atlas_size, const ChunksStorage* chunks) { + this->chunk = chunk; + voxelsBuffer->setPosition(chunk->x * CHUNK_W - 1, 0, chunk->z * CHUNK_D - 1); + chunks->getVoxels(voxelsBuffer); + overflow = false; + offset = 0; + const voxel* voxels = chunk->voxels; + render(voxels, atlas_size); + + const vattr attrs[]{ {3}, {2}, {4}, {0} }; + Mesh* mesh = new Mesh(buffer, offset / VERTEX_SIZE, attrs); + return mesh; +} + +VoxelsVolume* BlocksRenderer::getVoxelsBuffer() const { + return voxelsBuffer; +} diff --git a/src/graphics/BlocksRenderer.h b/src/graphics/BlocksRenderer.h new file mode 100644 index 000000000..fd6e542b3 --- /dev/null +++ b/src/graphics/BlocksRenderer.h @@ -0,0 +1,71 @@ +#ifndef GRAPHICS_BLOCKS_RENDERER_H +#define GRAPHICS_BLOCKS_RENDERER_H + +#include +#include +#include "UVRegion.h" +#include "../typedefs.h" +#include "../voxels/voxel.h" + +class Mesh; +class Block; +class Chunk; +class Chunks; +class VoxelsVolume; +class ChunksStorage; + +class BlocksRenderer { + float* buffer; + size_t offset; + size_t capacity; + + bool overflow = false; + + const Chunk* chunk = nullptr; + VoxelsVolume* voxelsBuffer; + + void vertex(glm::vec3 coord, float u, float v, glm::vec4 light); + + void face(glm::vec3 coord, float w, float h, + const glm::vec3 axisX, + const glm::vec3 axisY, + const UVRegion& region, + const glm::vec4 lights[4], + const glm::vec4 tint); + + void face(glm::vec3 coord, float w, float h, + const glm::vec3 axisX, + const glm::vec3 axisY, + const UVRegion& region, + const glm::vec4 lights[4], + const glm::vec4 tint, + bool rotated); + + void face(glm::vec3 coord, float w, float h, + const glm::vec3 axisX, + const glm::vec3 axisY, + const UVRegion& region, + const glm::vec4 lights[4]) { + face(coord, w, h, axisX, axisY, region, lights, glm::vec4(1.0f)); + } + + void cube(glm::vec3 coord, glm::vec3 size, const UVRegion faces[6]); + void blockCube(int x, int y, int z, glm::vec3 size, const UVRegion faces[6], ubyte group); + void blockCubeShaded(int x, int y, int z, glm::vec3 size, const UVRegion faces[6], const Block* block, ubyte states); + void blockXSprite(int x, int y, int z, glm::vec3 size, const UVRegion face1, const UVRegion face2, float spread); + + bool isOpenForLight(int x, int y, int z) const; + bool isOpen(int x, int y, int z, ubyte group) const; + + glm::vec4 pickLight(int x, int y, int z) const; + glm::vec4 pickSoftLight(int x, int y, int z, glm::ivec3 right, glm::ivec3 up) const; + void render(const voxel* voxels, int atlas_size); +public: + BlocksRenderer(size_t capacity); + virtual ~BlocksRenderer(); + + Mesh* render(const Chunk* chunk, int atlas_size, const ChunksStorage* chunks); + VoxelsVolume* getVoxelsBuffer() const; +}; + +#endif // GRAPHICS_BLOCKS_RENDERER_H \ No newline at end of file diff --git a/src/graphics/ChunksRenderer.cpp b/src/graphics/ChunksRenderer.cpp new file mode 100644 index 000000000..a74550c83 --- /dev/null +++ b/src/graphics/ChunksRenderer.cpp @@ -0,0 +1,52 @@ +#include "ChunksRenderer.h" + +#include "Mesh.h" +#include "BlocksRenderer.h" +#include "../voxels/Chunk.h" +#include "../world/Level.h" + +#include +#include + +using glm::ivec2; +using std::shared_ptr; + +ChunksRenderer::ChunksRenderer(Level* level) : level(level) { + const int MAX_FULL_CUBES = 3000; + renderer = new BlocksRenderer(9 * 6 * 6 * MAX_FULL_CUBES); +} + +ChunksRenderer::~ChunksRenderer() { + delete renderer; +} + +shared_ptr ChunksRenderer::render(Chunk* chunk) { + chunk->setModified(false); + Mesh* mesh = renderer->render(chunk, 16, level->chunksStorage); + auto sptr = shared_ptr(mesh); + meshes[ivec2(chunk->x, chunk->z)] = sptr; + return sptr; +} + +void ChunksRenderer::unload(Chunk* chunk) { + auto found = meshes.find(ivec2(chunk->x, chunk->z)); + if (found != meshes.end()) { + meshes.erase(found); + } +} + +shared_ptr ChunksRenderer::getOrRender(Chunk* chunk) { + auto found = meshes.find(ivec2(chunk->x, chunk->z)); + if (found != meshes.end() && !chunk->isModified()){ + return found->second; + } + return render(chunk); +} + +shared_ptr ChunksRenderer::get(Chunk* chunk) { + auto found = meshes.find(ivec2(chunk->x, chunk->z)); + if (found != meshes.end()) { + return found->second; + } + return nullptr; +} diff --git a/src/graphics/ChunksRenderer.h b/src/graphics/ChunksRenderer.h new file mode 100644 index 000000000..7f066263d --- /dev/null +++ b/src/graphics/ChunksRenderer.h @@ -0,0 +1,31 @@ +#ifndef SRC_GRAPHICS_CHUNKSRENDERER_H_ +#define SRC_GRAPHICS_CHUNKSRENDERER_H_ + +#include +#include +#include +#include "../voxels/Block.h" +#include "../voxels/ChunksStorage.h" + +class Mesh; +class Chunk; +class Level; +class BlocksRenderer; + +class ChunksRenderer { + BlocksRenderer* renderer; + Level* level; + std::unordered_map> meshes; +public: + ChunksRenderer(Level* level); + virtual ~ChunksRenderer(); + + std::shared_ptr render(Chunk* chunk); + void unload(Chunk* chunk); + + std::shared_ptr getOrRender(Chunk* chunk); + std::shared_ptr get(Chunk* chunk); + +}; + +#endif // SRC_GRAPHICS_CHUNKSRENDERER_H_ \ No newline at end of file diff --git a/src/graphics/LineBatch.cpp b/src/graphics/LineBatch.cpp index ca37f26e3..0d8f6216b 100644 --- a/src/graphics/LineBatch.cpp +++ b/src/graphics/LineBatch.cpp @@ -13,7 +13,7 @@ #define LB_VERTEX_SIZE (3+4) LineBatch::LineBatch(size_t capacity) : capacity(capacity) { - int attrs[] = {3,4, 0}; + const vattr attrs[] = { {3},{4}, {0} }; buffer = new float[capacity * LB_VERTEX_SIZE * 2]; mesh = new Mesh(buffer, 0, attrs); index = 0; diff --git a/src/graphics/Mesh.cpp b/src/graphics/Mesh.cpp index ef99560fa..c89cf5f00 100644 --- a/src/graphics/Mesh.cpp +++ b/src/graphics/Mesh.cpp @@ -1,10 +1,13 @@ #include "Mesh.h" #include -Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(vertices){ +int Mesh::meshesCount = 0; + +Mesh::Mesh(const float* buffer, size_t vertices, const vattr* attrs) : vertices(vertices){ + meshesCount++; vertexSize = 0; - for (int i = 0; attrs[i]; i++){ - vertexSize += attrs[i]; + for (int i = 0; attrs[i].size; i++){ + vertexSize += attrs[i].size; } glGenVertexArrays(1, &vao); @@ -21,8 +24,8 @@ Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(ve // attributes int offset = 0; - for (int i = 0; attrs[i]; i++){ - int size = attrs[i]; + for (int i = 0; attrs[i].size; i++){ + int size = attrs[i].size; glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float))); glEnableVertexAttribArray(i); offset += size; @@ -32,6 +35,7 @@ Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(ve } Mesh::~Mesh(){ + meshesCount--; glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); } @@ -48,3 +52,7 @@ void Mesh::draw(unsigned int primitive){ glDrawArrays(primitive, 0, vertices); glBindVertexArray(0); } + +void Mesh::draw() { + draw(GL_TRIANGLES); +} \ No newline at end of file diff --git a/src/graphics/Mesh.h b/src/graphics/Mesh.h index 12c74fc0d..58839ba2f 100644 --- a/src/graphics/Mesh.h +++ b/src/graphics/Mesh.h @@ -2,6 +2,11 @@ #define GRAPHICS_MESH_H_ #include +#include "../typedefs.h" + +struct vattr { + ubyte size; +}; class Mesh { unsigned int vao; @@ -9,11 +14,14 @@ class Mesh { size_t vertices; size_t vertexSize; public: - Mesh(const float* buffer, size_t vertices, const int* attrs); + Mesh(const float* buffer, size_t vertices, const vattr* attrs); ~Mesh(); void reload(const float* buffer, size_t vertices); void draw(unsigned int primitive); + void draw(); + + static int meshesCount; }; #endif /* GRAPHICS_MESH_H_ */ diff --git a/src/graphics/VoxelRenderer.cpp b/src/graphics/VoxelRenderer.cpp deleted file mode 100644 index 689156f2c..000000000 --- a/src/graphics/VoxelRenderer.cpp +++ /dev/null @@ -1,640 +0,0 @@ -#include "VoxelRenderer.h" - -#include -#include -#include "Mesh.h" -#include "../voxels/Chunk.h" -#include "../voxels/voxel.h" -#include "../voxels/Block.h" -#include "../lighting/Lightmap.h" - -#define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A))) -#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) -#define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) -#define IS_CHUNK(X,Y,Z) (GET_CHUNK(X,Y,Z) != nullptr) -#define GET_CHUNK(X,Y,Z) (chunks[(CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1]) - -#define LIGHT(X,Y,Z, CHANNEL) (IS_CHUNK(X,Y,Z) ? GET_CHUNK(X,Y,Z)->lightmap->get(LOCAL(X, CHUNK_W), LOCAL(Y, CHUNK_H), LOCAL(Z, CHUNK_D), (CHANNEL)) : 0) -#define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)]) -#define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP)) - -#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer.push_back(X);\ - buffer.push_back(Y);\ - buffer.push_back(Z);\ - buffer.push_back(U);\ - buffer.push_back(V);\ - buffer.push_back(R);\ - buffer.push_back(G);\ - buffer.push_back(B);\ - buffer.push_back(S);\ - INDEX += CHUNK_VERTEX_SIZE; - - -#define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\ - float v1 = 1-((1 + (INDEX) / 16) * uvsize);\ - float u2 = u1 + uvsize;\ - float v2 = v1 + uvsize; - -int chunk_attrs[] = {3,2,4, 0}; - -VoxelRenderer::VoxelRenderer() { -} - -VoxelRenderer::~VoxelRenderer(){ -} - -inline void _renderBlock(std::vector& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ - float l; - float uvsize = 1.0f/16.0f; - - Block* block = Block::blocks[vox.id]; - unsigned char group = block->drawGroup; - int textureCopyFaces[6]; - int rot = 0; - - for (int i=0; i<6; i++){ - textureCopyFaces[i] = block->textureFaces[i]; - } - - if (block->rotatable){ - if (vox.states == 0x31){ - rot = 1; - textureCopyFaces[0] = block->textureFaces[2]; - textureCopyFaces[1] = block->textureFaces[3]; - textureCopyFaces[2] = block->textureFaces[0]; - textureCopyFaces[3] = block->textureFaces[1]; - } else if (vox.states == 0x32){ - rot = 2; - } else if (vox.states == 0x33){ - rot = 3; - textureCopyFaces[2] = block->textureFaces[4]; - textureCopyFaces[3] = block->textureFaces[5]; - textureCopyFaces[4] = block->textureFaces[2]; - textureCopyFaces[5] = block->textureFaces[3]; - } - } - - if (!IS_BLOCKED(x,y+1,z,group)){ - l = 1.0f; - - SETUP_UV(textureCopyFaces[3]); - - 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; - float lr2 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 75.0f; - float lr3 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 75.0f; - - float lg0 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 75.0f; - float lg1 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 75.0f; - float lg2 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 75.0f; - float lg3 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 75.0f; - - float lb0 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 75.0f; - float lb1 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 75.0f; - float lb2 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 75.0f; - float lb3 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 75.0f; - - float ls0 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 75.0f; - float ls1 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 75.0f; - float ls2 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 75.0f; - float ls3 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3); - } else if (rot == 1){ - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v1, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr3,lg3,lb3,ls3); - } else if (rot == 3){ - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3); - } - } - if (!IS_BLOCKED(x,y-1,z,group)){ - l = 0.75f; - - SETUP_UV(textureCopyFaces[2]); - - 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; - float lr2 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 75.0f; - float lr3 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 75.0f; - - float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 75.0f; - float lg1 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 75.0f; - float lg2 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 75.0f; - float lg3 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 75.0f; - - float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 75.0f; - float lb1 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 75.0f; - float lb2 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 75.0f; - float lb3 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 75.0f; - - float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 75.0f; - float ls1 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 75.0f; - float ls2 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 75.0f; - float ls3 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } else if (rot == 1){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v2, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v2, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, lr1,lg1,lb1,ls1); - } else if (rot == 3){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } - } - - if (!IS_BLOCKED(x+1,y,z,group)){ - l = 0.95f; - - SETUP_UV(textureCopyFaces[1]); - - 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; - float lr2 = (LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y+1,z,0)) / 75.0f; - float lr3 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y-1,z,0)) / 75.0f; - - float lg0 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y-1,z,1)) / 75.0f; - float lg1 = (LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y+1,z,1)) / 75.0f; - float lg2 = (LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y+1,z,1)) / 75.0f; - float lg3 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y-1,z,1)) / 75.0f; - - float lb0 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y-1,z,2)) / 75.0f; - float lb1 = (LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y+1,z,2)) / 75.0f; - float lb2 = (LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y+1,z,2)) / 75.0f; - float lb3 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y-1,z,2)) / 75.0f; - - float ls0 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y-1,z,3)) / 75.0f; - float ls1 = (LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y+1,z,3)) / 75.0f; - float ls2 = (LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y+1,z,3)) / 75.0f; - float ls3 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y-1,z,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, lr3,lg3,lb3,ls3); - } else if (rot == 1){ - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr3,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr1,lg3,lb3,ls3); - } else if (rot == 3){ - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v2, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v1, lr2,lg2,lb2,ls2); - - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v2, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v1, lr3,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr1,lg3,lb3,ls3); - } - } - if (!IS_BLOCKED(x-1,y,z,group)){ - l = 0.85f; - - SETUP_UV(textureCopyFaces[0]); - - 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; - float lr2 = (LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y+1,z,0)) / 75.0f; - float lr3 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y-1,z,0)) / 75.0f; - - float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y-1,z,1)) / 75.0f; - float lg1 = (LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y+1,z,1)) / 75.0f; - float lg2 = (LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y+1,z,1)) / 75.0f; - float lg3 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y-1,z,1)) / 75.0f; - - float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y-1,z,2)) / 75.0f; - float lb1 = (LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y+1,z,2)) / 75.0f; - float lb2 = (LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y+1,z,2)) / 75.0f; - float lb3 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y-1,z,2)) / 75.0f; - - float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y-1,z,3)) / 75.0f; - float ls1 = (LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y+1,z,3)) / 75.0f; - float ls2 = (LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y+1,z,3)) / 75.0f; - float ls3 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y-1,z,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } else if (rot == 1){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } else if (rot == 3){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, lr3,lg3,lb3,ls3); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } - } - - if (!IS_BLOCKED(x,y,z+1,group)){ - l = 0.9f; - - SETUP_UV(textureCopyFaces[5]); - - 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; - float lr2 = l*(LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 75.0f; - float lr3 = l*(LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 75.0f; - - float lg0 = l*(LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 75.0f; - float lg1 = l*(LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 75.0f; - float lg2 = l*(LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 75.0f; - float lg3 = l*(LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 75.0f; - - float lb0 = l*(LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 75.0f; - float lb1 = l*(LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 75.0f; - float lb2 = l*(LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 75.0f; - float lb3 = l*(LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 75.0f; - - float ls0 = l*(LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 75.0f; - float ls1 = l*(LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 75.0f; - float ls2 = l*(LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 75.0f; - float ls3 = l*(LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } else if (rot == 1){ - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v1, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v2, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } else if (rot == 3){ - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, lr3,lg3,lb3,ls3); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1); - } - } - if (!IS_BLOCKED(x,y,z-1,group)){ - l = 0.8f; - - SETUP_UV(textureCopyFaces[4]); - - 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; - float lr2 = l*(LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 75.0f; - float lr3 = l*(LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 75.0f; - - float lg0 = l*(LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 75.0f; - float lg1 = l*(LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 75.0f; - float lg2 = l*(LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 75.0f; - float lg3 = l*(LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 75.0f; - - float lb0 = l*(LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 75.0f; - float lb1 = l*(LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 75.0f; - float lb2 = l*(LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 75.0f; - float lb3 = l*(LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 75.0f; - - float ls0 = l*(LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 75.0f; - float ls1 = l*(LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 75.0f; - float ls2 = l*(LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 75.0f; - float ls3 = l*(LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 75.0f; - - if ((rot == 0) || (rot == 2)){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3); - } else if (rot == 1){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v1, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v2, lr3,lg3,lb3,ls3); - } else if (rot == 3){ - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, lr2,lg2,lb2,ls2); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, lr3,lg3,lb3,ls3); - } - } -} - -inline void _renderBlockShadeless(std::vector& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ - float uvsize = 1.0f/16.0f; - - Block* block = Block::blocks[vox.id]; - unsigned char group = block->drawGroup; - - if (!IS_BLOCKED(x,y+1,z,group)){ - SETUP_UV(block->textureFaces[3]); - - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, 1,1,1,0); - } - if (!IS_BLOCKED(x,y-1,z,group)){ - SETUP_UV(block->textureFaces[2]); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0); - } - - if (!IS_BLOCKED(x+1,y,z,group)){ - SETUP_UV(block->textureFaces[1]); - - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0); - } - if (!IS_BLOCKED(x-1,y,z,group)){ - SETUP_UV(block->textureFaces[0]); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0); - } - - if (!IS_BLOCKED(x,y,z+1,group)){ - SETUP_UV(block->textureFaces[5]); - - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0); - } - if (!IS_BLOCKED(x,y,z-1,group)){ - SETUP_UV(block->textureFaces[4]); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0); - - VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0); - VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0); - VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0); - } -} - - -inline void _renderXBlock(std::vector& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ - Block* block = Block::blocks[vox.id]; - - int rand = ((x * z + y) ^ (z * y - x)) * (z + y); - - float xs = (float)(char)rand / 512; - float zs = (float)(char)(rand >> 8) / 512; - - if (block->model != 2){ - return; - } - - float uvsize = 1.0f/16.0f; - - float lr = LIGHT(x,y,z, 0); - float lg = LIGHT(x,y,z, 1); - float lb = LIGHT(x,y,z, 2); - float ls = LIGHT(x,y,z, 3); - - float lr0 = (LIGHT(x,y-1,z,0) + lr*3) / 60.0f; - float lr1 = (LIGHT(x,y+1,z,0) + lr*3) / 60.0f; - - float lg0 = (LIGHT(x,y-1,z,1) + lg*3) / 60.0f; - float lg1 = (LIGHT(x,y+1,z,1) + lg*3) / 60.0f; - - float lb0 = (LIGHT(x,y-1,z,2) + lb*3) / 60.0f; - float lb1 = (LIGHT(x,y+1,z,2) + lb*3) / 60.0f; - - float ls0 = (LIGHT(x,y-1,z,3) + ls*3) / 60.0f; - float ls1 = (LIGHT(x,y+1,z,3) + ls*3) / 60.0f; - - {SETUP_UV(block->textureFaces[1]); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z-0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.3535f+xs, y+0.5f, z-0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.3535f+xs, y+0.5f, z+0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z-0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z+0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.3535f+xs, y-0.5f, z+0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0);} - - {SETUP_UV(block->textureFaces[0]); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z-0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z+0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.3535f+xs, y+0.5f, z-0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z-0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y-0.5f, z+0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z+0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1);} - - {SETUP_UV(block->textureFaces[5]); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z+0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z-0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x-0.3535f+xs, y+0.5f, z+0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z+0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y-0.5f, z-0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z-0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1);} - - {SETUP_UV(block->textureFaces[4]); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z+0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x-0.3535f+xs, y+0.5f, z+0.3535f+zs, u2,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.3535f+xs, y+0.5f, z-0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - - VERTEX(index, x-0.3535f+xs, y-0.5f, z+0.3535f+zs, u2,v1, lr0,lg0,lb0,ls0); - VERTEX(index, x+0.3535f+xs, y+0.5f, z-0.3535f+zs, u1,v2, lr1,lg1,lb1,ls1); - VERTEX(index, x+0.3535f+xs, y-0.5f, z-0.3535f+zs, u1,v1, lr0,lg0,lb0,ls0);} -} - -const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& size){ - buffer.clear(); - size_t index = 0; - for (int y = 0; y < CHUNK_H; y++){ - for (int z = 0; z < CHUNK_D; z++){ - for (int x = 0; x < CHUNK_W; x++){ - voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; - if (vox.id == 0) - continue; - if (vox.id == 9 || vox.id == 4 || vox.id == 12 || vox.id == 13) - continue; - Block* block = Block::blocks[vox.id]; - if (block->emission[0] || block->emission[1] || block->emission[2]){ - continue; - } - _renderBlock(buffer, x, y, z, chunks, vox, 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; - Block* block = Block::blocks[vox.id]; - if (block->emission[0] || block->emission[1] || block->emission[2]){ - _renderBlockShadeless(buffer, x, y, z, chunks, vox, 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); - } - } - } - - 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 (Block::blocks[vox.id]->model != BLOCK_MODEL_X_SPRITE) - continue; - _renderXBlock(buffer, x, y, z, chunks, vox, 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 != 4) - continue; - _renderBlock(buffer, x, y, z, chunks, vox, index); - } - } - } - size = buffer.size(); - return &buffer[0]; -} diff --git a/src/graphics/VoxelRenderer.h b/src/graphics/VoxelRenderer.h deleted file mode 100644 index 3e1d545c7..000000000 --- a/src/graphics/VoxelRenderer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef GRAPHICS_VOXELRENDERER_H_ -#define GRAPHICS_VOXELRENDERER_H_ - -#include -#include - -class Mesh; -class Chunk; - -#define CHUNK_VERTEX_SIZE (3 + 2 + 4) - -class VoxelRenderer { -public: - std::vector buffer; - unsigned char lights[27 * 4]; - VoxelRenderer(); - ~VoxelRenderer(); - - const float* render(Chunk* chunk, const Chunk** chunks, size_t& size); -}; - -#endif /* GRAPHICS_VOXELRENDERER_H_ */ diff --git a/src/hud_render.cpp b/src/hud_render.cpp index 9e028b035..48b22083e 100644 --- a/src/hud_render.cpp +++ b/src/hud_render.cpp @@ -1,5 +1,6 @@ #include "hud_render.h" +#include #include #include @@ -20,19 +21,6 @@ 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; @@ -63,6 +51,11 @@ void HudRenderer::drawDebug(Level* level, Assets* assets, int fps, bool occlusio 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); + + std::wstringstream stream; + stream << std::hex << player->selectedVoxel.states; + font->draw(batch, L"block-selected: "+std::to_wstring(player->selectedVoxel.id)+L" "+stream.str(), 16, 78, STYLE_OUTLINE); + font->draw(batch, L"meshes: " + std::to_wstring(Mesh::meshesCount), 16, 102, STYLE_OUTLINE); // batch->render(); } diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index 5a036d76e..f4d884e82 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -6,8 +6,11 @@ #include "../voxels/voxel.h" #include "../voxels/Block.h" +#include #include +using std::shared_ptr; + Lighting::Lighting(Chunks* chunks){ this->chunks = chunks; solverR = new LightSolver(chunks, 0); @@ -25,7 +28,7 @@ Lighting::~Lighting(){ void Lighting::clear(){ for (unsigned int index = 0; index < chunks->volume; index++){ - Chunk* chunk = chunks->chunks[index]; + shared_ptr chunk = chunks->chunks[index]; if (chunk == nullptr) continue; Lightmap* lightmap = chunk->lightmap; diff --git a/src/lighting/Lightmap.h b/src/lighting/Lightmap.h index c0ca007af..f8a329dcc 100644 --- a/src/lighting/Lightmap.h +++ b/src/lighting/Lightmap.h @@ -1,11 +1,13 @@ #ifndef LIGHTING_LIGHTMAP_H_ #define LIGHTING_LIGHTMAP_H_ +#include "../constants.h" #include "../voxels/Chunk.h" +// Lichtkarte class Lightmap { public: - unsigned short* map; + light_t* map; int highestPoint = 0; Lightmap(); ~Lightmap(); @@ -60,6 +62,18 @@ class Lightmap { const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x; map[index] = (map[index] & (0xFFFF & (~(0xF << (channel*4))))) | (value << (channel << 2)); } + + inline const light_t* getLights() const { + return map; + } + + inline light_t* getLightsWriteable() { + return map; + } + + static inline light_t extract(light_t light, ubyte channel) { + return (light >> (channel << 2)) & 0xF; + } }; #endif /* LIGHTING_LIGHTMAP_H_ */ diff --git a/src/objects/Player.h b/src/objects/Player.h index ac340c47e..3818bd54d 100644 --- a/src/objects/Player.h +++ b/src/objects/Player.h @@ -3,6 +3,8 @@ #include +#include "../voxels/voxel.h" + class Camera; class Hitbox; class PhysicsSolver; @@ -21,6 +23,7 @@ class Player { float cameraShaking = 0.0f; float cameraShakingTimer = 0.0f; glm::vec3 interpVel {0.0f, 0.0f, 0.0f}; + voxel selectedVoxel {0, 0}; Player(glm::vec3 position, float speed, Camera* camera); ~Player(); }; diff --git a/src/physics/PhysicsSolver.h b/src/physics/PhysicsSolver.h index c3c9be83d..2d3d88fdf 100644 --- a/src/physics/PhysicsSolver.h +++ b/src/physics/PhysicsSolver.h @@ -5,15 +5,13 @@ #include #include -using namespace glm; - class Hitbox; class Chunks; class PhysicsSolver { - vec3 gravity; + glm::vec3 gravity; public: - PhysicsSolver(vec3 gravity); + PhysicsSolver(glm::vec3 gravity); void step(Chunks* chunks, Hitbox* hitbox, float delta, @@ -21,7 +19,7 @@ class PhysicsSolver { bool shifting, float gravityScale, bool collisions); - void colisionCalc(Chunks* chunks, Hitbox* hitbox, vec3* vel, vec3* pos, vec3 half); + void colisionCalc(Chunks* chunks, Hitbox* hitbox, glm::vec3* vel, glm::vec3* pos, glm::vec3 half); bool isBlockInside(int x, int y, int z, Hitbox* hitbox); }; diff --git a/src/player_control.cpp b/src/player_control.cpp index 9bdd68299..dc4cea9b7 100644 --- a/src/player_control.cpp +++ b/src/player_control.cpp @@ -183,6 +183,7 @@ void PlayerController::update_interaction(){ vec3 iend; voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend); if (vox != nullptr){ + player->selectedVoxel = *vox; selectedBlockId = vox->id; selectedBlockPosition = iend; int x = (int)iend.x; diff --git a/src/typedefs.h b/src/typedefs.h index 52b4123c4..513bf940d 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -2,3 +2,6 @@ typedef unsigned int uint; typedef unsigned char ubyte; + +typedef uint8_t blockid_t; +typedef uint16_t light_t; diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index 635ebd224..c63b511df 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -17,8 +18,6 @@ #include #include -using namespace glm; - #include "window/Window.h" #include "window/Events.h" #include "window/Camera.h" @@ -26,7 +25,7 @@ using namespace glm; #include "voxels/Chunk.h" #include "voxels/Chunks.h" #include "voxels/ChunksController.h" -#include "voxels/ChunksLoader.h" +#include "voxels/ChunksStorage.h" #include "objects/Player.h" #include "world/Level.h" #include "world/World.h" @@ -36,14 +35,19 @@ using namespace glm; #include "world_render.h" #include "hud_render.h" +using std::shared_ptr; + class initialize_error : public std::runtime_error { +public: initialize_error(const std::string& message) : std::runtime_error(message) {} }; + struct EngineSettings { int displayWidth; int displayHeight; + int displaySamples; const char* title; }; @@ -66,8 +70,7 @@ class Engine { }; Engine::Engine(const EngineSettings& settings) { - Window::initialize(settings.displayWidth, settings.displayHeight, settings.title); - Events::initialize(); + Window::initialize(settings.displayWidth, settings.displayHeight, settings.title, settings.displaySamples); assets = new Assets(); std::cout << "-- loading assets" << std::endl; @@ -78,7 +81,7 @@ Engine::Engine(const EngineSettings& settings) { if (!loader.loadNext()) { delete assets; Window::terminate(); - throw std::runtime_error("could not to initialize assets"); + throw initialize_error("could not to initialize assets"); } } std::cout << "-- loading world" << std::endl; @@ -115,7 +118,7 @@ void Engine::updateHotkeys() { } if (Events::jpressed(GLFW_KEY_F5)) { for (unsigned i = 0; i < level->chunks->volume; i++) { - Chunk* chunk = level->chunks->chunks[i]; + shared_ptr chunk = level->chunks->chunks[i]; if (chunk != nullptr && chunk->isReady()) { chunk->setModified(true); } @@ -137,15 +140,7 @@ void Engine::mainloop() { updateHotkeys(); level->update(delta, Events::_cursor_locked); - int freeLoaders = level->chunksController->countFreeLoaders(); - for (int i = 0; i < freeLoaders; i++) - level->chunksController->_buildMeshes(); - 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); + level->chunksController->loadVisible(world->wfile); worldRenderer.draw(camera, occlusion); hud.draw(level, assets); @@ -176,15 +171,13 @@ Engine::~Engine() { int main() { setup_definitions(); - try { - Engine engine(EngineSettings{ 1280, 720, "VoxelEngine-Cpp v13" }); + Engine engine(EngineSettings{ 1280, 720, 1, "VoxelEngine-Cpp v13" }); engine.mainloop(); } catch (const initialize_error& err) { std::cerr << "could not to initialize engine" << std::endl; std::cerr << err.what() << std::endl; } - return 0; } diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 2b6c4832a..5ca74b696 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -4,6 +4,13 @@ #define BLOCK_MODEL_CUBE 1 #define BLOCK_MODEL_X_SPRITE 2 +#define FACE_MX 0 +#define FACE_PX 1 +#define FACE_MY 2 +#define FACE_PY 3 +#define FACE_MZ 4 +#define FACE_PZ 5 + class Block { public: static Block* blocks[256]; diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index 52debffea..6fecb180a 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -36,11 +36,3 @@ Chunk* Chunk::clone() const { return other; } -void Chunk::incref(){ - references++; -} - -void Chunk::decref(){ - if (--references <= 0) - delete this; -} diff --git a/src/voxels/Chunk.h b/src/voxels/Chunk.h index 18d6f28bb..329dbed88 100644 --- a/src/voxels/Chunk.h +++ b/src/voxels/Chunk.h @@ -2,11 +2,7 @@ #define VOXELS_CHUNK_H_ #include - -#define CHUNK_W 16 -#define CHUNK_H 256 -#define CHUNK_D 16 -#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D * 2) +#include "../constants.h" #define CHUNK_MODIFIED 0x1 #define CHUNK_READY 0x2 @@ -14,7 +10,7 @@ #define CHUNK_LIGHTED 0x8 #define CHUNK_UNSAVED 0x10 -class voxel; +struct voxel; class Lightmap; struct RenderData { @@ -33,7 +29,6 @@ class Chunk { Lightmap* lightmap; int flags = 0; int surrounding = 0; - int references = 1; RenderData renderData; Chunk(int x, int z); @@ -42,8 +37,6 @@ class Chunk { bool isEmpty(); Chunk* clone() const; - void incref(); - void decref(); // flags getters/setters below diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 4dd538cfc..3a5d89611 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -7,29 +7,28 @@ #include "../files/WorldFiles.h" #include "../graphics/Mesh.h" +#include "../voxmaths.h" #include #include +using glm::vec3; +using std::shared_ptr; + 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]; - - meshes = new Mesh*[volume]; - meshesSecond = new Mesh*[volume]; + chunks = new shared_ptr[volume]; + chunksSecond = new shared_ptr[volume]; for (size_t i = 0; i < volume; i++){ chunks[i] = nullptr; - meshes[i] = nullptr; } chunksCount = 0; } Chunks::~Chunks(){ for (size_t i = 0; i < volume; i++){ - if (chunks[i]) - chunks[i]->decref(); + chunks[i] = nullptr; } delete[] chunks; } @@ -45,7 +44,7 @@ voxel* Chunks::get(int x, int y, int z){ if (z < 0) cz--; if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return nullptr; - Chunk* chunk = chunks[(cy * d + cz) * w + cx]; + shared_ptr chunk = chunks[(cy * d + cz) * w + cx]; if (chunk == nullptr) return nullptr; int lx = x - cx * CHUNK_W; @@ -61,18 +60,15 @@ bool Chunks::isObstacle(int x, int y, int z){ return Block::blocks[v->id]->obstacle; } -unsigned char Chunks::getLight(int x, int y, int z, int channel){ +ubyte Chunks::getLight(int x, int y, int z, int channel){ x -= ox * CHUNK_W; z -= oz * CHUNK_D; - int cx = x / CHUNK_W; - int cy = y / CHUNK_H; - int cz = z / CHUNK_D; - if (x < 0) cx--; - if (y < 0) cy--; - if (z < 0) cz--; + int cx = floordiv(x, CHUNK_W); + int cy = floordiv(y, CHUNK_H); + int cz = floordiv(z, CHUNK_D); if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return 0; - Chunk* chunk = chunks[(cy * d + cz) * w + cx]; + shared_ptr chunk = chunks[(cy * d + cz) * w + cx]; if (chunk == nullptr) return 0; int lx = x - cx * CHUNK_W; @@ -81,18 +77,15 @@ unsigned char Chunks::getLight(int x, int y, int z, int channel){ return chunk->lightmap->get(lx,ly,lz, channel); } -unsigned short Chunks::getLight(int x, int y, int z){ +light_t Chunks::getLight(int x, int y, int z){ x -= ox * CHUNK_W; z -= oz * CHUNK_D; - int cx = x / CHUNK_W; - int cy = y / CHUNK_H; - int cz = z / CHUNK_D; - if (x < 0) cx--; - if (y < 0) cy--; - if (z < 0) cz--; + int cx = floordiv(x, CHUNK_W); + int cy = floordiv(y, CHUNK_H); + int cz = floordiv(z, CHUNK_D); if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return 0; - Chunk* chunk = chunks[(cy * d + cz) * w + cx]; + shared_ptr chunk = chunks[(cy * d + cz) * w + cx]; if (chunk == nullptr) return 0; int lx = x - cx * CHUNK_W; @@ -112,7 +105,7 @@ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ if (z < 0) cz--; if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return nullptr; - return chunks[(cy * d + cz) * w + cx]; + return chunks[(cy * d + cz) * w + cx].get(); } Chunk* Chunks::getChunk(int x, int z){ @@ -120,7 +113,7 @@ Chunk* Chunks::getChunk(int x, int z){ z -= oz; if (x < 0 || z < 0 || x >= w || z >= d) return nullptr; - return chunks[z * w + x]; + return chunks[z * w + x].get(); } void Chunks::set(int x, int y, int z, int id, uint8_t states){ @@ -134,7 +127,7 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){ if (z < 0) cz--; if (cx < 0 || cz < 0 || cx >= w || cz >= d) return; - Chunk* chunk = chunks[cz * w + cx]; + Chunk* chunk = chunks[cz * w + cx].get(); if (chunk == nullptr) return; int lx = x - cx * CHUNK_W; @@ -169,7 +162,7 @@ voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, v float stepy = (dy > 0.0f) ? 1.0f : -1.0f; float stepz = (dz > 0.0f) ? 1.0f : -1.0f; - float infinity = std::numeric_limits::infinity(); + constexpr float infinity = std::numeric_limits::infinity(); float txDelta = (dx == 0.0f) ? infinity : abs(1.0f / dx); float tyDelta = (dy == 0.0f) ? infinity : abs(1.0f / dy); @@ -256,35 +249,26 @@ void Chunks::setCenter(WorldFiles* worldFiles, int x, int z) { void Chunks::translate(WorldFiles* worldFiles, int dx, int dz){ for (unsigned int i = 0; i < volume; i++){ chunksSecond[i] = nullptr; - meshesSecond[i] = nullptr; } for (int z = 0; z < d; z++){ for (int x = 0; x < w; x++){ - Chunk* chunk = chunks[z * w + x]; + shared_ptr 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; + worldFiles->put((const ubyte*)chunk->voxels, chunk->x, chunk->z); chunksCount--; continue; } - meshesSecond[nz * w + nx] = mesh; chunksSecond[nz * w + nx] = chunk; } } - Chunk** ctemp = chunks; + shared_ptr* ctemp = chunks; chunks = chunksSecond; chunksSecond = ctemp; - Mesh** mtemp = meshes; - meshes = meshesSecond; - meshesSecond = mtemp; - ox += dx; oz += dz; } @@ -294,7 +278,7 @@ void Chunks::_setOffset(int x, int z){ oz = z; } -bool Chunks::putChunk(Chunk* chunk) { +bool Chunks::putChunk(shared_ptr chunk) { int x = chunk->x; int z = chunk->z; x -= ox; @@ -306,14 +290,9 @@ bool Chunks::putChunk(Chunk* chunk) { return true; } -void Chunks::clear(bool freeMemory){ +void Chunks::clear(){ for (size_t i = 0; i < volume; i++){ - if (freeMemory){ - chunks[i]->decref(); - delete meshes[i]; - } chunks[i] = nullptr; - meshes[i] = nullptr; } chunksCount = 0; } diff --git a/src/voxels/Chunks.h b/src/voxels/Chunks.h index b8268a774..509b7671f 100644 --- a/src/voxels/Chunks.h +++ b/src/voxels/Chunks.h @@ -2,11 +2,10 @@ #define VOXELS_CHUNKS_H_ #include +#include #include +#include "../typedefs.h" -using namespace glm; - -class Mesh; class VoxelRenderer; class Chunk; @@ -15,10 +14,8 @@ class WorldFiles; class Chunks { public: - Chunk** chunks; - Chunk** chunksSecond; - Mesh** meshes; - Mesh** meshesSecond; + std::shared_ptr* chunks; + std::shared_ptr* chunksSecond; size_t volume; size_t chunksCount; int w,d; @@ -27,15 +24,15 @@ class Chunks { Chunks(int w, int d, int ox, int oz); ~Chunks(); - bool putChunk(Chunk* chunk); + bool putChunk(std::shared_ptr chunk); 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); - unsigned char getLight(int x, int y, int z, int channel); + light_t getLight(int x, int y, int z); + ubyte getLight(int x, int y, int z, int channel); void set(int x, int y, int z, int id, uint8_t states); - voxel* rayCast(vec3 start, vec3 dir, float maxLength, vec3& end, vec3& norm, vec3& iend); + voxel* rayCast(glm::vec3 start, glm::vec3 dir, float maxLength, glm::vec3& end, glm::vec3& norm, glm::vec3& iend); bool isObstacle(int x, int y, int z); @@ -45,7 +42,7 @@ class Chunks { void setCenter(WorldFiles* worldFiles, int x, int z); void translate(WorldFiles* worldFiles, int x, int z); - void clear(bool freeMemory); + void clear(); }; #endif /* VOXELS_CHUNKS_H_ */ diff --git a/src/voxels/ChunksController.cpp b/src/voxels/ChunksController.cpp index e3fc3a712..c697d3c3b 100644 --- a/src/voxels/ChunksController.cpp +++ b/src/voxels/ChunksController.cpp @@ -1,14 +1,17 @@ #include "ChunksController.h" +#include "Block.h" #include "Chunk.h" #include "Chunks.h" +#include "ChunksStorage.h" #include "WorldGenerator.h" #include "../graphics/Mesh.h" -#include "../graphics/VoxelRenderer.h" #include "../lighting/Lighting.h" #include "../files/WorldFiles.h" -#include "ChunksLoader.h" +#include "../world/Level.h" +#include "../world/World.h" #include #include +#include #if defined(_WIN32) && defined(__MINGW32__) #define _WIN32_WINNT 0x0501 @@ -19,31 +22,13 @@ #define MIN_SURROUNDING 9 +using std::shared_ptr; -ChunksController::ChunksController(World* world, Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){ - loadersCount = std::thread::hardware_concurrency() * 2 - 1; - if (loadersCount <= 0) - loadersCount = 1; - loaders = new ChunksLoader*[loadersCount]; - for (int i = 0; i < loadersCount; i++){ - loaders[i] = new ChunksLoader(world); - } - std::cout << "created " << loadersCount << " loaders" << std::endl; -} -ChunksController::~ChunksController(){ - for (int i = 0; i < loadersCount; i++) - delete loaders[i]; - delete[] loaders; +ChunksController::ChunksController(Level* level, Chunks* chunks, Lighting* lighting) : level(level), chunks(chunks), lighting(lighting){ } -int ChunksController::countFreeLoaders(){ - int count = 0; - for (int i = 0; i < loadersCount; i++){ - if (!loaders[i]->isBusy()) - count++; - } - return count; +ChunksController::~ChunksController(){ } bool ChunksController::loadVisible(WorldFiles* worldFiles){ @@ -57,16 +42,22 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){ 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]; + shared_ptr 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++; + if (other != nullptr) surrounding++; } } chunk->surrounding = surrounding; + if (surrounding == MIN_SURROUNDING && !chunk->isLighted()) { + lighting->buildSkyLight(chunk->x, chunk->z); + lighting->onChunkLoaded(chunk->x, chunk->z); + chunk->setLighted(true); + return false; + } continue; } int lx = x - w / 2; @@ -81,200 +72,29 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){ } int index = nearZ * w + nearX; - Chunk* chunk = chunks->chunks[index]; - if (chunk != nullptr) - return false; - - ChunksLoader* freeLoader = getFreeLoader(); - if (freeLoader == nullptr) + shared_ptr chunk = chunks->chunks[index]; + if (chunk != nullptr) { return false; + } - chunk = new Chunk(nearX+ox, nearZ+oz); - if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels)) + chunk = shared_ptr(new Chunk(nearX+ox, nearZ+oz)); + level->chunksStorage->store(chunk); + if (worldFiles->getChunk(chunk->x, chunk->z, (ubyte*)chunk->voxels)) chunk->setLoaded(true); chunks->putChunk(chunk); - Chunk* closes[9]; - for (int i = 0; i < 9; i++) - closes[i] = nullptr; - for (size_t j = 0; j < chunks->volume; j++){ - Chunk* other = chunks->chunks[j]; - if (other == nullptr) - continue; - if (!other->isReady()) - continue; - - int ox = other->x - chunk->x; - int oz = other->z - chunk->z; - - if (abs(ox) > 1 || abs(oz) > 1) - continue; - - ox += 1; - oz += 1; - closes[oz * 3 + ox] = other; - } - freeLoader->load(chunk, (Chunk**)closes); - return true; -} - -ChunksLoader* ChunksController::getFreeLoader() { - ChunksLoader* freeLoader = nullptr; - for (int i = 0; i < loadersCount; i++){ - ChunksLoader* loader = loaders[i]; - if (loader->isBusy()){ - continue; - } - 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; + if (!chunk->isLoaded()) { + WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, level->world->seed); + chunk->setUnsaved(true); } - freeLoader->lights(chunk, (Chunk**)closes); -} - -bool ChunksController::_buildMeshes() { - 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 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; - 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 = nearZ * w + nearX; - Chunk* chunk = chunks->chunks[index]; - if (chunk == nullptr){ - return false; - } - Mesh* mesh = chunks->meshes[index]; - if (mesh == nullptr || chunk->isModified()){ - if (chunk->renderData.vertices != nullptr) { - return false; - } - Chunk* closes[9]; - if (chunk->isEmpty()){ - chunks->meshes[index] = nullptr; - return false; - } - - 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; - if ((!other->isReady() || !other->isLighted()) && other != chunk) - return false; - closes[oz * 3 + ox] = other; + for (size_t i = 0; i < CHUNK_VOL; i++) { + if (Block::blocks[chunk->voxels[i].id] == nullptr) { + std::cout << "corruped block detected at " << i << " of chunk " << chunk->x << "x" << chunk->z << std::endl; + chunk->voxels[i].id = 11; } - chunk->setModified(false); - chunk->renderData.vertices = (float*)1; - freeLoader->render(chunk, (Chunk**)closes); - - return true; } - return false; -} + lighting->prebuildSkyLight(chunk->x, chunk->z); + return true; +} \ No newline at end of file diff --git a/src/voxels/ChunksController.h b/src/voxels/ChunksController.h index 1363c7a1b..a38688861 100644 --- a/src/voxels/ChunksController.h +++ b/src/voxels/ChunksController.h @@ -1,7 +1,7 @@ #ifndef VOXELS_CHUNKSCONTROLLER_H_ #define VOXELS_CHUNKSCONTROLLER_H_ -class World; +class Level; class Chunks; class Lighting; class WorldFiles; @@ -10,19 +10,14 @@ class ChunksLoader; class ChunksController { private: + Level* level; Chunks* chunks; Lighting* lighting; - ChunksLoader** loaders; - int loadersCount; public: - ChunksController(World* world, Chunks* chunks, Lighting* lighting); + ChunksController(Level* level, Chunks* chunks, Lighting* lighting); ~ChunksController(); - ChunksLoader* getFreeLoader(); - int countFreeLoaders(); bool loadVisible(WorldFiles* worldFiles); - void calculateLights(); - bool _buildMeshes(); }; #endif /* VOXELS_CHUNKSCONTROLLER_H_ */ diff --git a/src/voxels/ChunksLoader.cpp b/src/voxels/ChunksLoader.cpp deleted file mode 100644 index f688a70af..000000000 --- a/src/voxels/ChunksLoader.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "ChunksLoader.h" -#include - -#include "Chunk.h" -#include "Chunks.h" -#include "Block.h" -#include "voxel.h" -#include "../world/World.h" -#include "WorldGenerator.h" -#include "../lighting/Lighting.h" -#include "../graphics/VoxelRenderer.h" - -#include - -#define SURROUNDINGS_C 9 - -void ChunksLoader::_thread(){ - Chunks chunks(3, 3, -1, -1); - Lighting lighting(&chunks); - VoxelRenderer renderer; - while (state != OFF){ - if (current == nullptr){ - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - continue; - } - Chunk* chunk = current; - 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); - } - } - - if (state == LOAD){ - chunks.putChunk(chunk); - 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++){ - if (Block::blocks[chunk->voxels[i].id] == nullptr){ - std::cout << "corruped block detected at " << i << " of chunk " << chunk->x << "x" << chunk->z << std::endl; - chunk->voxels[i].id = 11; - } - } - 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**)(surroundings.load()), size); - float* vertices = new float[size]; - for (size_t i = 0; i < size; i++) - vertices[i] = renderer.buffer[i]; - chunk->renderData.vertices = vertices; - chunk->renderData.size = size; - } - - chunks.clear(false); - for (int i = 0; i < SURROUNDINGS_C; i++){ - Chunk* other = surroundings[i]; - if (other) - other->decref(); - } - chunk->setReady(true); - current = nullptr; - chunk->decref(); - } -} - -void ChunksLoader::perform(Chunk* chunk, Chunk** surroundings_passed, LoaderMode mode){ - if (isBusy()){ - std::cerr << "performing while busy" << std::endl; - return; - } - chunk->incref(); - if (surroundings == nullptr){ - surroundings = new Chunk*[SURROUNDINGS_C]; - } - for (int i = 0; i < SURROUNDINGS_C; i++){ - Chunk* other = surroundings_passed[i]; - if (other == nullptr) - surroundings[i] = nullptr; - else { - other->incref(); - surroundings[i] = other; - } - } - current = chunk; - state = mode; -} - -void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){ - perform(chunk, closes_passed, LOAD); -} - -void ChunksLoader::lights(Chunk* chunk, Chunk** closes_passed){ - perform(chunk, closes_passed, LIGHTS); -} - -void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){ - perform(chunk, closes_passed, RENDER); -} diff --git a/src/voxels/ChunksLoader.h b/src/voxels/ChunksLoader.h deleted file mode 100644 index 27a656e93..000000000 --- a/src/voxels/ChunksLoader.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef VOXELS_CHUNKSLOADER_H_ -#define VOXELS_CHUNKSLOADER_H_ - -#if defined(_WIN32) && defined(__MINGW32__) -#define _WIN32_WINNT 0x0501 -#include -#else -#include -#endif // _WIN32 && __MINGW32__ - -#include - -class Chunk; -class World; - -enum LoaderMode { - OFF, IDLE, LOAD, LIGHTS, RENDER, -}; - -class ChunksLoader final { -private: - std::thread loaderThread; - void _thread(); - std::atomic current {nullptr}; - std::atomic surroundings {nullptr}; - std::atomic state {IDLE}; - World* world; - - void perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode); -public: - ChunksLoader(World* world) : loaderThread{}, world(world) { - loaderThread = std::thread{&ChunksLoader::_thread, this}; - } - ~ChunksLoader(){ - state = OFF; - loaderThread.join(); - } - - bool isBusy(){ - return current != nullptr; - } - - void load(Chunk* chunk, Chunk** closes_passed); - void lights(Chunk* chunk, Chunk** closes_passed); - void render(Chunk* chunk, Chunk** closes_passed); - - void stop(){ - state = OFF; - } -}; - -#endif /* VOXELS_CHUNKSLOADER_H_ */ diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp new file mode 100644 index 000000000..ec7f7e1bc --- /dev/null +++ b/src/voxels/ChunksStorage.cpp @@ -0,0 +1,93 @@ +#include "ChunksStorage.h" + +#include + +#include "VoxelsVolume.h" +#include "Chunk.h" +#include "../voxmaths.h" +#include "../lighting/Lightmap.h" + + +using glm::ivec2; +using std::shared_ptr; + +ChunksStorage::ChunksStorage() { +} + +ChunksStorage::~ChunksStorage() { +} + +void ChunksStorage::store(shared_ptr chunk) { + chunksMap[ivec2(chunk->x, chunk->z)] = chunk; +} + +shared_ptr ChunksStorage::get(int x, int z) const { + auto found = chunksMap.find(ivec2(x, z)); + if (found == chunksMap.end()) { + return nullptr; + } + return found->second; +} + +// some magic code +void ChunksStorage::getVoxels(VoxelsVolume* volume) const { + voxel* voxels = volume->getVoxels(); + light_t* lights = volume->getLights(); + int x = volume->getX(); + int y = volume->getY(); + int z = volume->getZ(); + + int w = volume->getW(); + int h = volume->getH(); + int d = volume->getD(); + + int scx = floordiv(x, CHUNK_W); + int scz = floordiv(z, CHUNK_D); + + int ecx = floordiv(x + w, CHUNK_W); + int ecz = floordiv(z + d, CHUNK_D); + + int cw = ecx - scx + 1; + int ch = ecz - scz + 1; + + // cw*ch chunks will be scanned + for (int cz = scz; cz < scz + ch; cz++) { + for (int cx = scx; cx < scx + cw; cx++) { + auto found = chunksMap.find(ivec2(cx, cz)); + if (found == chunksMap.end()) { + // no chunk loaded -> filling with BLOCK_VOID + for (int ly = y; ly < y + h; ly++) { + for (int lz = max(z, cz * CHUNK_D); + lz < min(z + d, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = max(x, cx * CHUNK_W); + lx < min(x + w, (cx + 1) * CHUNK_W); + lx++) { + voxels[vox_index(lx - x, ly - y, lz - z, w, d)].id = BLOCK_VOID; + lights[vox_index(lx - x, ly - y, lz - z, w, d)] = 0; + } + } + } + } + else { + const std::shared_ptr& chunk = found->second; + const voxel* cvoxels = chunk->voxels; + const light_t* clights = chunk->lightmap->getLights(); + for (int ly = y; ly < y + h; ly++) { + for (int lz = max(z, cz * CHUNK_D); + lz < min(z + d, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = max(x, cx * CHUNK_W); + lx < min(x + w, (cx + 1) * CHUNK_W); + lx++) { + voxels[vox_index(lx - x, ly - y, lz - z, w, d)] = + cvoxels[vox_index(lx - cx * CHUNK_W, ly, lz - cz * CHUNK_D, CHUNK_W, CHUNK_D)]; + lights[vox_index(lx - x, ly - y, lz - z, w, d)] = + clights[vox_index(lx - cx * CHUNK_W, ly, lz - cz * CHUNK_D, CHUNK_W, CHUNK_D)]; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/voxels/ChunksStorage.h b/src/voxels/ChunksStorage.h new file mode 100644 index 000000000..d15c99c4c --- /dev/null +++ b/src/voxels/ChunksStorage.h @@ -0,0 +1,29 @@ +#ifndef VOXELS_CHUNKSSTORAGE_H_ +#define VOXELS_CHUNKSSTORAGE_H_ + +#include +#include +#include "voxel.h" +#include "../typedefs.h" + +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/gtx/hash.hpp" + +class Chunk; +class VoxelsVolume; + +class ChunksStorage { + std::unordered_map> chunksMap; +public: + ChunksStorage(); + virtual ~ChunksStorage(); + + std::shared_ptr get(int x, int y) const; + void store(std::shared_ptr chunk); + void getVoxels(VoxelsVolume* volume) const; + + light_t getLight(int x, int y, int z, ubyte channel) const; +}; + + +#endif // VOXELS_CHUNKSSTORAGE_H_ \ No newline at end of file diff --git a/src/voxels/VoxelsVolume.cpp b/src/voxels/VoxelsVolume.cpp new file mode 100644 index 000000000..a616d873e --- /dev/null +++ b/src/voxels/VoxelsVolume.cpp @@ -0,0 +1,30 @@ +#include "VoxelsVolume.h" + +VoxelsVolume::VoxelsVolume(int x, int y, int z, int w, int h, int d) + : x(x), y(y), z(z), w(w), h(h), d(d) { + voxels = new voxel[w * h * d]; + for (int i = 0; i < w * h * d; i++) { + voxels[i].id = BLOCK_VOID; + } + lights = new light_t[w * h * d]; +} + +VoxelsVolume::VoxelsVolume(int w, int h, int d) + : x(0), y(0), z(0), w(w), h(h), d(d) { + voxels = new voxel[w * h * d]; + for (int i = 0; i < w * h * d; i++) { + voxels[i].id = BLOCK_VOID; + } + lights = new light_t[w * h * d]; +} + +VoxelsVolume::~VoxelsVolume() { + delete[] lights; + delete[] voxels; +} + +void VoxelsVolume::setPosition(int x, int y, int z) { + this->x = x; + this->y = y; + this->z = z; +} diff --git a/src/voxels/VoxelsVolume.h b/src/voxels/VoxelsVolume.h new file mode 100644 index 000000000..32f064b4f --- /dev/null +++ b/src/voxels/VoxelsVolume.h @@ -0,0 +1,67 @@ +#ifndef VOXELS_VOXELSVOLUME_H_ +#define VOXELS_VOXELSVOLUME_H_ + +#include "../typedefs.h" +#include "../constants.h" +#include "voxel.h" + +class VoxelsVolume { + int x, y, z; + int w, h, d; + voxel* voxels; + light_t* lights; +public: + VoxelsVolume(int w, int h, int d); + VoxelsVolume(int x, int y, int z, int w, int h, int d); + virtual ~VoxelsVolume(); + + void setPosition(int x, int y, int z); + + int getX() const { + return x; + } + + int getY() const { + return y; + } + + int getZ() const { + return z; + } + + int getW() const { + return w; + } + + int getH() const { + return h; + } + + int getD() const { + return d; + } + + voxel* getVoxels() const { + return voxels; + } + + light_t* getLights() const { + return lights; + } + + inline blockid_t pickBlockId(int bx, int by, int bz) const { + if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || bz >= z + d) { + return BLOCK_VOID; + } + return voxels[vox_index(bx - x, by - y, bz - z, w, d)].id; + } + + inline light_t pickLight(int bx, int by, int bz) const { + if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || bz >= z + d) { + return 0; + } + return lights[vox_index(bx - x, by - y, bz - z, w, d)]; + } +}; + +#endif // VOXELS_VOXELSVOLUME_H_ \ No newline at end of file diff --git a/src/voxels/voxel.h b/src/voxels/voxel.h index 15eae23ae..54faa86eb 100644 --- a/src/voxels/voxel.h +++ b/src/voxels/voxel.h @@ -1,10 +1,10 @@ #ifndef VOXELS_VOXEL_H_ #define VOXELS_VOXEL_H_ -#include +#include "../typedefs.h" struct voxel { - uint8_t id; + blockid_t id; uint8_t states; }; diff --git a/src/voxmaths.h b/src/voxmaths.h new file mode 100644 index 000000000..30476a156 --- /dev/null +++ b/src/voxmaths.h @@ -0,0 +1,43 @@ +#ifndef SRC_VOXNATHS_H_ +#define SRC_VOXNATHS_H_ + +#include "typedefs.h" + +inline int floordiv(int a, int b) { + if (a < 0 && a % b) { + return (a / b) - 1; + } + return a / b; +} + +inline int ceildiv(int a, int b) { + if (a > 0 && a % b) { + return a / b + 1; + } + return a / b; +} + +inline int max(int a, int b) { + return (a > b) ? a : b; +} + +inline int min(int a, int b) { + return (a < b) ? a : b; +} + +static unsigned int g_seed; + +inline void fast_srand(int seed) { + g_seed = seed; +} + +inline int fast_rand(void) { + g_seed = (214013 * g_seed + 2531011); + return (g_seed >> 16) & 0x7FFF; +} + +inline light_t light_pack(ubyte r, ubyte g, ubyte b, ubyte s) { + return r | (g << 4) | (b << 8) | (s << 12); +} + +#endif // SRC_VOXNATHS_H_ \ No newline at end of file diff --git a/src/window/Events.cpp b/src/window/Events.cpp index 58df902ca..4295d1844 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -13,60 +13,15 @@ float Events::y = 0.0f; bool Events::_cursor_locked = false; bool Events::_cursor_started = false; -#define _MOUSE_BUTTONS 1024 -void cursor_position_callback(GLFWwindow*, double xpos, double ypos){ - if (Events::_cursor_started){ - Events::deltaX += xpos-Events::x; - Events::deltaY += ypos-Events::y; - } - else { - Events::_cursor_started = true; - } - Events::x = xpos; - Events::y = ypos; -} - -void mouse_button_callback(GLFWwindow*, int button, int action, int){ - if (action == GLFW_PRESS){ - Events::_keys[_MOUSE_BUTTONS+button] = true; - Events::_frames[_MOUSE_BUTTONS+button] = Events::_current; - } - else if (action == GLFW_RELEASE){ - Events::_keys[_MOUSE_BUTTONS+button] = false; - Events::_frames[_MOUSE_BUTTONS+button] = Events::_current; - } -} - -void key_callback(GLFWwindow*, int key, int /*scancode*/, int action, int /*mode*/) { - if (action == GLFW_PRESS){ - Events::_keys[key] = true; - Events::_frames[key] = Events::_current; - } - else if (action == GLFW_RELEASE){ - Events::_keys[key] = false; - Events::_frames[key] = Events::_current; - } -} - -void window_size_callback(GLFWwindow*, int width, int height){ - glViewport(0,0, width, height); - Window::width = width; - Window::height = height; -} int Events::initialize(){ - GLFWwindow* window = Window::window; _keys = new bool[1032]; _frames = new uint[1032]; memset(_keys, false, 1032*sizeof(bool)); memset(_frames, 0, 1032*sizeof(uint)); - glfwSetKeyCallback(window, key_callback); - glfwSetMouseButtonCallback(window, mouse_button_callback); - glfwSetCursorPosCallback(window, cursor_position_callback); - glfwSetWindowSizeCallback(window, window_size_callback); return 0; } diff --git a/src/window/Events.h b/src/window/Events.h index d2a92c269..671bd63d1 100644 --- a/src/window/Events.h +++ b/src/window/Events.h @@ -30,4 +30,6 @@ class Events { static void toggleCursor(); }; +#define _MOUSE_BUTTONS 1024 + #endif /* WINDOW_EVENTS_H_ */ diff --git a/src/window/Window.cpp b/src/window/Window.cpp index 9a11b210d..3268b0dc5 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -1,5 +1,6 @@ #include #include "Window.h" +#include "Events.h" #include #include @@ -7,13 +8,53 @@ GLFWwindow* Window::window = nullptr; uint Window::width = 0; uint Window::height = 0; -int Window::initialize(uint width, uint height, const char* title){ +void cursor_position_callback(GLFWwindow*, double xpos, double ypos) { + if (Events::_cursor_started) { + Events::deltaX += xpos - Events::x; + Events::deltaY += ypos - Events::y; + } + else { + Events::_cursor_started = true; + } + Events::x = xpos; + Events::y = ypos; +} + +void mouse_button_callback(GLFWwindow*, int button, int action, int) { + if (action == GLFW_PRESS) { + Events::_keys[_MOUSE_BUTTONS + button] = true; + Events::_frames[_MOUSE_BUTTONS + button] = Events::_current; + } + else if (action == GLFW_RELEASE) { + Events::_keys[_MOUSE_BUTTONS + button] = false; + Events::_frames[_MOUSE_BUTTONS + button] = Events::_current; + } +} + +void key_callback(GLFWwindow*, int key, int /*scancode*/, int action, int /*mode*/) { + if (action == GLFW_PRESS) { + Events::_keys[key] = true; + Events::_frames[key] = Events::_current; + } + else if (action == GLFW_RELEASE) { + Events::_keys[key] = false; + Events::_frames[key] = Events::_current; + } +} + +void window_size_callback(GLFWwindow*, int width, int height) { + glViewport(0, 0, width, height); + Window::width = width; + Window::height = height; +} + +int Window::initialize(uint width, uint height, const char* title, int samples){ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); - glfwWindowHint(GLFW_SAMPLES, 16); + glfwWindowHint(GLFW_SAMPLES, samples); window = glfwCreateWindow(width, height, title, nullptr, nullptr); if (window == nullptr){ @@ -35,11 +76,16 @@ int Window::initialize(uint width, uint height, const char* title){ glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glEnable(GL_MULTISAMPLE); - // glDisable(GL_MULTISAMPLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Window::width = width; Window::height = height; + + Events::initialize(); + glfwSetKeyCallback(window, key_callback); + glfwSetMouseButtonCallback(window, mouse_button_callback); + glfwSetCursorPosCallback(window, cursor_position_callback); + glfwSetWindowSizeCallback(window, window_size_callback); return 0; } diff --git a/src/window/Window.h b/src/window/Window.h index 605cda547..0f02294ac 100644 --- a/src/window/Window.h +++ b/src/window/Window.h @@ -6,11 +6,11 @@ class GLFWwindow; class Window { + static GLFWwindow* window; public: static uint width; static uint height; - static GLFWwindow* window; // не лучшее решение делать window публичным - static int initialize(uint width, uint height, const char* title); + static int initialize(uint width, uint height, const char* title, int samples); static void terminate(); static void viewport(int x, int y, int width, int height); diff --git a/src/world/Level.cpp b/src/world/Level.cpp index b591fc9dc..2b7d9db3a 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -3,18 +3,20 @@ #include "../lighting/Lighting.h" #include "../voxels/Chunks.h" #include "../voxels/ChunksController.h" +#include "../voxels/ChunksStorage.h" #include "../player_control.h" #include "../physics/Hitbox.h" #include "../physics/PhysicsSolver.h" #include "../objects/Player.h" -Level::Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics) : +Level::Level(World* world, Player* player, Chunks* chunks, ChunksStorage* chunksStorage, PhysicsSolver* physics) : world(world), player(player), chunks(chunks), + chunksStorage(chunksStorage), physics(physics) { lighting = new Lighting(chunks); - chunksController = new ChunksController(world, chunks, lighting); + chunksController = new ChunksController(this, chunks, lighting); playerController = new PlayerController(this); } @@ -24,6 +26,7 @@ Level::~Level(){ delete player; delete lighting; delete chunksController; + delete chunksStorage; delete playerController; } diff --git a/src/world/Level.h b/src/world/Level.h index aea33c5a2..6c981fea4 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -7,6 +7,7 @@ class Chunks; class Lighting; class PhysicsSolver; class ChunksController; +class ChunksStorage; class PlayerController; class Level { @@ -14,11 +15,12 @@ class Level { World* world; Player* player; Chunks* chunks; + ChunksStorage* chunksStorage; PhysicsSolver* physics; Lighting* lighting; ChunksController* chunksController; PlayerController* playerController; - Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics); + Level(World* world, Player* player, Chunks* chunks, ChunksStorage* chunksStorage, PhysicsSolver* physics); ~Level(); void update(float delta, bool interactions); diff --git a/src/world/World.cpp b/src/world/World.cpp index 04b32d334..adaa578d8 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,13 +1,18 @@ #include "World.h" +#include + +#include "Level.h" #include "../files/WorldFiles.h" #include "../voxels/Chunk.h" #include "../voxels/Chunks.h" -#include "Level.h" +#include "../voxels/ChunksStorage.h" #include "../objects/Player.h" #include "../physics/PhysicsSolver.h" #include "../window/Camera.h" +using std::shared_ptr; + World::World(std::string name, std::string directory, int seed) : name(name), seed(seed) { wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_VOL * 2 + 8)); } @@ -20,10 +25,10 @@ void World::write(Level* level) { Chunks* chunks = level->chunks; for (unsigned int i = 0; i < chunks->volume; i++) { - Chunk* chunk = chunks->chunks[i]; + shared_ptr chunk = chunks->chunks[i]; if (chunk == nullptr || !chunk->isUnsaved()) continue; - wfile->put((const char*)chunk->voxels, chunk->x, chunk->z); + wfile->put((const ubyte*)chunk->voxels, chunk->x, chunk->z); } wfile->write(); @@ -31,7 +36,8 @@ void World::write(Level* level) { } Level* World::loadLevel(Player* player) { - Level* level = new Level(this, player, new Chunks(56, 56, 0, 0), new PhysicsSolver(vec3(0, -19.6f, 0))); + ChunksStorage* storage = new ChunksStorage(); + Level* level = new Level(this, player, new Chunks(16, 16, 0, 0), storage, new PhysicsSolver(vec3(0, -19.6f, 0))); wfile->readPlayer(player); Camera* camera = player->camera; diff --git a/src/world_render.cpp b/src/world_render.cpp index 35028f04c..6d0a2b5fd 100644 --- a/src/world_render.cpp +++ b/src/world_render.cpp @@ -1,9 +1,10 @@ #include "world_render.h" #include -#include "graphics/VoxelRenderer.h" #include +#include +#include "graphics/ChunksRenderer.h" #include "window/Window.h" #include "window/Camera.h" #include "graphics/Mesh.h" @@ -20,13 +21,15 @@ #include "Assets.h" #include "player_control.h" +using std::shared_ptr; + float _camera_cx; float _camera_cz; WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) { lineBatch = new LineBatch(4096); batch3d = new Batch3D(1024); - renderer = new VoxelRenderer(); + renderer = new ChunksRenderer(level); } WorldRenderer::~WorldRenderer() { @@ -38,15 +41,17 @@ WorldRenderer::~WorldRenderer() { Chunks* _chunks = nullptr; bool chunks_distance_compare(size_t i, size_t j) { - Chunk* a = _chunks->chunks[i]; - Chunk* b = _chunks->chunks[j]; + shared_ptr a = _chunks->chunks[i]; + shared_ptr 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)); } bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){ - Chunk* chunk = level->chunks->chunks[index]; - Mesh* mesh = level->chunks->meshes[index]; + shared_ptr chunk = level->chunks->chunks[index]; + if (!chunk->isLighted()) + return false; + shared_ptr mesh = renderer->getOrRender(chunk.get()); if (mesh == nullptr) return false; @@ -64,7 +69,7 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool } } } - mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W+0.5f, 0.5f, chunk->z*CHUNK_D+0.5f)); + mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1)); shader->uniformMatrix("u_model", model); glDisable(GL_MULTISAMPLE); mesh->draw(GL_TRIANGLES); @@ -109,11 +114,10 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){ std::vector indices; for (size_t i = 0; i < chunks->volume; i++){ - Chunk* chunk = chunks->chunks[i]; + shared_ptr chunk = chunks->chunks[i]; if (chunk == nullptr) continue; - if (chunks->meshes[i] != nullptr) - indices.push_back(i); + indices.push_back(i); } float px = camera->position.x / (float)CHUNK_W; diff --git a/src/world_render.h b/src/world_render.h index 2dd611dab..7864cfe07 100644 --- a/src/world_render.h +++ b/src/world_render.h @@ -16,7 +16,7 @@ class Camera; class Assets; class LineBatch; class Batch3D; -class VoxelRenderer; +class ChunksRenderer; class Shader; class Texture; class Framebuffer; @@ -28,8 +28,8 @@ class WorldRenderer { Level* level; bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); public: - VoxelRenderer *renderer; - LineBatch *lineBatch; + ChunksRenderer* renderer; + LineBatch* lineBatch; WorldRenderer(Level* level, Assets* assets); ~WorldRenderer();