voxels renderer rebuilt, WorldFiles fix
This commit is contained in:
parent
0576316282
commit
754c5b80d0
@ -18,8 +18,11 @@ Assets::~Assets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Assets::getTexture(std::string name){
|
Texture* Assets::getTexture(std::string name) const {
|
||||||
return textures[name];
|
auto found = textures.find(name);
|
||||||
|
if (found == textures.end())
|
||||||
|
return nullptr;
|
||||||
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Texture* texture, std::string name){
|
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){
|
Shader* Assets::getShader(std::string name) const{
|
||||||
return shaders[name];
|
auto found = shaders.find(name);
|
||||||
|
if (found == shaders.end())
|
||||||
|
return nullptr;
|
||||||
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Shader* shader, std::string name){
|
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){
|
Font* Assets::getFont(std::string name) const {
|
||||||
return fonts[name];
|
auto found = fonts.find(name);
|
||||||
|
if (found == fonts.end())
|
||||||
|
return nullptr;
|
||||||
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Font* font, std::string name){
|
void Assets::store(Font* font, std::string name){
|
||||||
|
|||||||
@ -14,13 +14,13 @@ class Assets {
|
|||||||
std::unordered_map<std::string, Font*> fonts;
|
std::unordered_map<std::string, Font*> fonts;
|
||||||
public:
|
public:
|
||||||
~Assets();
|
~Assets();
|
||||||
Texture* getTexture(std::string name);
|
Texture* getTexture(std::string name) const;
|
||||||
void store(Texture* texture, std::string name);
|
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);
|
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);
|
void store(Font* font, std::string name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
17
src/constants.h
Normal file
17
src/constants.h
Normal file
@ -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_
|
||||||
@ -4,12 +4,10 @@
|
|||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../physics/Hitbox.h"
|
#include "../physics/Hitbox.h"
|
||||||
|
#include "../voxels/voxel.h"
|
||||||
#include "../voxels/Chunk.h"
|
#include "../voxels/Chunk.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
union {
|
#include "../voxmaths.h"
|
||||||
long _key;
|
|
||||||
int _coords[2];
|
|
||||||
} _tempcoords;
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -22,21 +20,25 @@ union {
|
|||||||
#define SECTION_FLAGS 3
|
#define SECTION_FLAGS 3
|
||||||
#define PLAYER_FLAG_FLIGHT 0x1
|
#define PLAYER_FLAG_FLIGHT 0x1
|
||||||
#define PLAYER_FLAG_NOCLIP 0x2
|
#define PLAYER_FLAG_NOCLIP 0x2
|
||||||
|
#define CHUNK_DATA_LEN (CHUNK_VOL*sizeof(voxel))
|
||||||
|
|
||||||
unsigned long WorldFiles::totalCompressed = 0;
|
using glm::ivec2;
|
||||||
|
using glm::vec3;
|
||||||
|
|
||||||
int bytes2Int(const unsigned char* src, unsigned int offset){
|
int64_t WorldFiles::totalCompressed = 0;
|
||||||
|
|
||||||
|
int bytes2Int(const ubyte* src, size_t offset){
|
||||||
return (src[offset] << 24) | (src[offset+1] << 16) | (src[offset+2] << 8) | (src[offset+3]);
|
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] = (char) (value >> 24 & 255);
|
||||||
dest[offset+1] = (char) (value >> 16 & 255);
|
dest[offset+1] = (char) (value >> 16 & 255);
|
||||||
dest[offset+2] = (char) (value >> 8 & 255);
|
dest[offset+2] = (char) (value >> 8 & 255);
|
||||||
dest[offset+3] = (char) (value >> 0 & 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);
|
uint32_t value = *((uint32_t*)&fvalue);
|
||||||
dest[offset] = (char) (value >> 24 & 255);
|
dest[offset] = (char) (value >> 24 & 255);
|
||||||
dest[offset+1] = (char) (value >> 16 & 255);
|
dest[offset+1] = (char) (value >> 16 & 255);
|
||||||
@ -44,8 +46,7 @@ void floatToBytes(float fvalue, char* dest, unsigned int offset){
|
|||||||
dest[offset+3] = (char) (value >> 0 & 255);
|
dest[offset+3] = (char) (value >> 0 & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
float bytes2Float(char* srcs, unsigned int offset){
|
float bytes2Float(ubyte* src, uint offset){
|
||||||
unsigned char* src = (unsigned char*) srcs;
|
|
||||||
uint32_t value = ((src[offset] << 24) |
|
uint32_t value = ((src[offset] << 24) |
|
||||||
(src[offset+1] << 16) |
|
(src[offset+1] << 16) |
|
||||||
(src[offset+2] << 8) |
|
(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){
|
WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : directory(directory){
|
||||||
mainBufferIn = new char[CHUNK_VOL*2];
|
mainBufferIn = new ubyte[CHUNK_DATA_LEN];
|
||||||
mainBufferOut = new char[mainBufferCapacity];
|
mainBufferOut = new ubyte[mainBufferCapacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldFiles::~WorldFiles(){
|
WorldFiles::~WorldFiles(){
|
||||||
delete[] mainBufferIn;
|
delete[] mainBufferIn;
|
||||||
delete[] mainBufferOut;
|
delete[] mainBufferOut;
|
||||||
std::unordered_map<long, WorldRegion>::iterator it;
|
for (auto it = regions.begin(); it != regions.end(); it++){
|
||||||
for (it = regions.begin(); it != regions.end(); it++){
|
|
||||||
WorldRegion region = it->second;
|
WorldRegion region = it->second;
|
||||||
if (region.chunksData == nullptr)
|
if (region.chunksData == nullptr)
|
||||||
continue;
|
continue;
|
||||||
@ -74,31 +74,35 @@ WorldFiles::~WorldFiles(){
|
|||||||
regions.clear();
|
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);
|
assert(chunkData != nullptr);
|
||||||
|
|
||||||
int regionX = x >> REGION_SIZE_BIT;
|
int regionX = floordiv(x, REGION_SIZE);
|
||||||
int regionY = y >> REGION_SIZE_BIT;
|
int regionY = floordiv(y, REGION_SIZE);
|
||||||
|
|
||||||
int localX = x - (regionX << REGION_SIZE_BIT);
|
int localX = x - (regionX * REGION_SIZE);
|
||||||
int localY = y - (regionY << REGION_SIZE_BIT);
|
int localY = y - (regionY * REGION_SIZE);
|
||||||
|
|
||||||
_tempcoords._coords[0] = regionX;
|
ivec2 key(regionX, regionY);
|
||||||
_tempcoords._coords[1] = regionY;
|
|
||||||
WorldRegion& region = regions[_tempcoords._key];
|
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 };
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldRegion& region = regions[key];
|
||||||
region.unsaved = true;
|
region.unsaved = true;
|
||||||
if (region.chunksData == nullptr){
|
ubyte* targetChunk = region.chunksData[localY * REGION_SIZE + localX];
|
||||||
region.chunksData = new char*[REGION_VOL];
|
|
||||||
for (unsigned int i = 0; i < REGION_VOL; i++)
|
|
||||||
region.chunksData[i] = nullptr;
|
|
||||||
}
|
|
||||||
char* targetChunk = region.chunksData[localY * REGION_SIZE + localX];
|
|
||||||
if (targetChunk == nullptr){
|
if (targetChunk == nullptr){
|
||||||
targetChunk = new char[CHUNK_VOL];
|
targetChunk = new ubyte[CHUNK_DATA_LEN];
|
||||||
region.chunksData[localY * REGION_SIZE + localX] = targetChunk;
|
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];
|
targetChunk[i] = chunkData[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -111,44 +115,46 @@ std::string WorldFiles::getPlayerFile() {
|
|||||||
return directory + "/player.bin";
|
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);
|
assert(out != nullptr);
|
||||||
|
|
||||||
int regionX = x >> REGION_SIZE_BIT;
|
int regionX = floordiv(x, REGION_SIZE);
|
||||||
int regionY = y >> REGION_SIZE_BIT;
|
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;
|
int chunkIndex = localY * REGION_SIZE + localX;
|
||||||
assert(chunkIndex >= 0 && chunkIndex < REGION_VOL);
|
assert(chunkIndex >= 0 && chunkIndex < REGION_VOL);
|
||||||
|
|
||||||
_tempcoords._coords[0] = regionX;
|
ivec2 key(regionX, regionY);
|
||||||
_tempcoords._coords[1] = regionY;
|
|
||||||
|
|
||||||
WorldRegion& region = regions[_tempcoords._key];
|
auto found = regions.find(key);
|
||||||
if (region.chunksData == nullptr)
|
if (found == regions.end()) {
|
||||||
return readChunk(x,y,out);
|
return readChunk(x, y, out);
|
||||||
|
}
|
||||||
|
|
||||||
char* chunk = region.chunksData[chunkIndex];
|
WorldRegion& region = found->second;
|
||||||
|
ubyte* chunk = region.chunksData[chunkIndex];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return readChunk(x,y,out);
|
return readChunk(x,y,out);
|
||||||
for (unsigned int i = 0; i < CHUNK_VOL; i++)
|
for (uint i = 0; i < CHUNK_DATA_LEN; i++)
|
||||||
out[i] = chunk[i];
|
out[i] = chunk[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldFiles::readChunk(int x, int y, char* out){
|
bool WorldFiles::readChunk(int x, int y, ubyte* out){
|
||||||
assert(out != nullptr);
|
assert(out != nullptr);
|
||||||
|
|
||||||
int regionX = x >> REGION_SIZE_BIT;
|
int regionX = floordiv(x, REGION_SIZE);
|
||||||
int regionY = y >> REGION_SIZE_BIT;
|
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;
|
int chunkIndex = localY * REGION_SIZE + localX;
|
||||||
|
|
||||||
std::string filename = getRegionFile(regionX, regionY);
|
std::string filename = getRegionFile(regionX, regionY);
|
||||||
|
|
||||||
std::ifstream input(filename, std::ios::binary);
|
std::ifstream input(filename, std::ios::binary);
|
||||||
if (!input.is_open()){
|
if (!input.is_open()){
|
||||||
return false;
|
return false;
|
||||||
@ -166,35 +172,31 @@ bool WorldFiles::readChunk(int x, int y, char* out){
|
|||||||
}
|
}
|
||||||
input.seekg(offset);
|
input.seekg(offset);
|
||||||
input.read((char*)(&offset), 4);
|
input.read((char*)(&offset), 4);
|
||||||
size_t compressedSize = bytes2Int((const unsigned char*)(&offset), 0);
|
size_t compressedSize = bytes2Int((const ubyte*)(&offset), 0);
|
||||||
|
input.read((char*)mainBufferIn, compressedSize);
|
||||||
input.read(mainBufferIn, compressedSize);
|
|
||||||
input.close();
|
input.close();
|
||||||
|
|
||||||
decompressRLE((unsigned char*)mainBufferIn, compressedSize, (unsigned char*)out, CHUNK_VOL);
|
decompressRLE((ubyte*)mainBufferIn, compressedSize, (ubyte*)out, CHUNK_DATA_LEN);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::write(){
|
void WorldFiles::write(){
|
||||||
std::unordered_map<long, WorldRegion>::iterator it;
|
for (auto it = regions.begin(); it != regions.end(); it++){
|
||||||
for (it = regions.begin(); it != regions.end(); it++){
|
|
||||||
if (it->second.chunksData == nullptr || !it->second.unsaved)
|
if (it->second.chunksData == nullptr || !it->second.unsaved)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int x;
|
ivec2 key = it->first;
|
||||||
int y;
|
|
||||||
longToCoords(x,y, it->first);
|
|
||||||
|
|
||||||
unsigned int size = writeRegion(mainBufferOut, x,y, it->second.chunksData);
|
unsigned int size = writeRegion(mainBufferOut, key.x, key.y, it->second.chunksData);
|
||||||
write_binary_file(getRegionFile(x,y), mainBufferOut, size);
|
write_binary_file(getRegionFile(key.x, key.y), (const char*)mainBufferOut, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::writePlayer(Player* player){
|
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;
|
size_t offset = 0;
|
||||||
dst[offset++] = SECTION_POSITION;
|
dst[offset++] = SECTION_POSITION;
|
||||||
@ -215,12 +217,12 @@ void WorldFiles::writePlayer(Player* player){
|
|||||||
|
|
||||||
bool WorldFiles::readPlayer(Player* player) {
|
bool WorldFiles::readPlayer(Player* player) {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
char* data = read_binary_file(getPlayerFile(), length);
|
ubyte* data = (ubyte*)read_binary_file(getPlayerFile(), length);
|
||||||
if (data == nullptr){
|
if (data == nullptr){
|
||||||
std::cerr << "could not to read player.bin (ignored)" << std::endl;
|
std::cerr << "could not to read player.bin (ignored)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glm::vec3 position = player->hitbox->position;
|
vec3 position = player->hitbox->position;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
while (offset < length){
|
while (offset < length){
|
||||||
char section = data[offset++];
|
char section = data[offset++];
|
||||||
@ -248,21 +250,19 @@ bool WorldFiles::readPlayer(Player* player) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WorldFiles::writeRegion(char* out, int x, int y, char** region){
|
uint WorldFiles::writeRegion(ubyte* out, int x, int y, ubyte** region){
|
||||||
unsigned int offset = REGION_VOL * 4;
|
uint offset = REGION_VOL * 4;
|
||||||
for (unsigned int i = 0; i < offset; i++)
|
for (uint i = 0; i < offset; i++)
|
||||||
out[i] = 0;
|
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++){
|
for (int i = 0; i < REGION_VOL; i++){
|
||||||
char* chunk = region[i];
|
ubyte* chunk = region[i];
|
||||||
if (chunk == nullptr){
|
if (chunk == nullptr){
|
||||||
chunk = new char[CHUNK_VOL];
|
chunk = new ubyte[CHUNK_DATA_LEN];
|
||||||
assert((((i % REGION_SIZE) + x * REGION_SIZE) >> REGION_SIZE_BIT) == x);
|
|
||||||
assert((((i / REGION_SIZE) + y * REGION_SIZE) >> REGION_SIZE_BIT) == y);
|
|
||||||
if (readChunk((i % REGION_SIZE) + x * REGION_SIZE, (i / REGION_SIZE) + y * REGION_SIZE, chunk)){
|
if (readChunk((i % REGION_SIZE) + x * REGION_SIZE, (i / REGION_SIZE) + y * REGION_SIZE, chunk)){
|
||||||
region[i] = chunk;
|
region[i] = chunk;
|
||||||
totalCompressed += CHUNK_VOL;
|
totalCompressed += CHUNK_DATA_LEN;
|
||||||
} else {
|
} else {
|
||||||
delete[] chunk;
|
delete[] chunk;
|
||||||
chunk = nullptr;
|
chunk = nullptr;
|
||||||
@ -274,21 +274,15 @@ unsigned int WorldFiles::writeRegion(char* out, int x, int y, char** region){
|
|||||||
} else {
|
} else {
|
||||||
int2Bytes(offset, out, i*4);
|
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);
|
int2Bytes(compressedSize, out, offset);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < compressedSize; j++)
|
for (uint j = 0; j < compressedSize; j++)
|
||||||
out[offset++] = compressed[j];
|
out[offset++] = compressed[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] compressed;
|
delete[] compressed;
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void longToCoords(int& x, int& y, long key) {
|
|
||||||
_tempcoords._key = key;
|
|
||||||
x = _tempcoords._coords[0];
|
|
||||||
y = _tempcoords._coords[1];
|
|
||||||
}
|
|
||||||
|
|||||||
@ -4,6 +4,13 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include "glm/gtx/hash.hpp"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
#define REGION_SIZE_BIT 5
|
#define REGION_SIZE_BIT 5
|
||||||
@ -11,28 +18,27 @@ class Player;
|
|||||||
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
||||||
|
|
||||||
struct WorldRegion {
|
struct WorldRegion {
|
||||||
char** chunksData;
|
ubyte** chunksData;
|
||||||
bool unsaved;
|
bool unsaved;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorldFiles {
|
class WorldFiles {
|
||||||
public:
|
public:
|
||||||
static unsigned long totalCompressed;
|
static int64_t totalCompressed;
|
||||||
std::unordered_map<long, WorldRegion> regions;
|
std::unordered_map<glm::ivec2, WorldRegion> regions;
|
||||||
std::string directory;
|
std::string directory;
|
||||||
char* mainBufferIn;
|
ubyte* mainBufferIn;
|
||||||
char* mainBufferOut;
|
ubyte* mainBufferOut;
|
||||||
|
|
||||||
WorldFiles(std::string directory, size_t mainBufferCapacity);
|
WorldFiles(std::string directory, size_t mainBufferCapacity);
|
||||||
~WorldFiles();
|
~WorldFiles();
|
||||||
|
|
||||||
void put(const char* chunkData, int x, int y);
|
void put(const ubyte* chunkData, int x, int y);
|
||||||
|
|
||||||
bool readPlayer(Player* player);
|
bool readPlayer(Player* player);
|
||||||
bool readChunk(int x, int y, char* out);
|
bool readChunk(int x, int y, ubyte* out);
|
||||||
bool getChunk(int x, int y, char* out);
|
bool getChunk(int x, int y, ubyte* out);
|
||||||
void readRegion(char* fileContent);
|
uint writeRegion(ubyte* out, int x, int y, ubyte** region);
|
||||||
unsigned int writeRegion(char* out, int x, int y, char** region);
|
|
||||||
void writePlayer(Player* player);
|
void writePlayer(Player* player);
|
||||||
void write();
|
void write();
|
||||||
|
|
||||||
@ -40,6 +46,4 @@ public:
|
|||||||
std::string getPlayerFile();
|
std::string getPlayerFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void longToCoords(int& x, int& y, long key);
|
|
||||||
|
|
||||||
#endif /* FILES_WORLDFILES_H_ */
|
#endif /* FILES_WORLDFILES_H_ */
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
#define VERTEX_SIZE 8
|
#define VERTEX_SIZE 8
|
||||||
|
|
||||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 1.0f){
|
Batch2D::Batch2D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 1.0f){
|
||||||
const int attrs[] = {
|
const vattr attrs[] = {
|
||||||
2, 2, 4, 0 //null terminator
|
{2}, {2}, {4}, {0}
|
||||||
};
|
};
|
||||||
|
|
||||||
buffer = new float[capacity * VERTEX_SIZE];
|
buffer = new float[capacity * VERTEX_SIZE];
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
#define VERTEX_SIZE 9
|
#define VERTEX_SIZE 9
|
||||||
|
|
||||||
Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 0.0f){
|
Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 0.0f){
|
||||||
const int attrs[] = {
|
const vattr attrs[] = {
|
||||||
3, 2, 4, 0 //null terminator
|
{3}, {2}, {4}, {0}
|
||||||
};
|
};
|
||||||
|
|
||||||
buffer = new float[capacity * VERTEX_SIZE];
|
buffer = new float[capacity * VERTEX_SIZE];
|
||||||
|
|||||||
352
src/graphics/BlocksRenderer.cpp
Normal file
352
src/graphics/BlocksRenderer.cpp
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
#include "BlocksRenderer.h"
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
71
src/graphics/BlocksRenderer.h
Normal file
71
src/graphics/BlocksRenderer.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef GRAPHICS_BLOCKS_RENDERER_H
|
||||||
|
#define GRAPHICS_BLOCKS_RENDERER_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#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
|
||||||
52
src/graphics/ChunksRenderer.cpp
Normal file
52
src/graphics/ChunksRenderer.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "ChunksRenderer.h"
|
||||||
|
|
||||||
|
#include "Mesh.h"
|
||||||
|
#include "BlocksRenderer.h"
|
||||||
|
#include "../voxels/Chunk.h"
|
||||||
|
#include "../world/Level.h"
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/ext.hpp>
|
||||||
|
|
||||||
|
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<Mesh> ChunksRenderer::render(Chunk* chunk) {
|
||||||
|
chunk->setModified(false);
|
||||||
|
Mesh* mesh = renderer->render(chunk, 16, level->chunksStorage);
|
||||||
|
auto sptr = shared_ptr<Mesh>(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<Mesh> 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<Mesh> ChunksRenderer::get(Chunk* chunk) {
|
||||||
|
auto found = meshes.find(ivec2(chunk->x, chunk->z));
|
||||||
|
if (found != meshes.end()) {
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
31
src/graphics/ChunksRenderer.h
Normal file
31
src/graphics/ChunksRenderer.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef SRC_GRAPHICS_CHUNKSRENDERER_H_
|
||||||
|
#define SRC_GRAPHICS_CHUNKSRENDERER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#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<glm::ivec2, std::shared_ptr<Mesh>> meshes;
|
||||||
|
public:
|
||||||
|
ChunksRenderer(Level* level);
|
||||||
|
virtual ~ChunksRenderer();
|
||||||
|
|
||||||
|
std::shared_ptr<Mesh> render(Chunk* chunk);
|
||||||
|
void unload(Chunk* chunk);
|
||||||
|
|
||||||
|
std::shared_ptr<Mesh> getOrRender(Chunk* chunk);
|
||||||
|
std::shared_ptr<Mesh> get(Chunk* chunk);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SRC_GRAPHICS_CHUNKSRENDERER_H_
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#define LB_VERTEX_SIZE (3+4)
|
#define LB_VERTEX_SIZE (3+4)
|
||||||
|
|
||||||
LineBatch::LineBatch(size_t capacity) : capacity(capacity) {
|
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];
|
buffer = new float[capacity * LB_VERTEX_SIZE * 2];
|
||||||
mesh = new Mesh(buffer, 0, attrs);
|
mesh = new Mesh(buffer, 0, attrs);
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
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;
|
vertexSize = 0;
|
||||||
for (int i = 0; attrs[i]; i++){
|
for (int i = 0; attrs[i].size; i++){
|
||||||
vertexSize += attrs[i];
|
vertexSize += attrs[i].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
@ -21,8 +24,8 @@ Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(ve
|
|||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (int i = 0; attrs[i]; i++){
|
for (int i = 0; attrs[i].size; i++){
|
||||||
int size = attrs[i];
|
int size = attrs[i].size;
|
||||||
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
|
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
|
||||||
glEnableVertexAttribArray(i);
|
glEnableVertexAttribArray(i);
|
||||||
offset += size;
|
offset += size;
|
||||||
@ -32,6 +35,7 @@ Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(ve
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mesh::~Mesh(){
|
Mesh::~Mesh(){
|
||||||
|
meshesCount--;
|
||||||
glDeleteVertexArrays(1, &vao);
|
glDeleteVertexArrays(1, &vao);
|
||||||
glDeleteBuffers(1, &vbo);
|
glDeleteBuffers(1, &vbo);
|
||||||
}
|
}
|
||||||
@ -48,3 +52,7 @@ void Mesh::draw(unsigned int primitive){
|
|||||||
glDrawArrays(primitive, 0, vertices);
|
glDrawArrays(primitive, 0, vertices);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::draw() {
|
||||||
|
draw(GL_TRIANGLES);
|
||||||
|
}
|
||||||
@ -2,6 +2,11 @@
|
|||||||
#define GRAPHICS_MESH_H_
|
#define GRAPHICS_MESH_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
struct vattr {
|
||||||
|
ubyte size;
|
||||||
|
};
|
||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
unsigned int vao;
|
unsigned int vao;
|
||||||
@ -9,11 +14,14 @@ class Mesh {
|
|||||||
size_t vertices;
|
size_t vertices;
|
||||||
size_t vertexSize;
|
size_t vertexSize;
|
||||||
public:
|
public:
|
||||||
Mesh(const float* buffer, size_t vertices, const int* attrs);
|
Mesh(const float* buffer, size_t vertices, const vattr* attrs);
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
void reload(const float* buffer, size_t vertices);
|
void reload(const float* buffer, size_t vertices);
|
||||||
void draw(unsigned int primitive);
|
void draw(unsigned int primitive);
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
static int meshesCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* GRAPHICS_MESH_H_ */
|
#endif /* GRAPHICS_MESH_H_ */
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "hud_render.h"
|
#include "hud_render.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
@ -20,19 +21,6 @@
|
|||||||
|
|
||||||
|
|
||||||
HudRenderer::HudRenderer() {
|
HudRenderer::HudRenderer() {
|
||||||
// float vertices[] = {
|
|
||||||
// // x y
|
|
||||||
// -0.01f,-0.01f,
|
|
||||||
// 0.01f, 0.01f,
|
|
||||||
|
|
||||||
// -0.01f, 0.01f,
|
|
||||||
// 0.01f,-0.01f,
|
|
||||||
// };
|
|
||||||
// int attrs[] = {
|
|
||||||
// 2, 0 //null terminator
|
|
||||||
// };
|
|
||||||
// crosshair = new Mesh(vertices, 4, attrs);
|
|
||||||
|
|
||||||
batch = new Batch2D(1024);
|
batch = new Batch2D(1024);
|
||||||
uicamera = new Camera(glm::vec3(), Window::height / 1.0f);
|
uicamera = new Camera(glm::vec3(), Window::height / 1.0f);
|
||||||
uicamera->perspective = false;
|
uicamera->perspective = false;
|
||||||
@ -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, L"fps:", 16, 42, STYLE_OUTLINE);
|
||||||
font->draw(batch, std::to_wstring(fps), 44, 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);
|
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();
|
// batch->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,11 @@
|
|||||||
#include "../voxels/voxel.h"
|
#include "../voxels/voxel.h"
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
Lighting::Lighting(Chunks* chunks){
|
Lighting::Lighting(Chunks* chunks){
|
||||||
this->chunks = chunks;
|
this->chunks = chunks;
|
||||||
solverR = new LightSolver(chunks, 0);
|
solverR = new LightSolver(chunks, 0);
|
||||||
@ -25,7 +28,7 @@ Lighting::~Lighting(){
|
|||||||
|
|
||||||
void Lighting::clear(){
|
void Lighting::clear(){
|
||||||
for (unsigned int index = 0; index < chunks->volume; index++){
|
for (unsigned int index = 0; index < chunks->volume; index++){
|
||||||
Chunk* chunk = chunks->chunks[index];
|
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
Lightmap* lightmap = chunk->lightmap;
|
Lightmap* lightmap = chunk->lightmap;
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
#ifndef LIGHTING_LIGHTMAP_H_
|
#ifndef LIGHTING_LIGHTMAP_H_
|
||||||
#define LIGHTING_LIGHTMAP_H_
|
#define LIGHTING_LIGHTMAP_H_
|
||||||
|
|
||||||
|
#include "../constants.h"
|
||||||
#include "../voxels/Chunk.h"
|
#include "../voxels/Chunk.h"
|
||||||
|
|
||||||
|
// Lichtkarte
|
||||||
class Lightmap {
|
class Lightmap {
|
||||||
public:
|
public:
|
||||||
unsigned short* map;
|
light_t* map;
|
||||||
int highestPoint = 0;
|
int highestPoint = 0;
|
||||||
Lightmap();
|
Lightmap();
|
||||||
~Lightmap();
|
~Lightmap();
|
||||||
@ -60,6 +62,18 @@ public:
|
|||||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||||
map[index] = (map[index] & (0xFFFF & (~(0xF << (channel*4))))) | (value << (channel << 2));
|
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_ */
|
#endif /* LIGHTING_LIGHTMAP_H_ */
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "../voxels/voxel.h"
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class Hitbox;
|
class Hitbox;
|
||||||
class PhysicsSolver;
|
class PhysicsSolver;
|
||||||
@ -21,6 +23,7 @@ public:
|
|||||||
float cameraShaking = 0.0f;
|
float cameraShaking = 0.0f;
|
||||||
float cameraShakingTimer = 0.0f;
|
float cameraShakingTimer = 0.0f;
|
||||||
glm::vec3 interpVel {0.0f, 0.0f, 0.0f};
|
glm::vec3 interpVel {0.0f, 0.0f, 0.0f};
|
||||||
|
voxel selectedVoxel {0, 0};
|
||||||
Player(glm::vec3 position, float speed, Camera* camera);
|
Player(glm::vec3 position, float speed, Camera* camera);
|
||||||
~Player();
|
~Player();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,15 +5,13 @@
|
|||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
using namespace glm;
|
|
||||||
|
|
||||||
class Hitbox;
|
class Hitbox;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
|
|
||||||
class PhysicsSolver {
|
class PhysicsSolver {
|
||||||
vec3 gravity;
|
glm::vec3 gravity;
|
||||||
public:
|
public:
|
||||||
PhysicsSolver(vec3 gravity);
|
PhysicsSolver(glm::vec3 gravity);
|
||||||
void step(Chunks* chunks,
|
void step(Chunks* chunks,
|
||||||
Hitbox* hitbox,
|
Hitbox* hitbox,
|
||||||
float delta,
|
float delta,
|
||||||
@ -21,7 +19,7 @@ public:
|
|||||||
bool shifting,
|
bool shifting,
|
||||||
float gravityScale,
|
float gravityScale,
|
||||||
bool collisions);
|
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);
|
bool isBlockInside(int x, int y, int z, Hitbox* hitbox);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -183,6 +183,7 @@ void PlayerController::update_interaction(){
|
|||||||
vec3 iend;
|
vec3 iend;
|
||||||
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
|
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
|
||||||
if (vox != nullptr){
|
if (vox != nullptr){
|
||||||
|
player->selectedVoxel = *vox;
|
||||||
selectedBlockId = vox->id;
|
selectedBlockId = vox->id;
|
||||||
selectedBlockPosition = iend;
|
selectedBlockPosition = iend;
|
||||||
int x = (int)iend.x;
|
int x = (int)iend.x;
|
||||||
|
|||||||
@ -2,3 +2,6 @@
|
|||||||
|
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
typedef unsigned char ubyte;
|
typedef unsigned char ubyte;
|
||||||
|
|
||||||
|
typedef uint8_t blockid_t;
|
||||||
|
typedef uint16_t light_t;
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -17,8 +18,6 @@
|
|||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
using namespace glm;
|
|
||||||
|
|
||||||
#include "window/Window.h"
|
#include "window/Window.h"
|
||||||
#include "window/Events.h"
|
#include "window/Events.h"
|
||||||
#include "window/Camera.h"
|
#include "window/Camera.h"
|
||||||
@ -26,7 +25,7 @@ using namespace glm;
|
|||||||
#include "voxels/Chunk.h"
|
#include "voxels/Chunk.h"
|
||||||
#include "voxels/Chunks.h"
|
#include "voxels/Chunks.h"
|
||||||
#include "voxels/ChunksController.h"
|
#include "voxels/ChunksController.h"
|
||||||
#include "voxels/ChunksLoader.h"
|
#include "voxels/ChunksStorage.h"
|
||||||
#include "objects/Player.h"
|
#include "objects/Player.h"
|
||||||
#include "world/Level.h"
|
#include "world/Level.h"
|
||||||
#include "world/World.h"
|
#include "world/World.h"
|
||||||
@ -36,14 +35,19 @@ using namespace glm;
|
|||||||
#include "world_render.h"
|
#include "world_render.h"
|
||||||
#include "hud_render.h"
|
#include "hud_render.h"
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
|
|
||||||
class initialize_error : public std::runtime_error {
|
class initialize_error : public std::runtime_error {
|
||||||
|
public:
|
||||||
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct EngineSettings {
|
struct EngineSettings {
|
||||||
int displayWidth;
|
int displayWidth;
|
||||||
int displayHeight;
|
int displayHeight;
|
||||||
|
int displaySamples;
|
||||||
const char* title;
|
const char* title;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,8 +70,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Engine::Engine(const EngineSettings& settings) {
|
Engine::Engine(const EngineSettings& settings) {
|
||||||
Window::initialize(settings.displayWidth, settings.displayHeight, settings.title);
|
Window::initialize(settings.displayWidth, settings.displayHeight, settings.title, settings.displaySamples);
|
||||||
Events::initialize();
|
|
||||||
|
|
||||||
assets = new Assets();
|
assets = new Assets();
|
||||||
std::cout << "-- loading assets" << std::endl;
|
std::cout << "-- loading assets" << std::endl;
|
||||||
@ -78,7 +81,7 @@ Engine::Engine(const EngineSettings& settings) {
|
|||||||
if (!loader.loadNext()) {
|
if (!loader.loadNext()) {
|
||||||
delete assets;
|
delete assets;
|
||||||
Window::terminate();
|
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;
|
std::cout << "-- loading world" << std::endl;
|
||||||
@ -115,7 +118,7 @@ void Engine::updateHotkeys() {
|
|||||||
}
|
}
|
||||||
if (Events::jpressed(GLFW_KEY_F5)) {
|
if (Events::jpressed(GLFW_KEY_F5)) {
|
||||||
for (unsigned i = 0; i < level->chunks->volume; i++) {
|
for (unsigned i = 0; i < level->chunks->volume; i++) {
|
||||||
Chunk* chunk = level->chunks->chunks[i];
|
shared_ptr<Chunk> chunk = level->chunks->chunks[i];
|
||||||
if (chunk != nullptr && chunk->isReady()) {
|
if (chunk != nullptr && chunk->isReady()) {
|
||||||
chunk->setModified(true);
|
chunk->setModified(true);
|
||||||
}
|
}
|
||||||
@ -137,15 +140,7 @@ void Engine::mainloop() {
|
|||||||
updateHotkeys();
|
updateHotkeys();
|
||||||
|
|
||||||
level->update(delta, Events::_cursor_locked);
|
level->update(delta, Events::_cursor_locked);
|
||||||
int freeLoaders = level->chunksController->countFreeLoaders();
|
level->chunksController->loadVisible(world->wfile);
|
||||||
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);
|
|
||||||
|
|
||||||
worldRenderer.draw(camera, occlusion);
|
worldRenderer.draw(camera, occlusion);
|
||||||
hud.draw(level, assets);
|
hud.draw(level, assets);
|
||||||
@ -176,15 +171,13 @@ Engine::~Engine() {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
setup_definitions();
|
setup_definitions();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Engine engine(EngineSettings{ 1280, 720, "VoxelEngine-Cpp v13" });
|
Engine engine(EngineSettings{ 1280, 720, 1, "VoxelEngine-Cpp v13" });
|
||||||
engine.mainloop();
|
engine.mainloop();
|
||||||
}
|
}
|
||||||
catch (const initialize_error& err) {
|
catch (const initialize_error& err) {
|
||||||
std::cerr << "could not to initialize engine" << std::endl;
|
std::cerr << "could not to initialize engine" << std::endl;
|
||||||
std::cerr << err.what() << std::endl;
|
std::cerr << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,13 @@
|
|||||||
#define BLOCK_MODEL_CUBE 1
|
#define BLOCK_MODEL_CUBE 1
|
||||||
#define BLOCK_MODEL_X_SPRITE 2
|
#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 {
|
class Block {
|
||||||
public:
|
public:
|
||||||
static Block* blocks[256];
|
static Block* blocks[256];
|
||||||
|
|||||||
@ -36,11 +36,3 @@ Chunk* Chunk::clone() const {
|
|||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::incref(){
|
|
||||||
references++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::decref(){
|
|
||||||
if (--references <= 0)
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,11 +2,7 @@
|
|||||||
#define VOXELS_CHUNK_H_
|
#define VOXELS_CHUNK_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "../constants.h"
|
||||||
#define CHUNK_W 16
|
|
||||||
#define CHUNK_H 256
|
|
||||||
#define CHUNK_D 16
|
|
||||||
#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D * 2)
|
|
||||||
|
|
||||||
#define CHUNK_MODIFIED 0x1
|
#define CHUNK_MODIFIED 0x1
|
||||||
#define CHUNK_READY 0x2
|
#define CHUNK_READY 0x2
|
||||||
@ -14,7 +10,7 @@
|
|||||||
#define CHUNK_LIGHTED 0x8
|
#define CHUNK_LIGHTED 0x8
|
||||||
#define CHUNK_UNSAVED 0x10
|
#define CHUNK_UNSAVED 0x10
|
||||||
|
|
||||||
class voxel;
|
struct voxel;
|
||||||
class Lightmap;
|
class Lightmap;
|
||||||
|
|
||||||
struct RenderData {
|
struct RenderData {
|
||||||
@ -33,7 +29,6 @@ public:
|
|||||||
Lightmap* lightmap;
|
Lightmap* lightmap;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int surrounding = 0;
|
int surrounding = 0;
|
||||||
int references = 1;
|
|
||||||
RenderData renderData;
|
RenderData renderData;
|
||||||
|
|
||||||
Chunk(int x, int z);
|
Chunk(int x, int z);
|
||||||
@ -42,8 +37,6 @@ public:
|
|||||||
bool isEmpty();
|
bool isEmpty();
|
||||||
|
|
||||||
Chunk* clone() const;
|
Chunk* clone() const;
|
||||||
void incref();
|
|
||||||
void decref();
|
|
||||||
|
|
||||||
// flags getters/setters below
|
// flags getters/setters below
|
||||||
|
|
||||||
|
|||||||
@ -7,29 +7,28 @@
|
|||||||
#include "../files/WorldFiles.h"
|
#include "../files/WorldFiles.h"
|
||||||
|
|
||||||
#include "../graphics/Mesh.h"
|
#include "../graphics/Mesh.h"
|
||||||
|
#include "../voxmaths.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
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){
|
Chunks::Chunks(int w, int d, int ox, int oz) : w(w), d(d), ox(ox), oz(oz){
|
||||||
volume = w*d;
|
volume = w*d;
|
||||||
chunks = new Chunk*[volume];
|
chunks = new shared_ptr<Chunk>[volume];
|
||||||
chunksSecond = new Chunk*[volume];
|
chunksSecond = new shared_ptr<Chunk>[volume];
|
||||||
|
|
||||||
meshes = new Mesh*[volume];
|
|
||||||
meshesSecond = new Mesh*[volume];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < volume; i++){
|
for (size_t i = 0; i < volume; i++){
|
||||||
chunks[i] = nullptr;
|
chunks[i] = nullptr;
|
||||||
meshes[i] = nullptr;
|
|
||||||
}
|
}
|
||||||
chunksCount = 0;
|
chunksCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunks::~Chunks(){
|
Chunks::~Chunks(){
|
||||||
for (size_t i = 0; i < volume; i++){
|
for (size_t i = 0; i < volume; i++){
|
||||||
if (chunks[i])
|
chunks[i] = nullptr;
|
||||||
chunks[i]->decref();
|
|
||||||
}
|
}
|
||||||
delete[] chunks;
|
delete[] chunks;
|
||||||
}
|
}
|
||||||
@ -45,7 +44,7 @@ voxel* Chunks::get(int x, int y, int z){
|
|||||||
if (z < 0) cz--;
|
if (z < 0) cz--;
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
int lx = x - cx * CHUNK_W;
|
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;
|
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;
|
x -= ox * CHUNK_W;
|
||||||
z -= oz * CHUNK_D;
|
z -= oz * CHUNK_D;
|
||||||
int cx = x / CHUNK_W;
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cy = y / CHUNK_H;
|
int cy = floordiv(y, CHUNK_H);
|
||||||
int cz = z / CHUNK_D;
|
int cz = floordiv(z, CHUNK_D);
|
||||||
if (x < 0) cx--;
|
|
||||||
if (y < 0) cy--;
|
|
||||||
if (z < 0) cz--;
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||||
return 0;
|
return 0;
|
||||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
int lx = x - cx * CHUNK_W;
|
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);
|
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;
|
x -= ox * CHUNK_W;
|
||||||
z -= oz * CHUNK_D;
|
z -= oz * CHUNK_D;
|
||||||
int cx = x / CHUNK_W;
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cy = y / CHUNK_H;
|
int cy = floordiv(y, CHUNK_H);
|
||||||
int cz = z / CHUNK_D;
|
int cz = floordiv(z, CHUNK_D);
|
||||||
if (x < 0) cx--;
|
|
||||||
if (y < 0) cy--;
|
|
||||||
if (z < 0) cz--;
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||||
return 0;
|
return 0;
|
||||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
@ -112,7 +105,7 @@ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
|||||||
if (z < 0) cz--;
|
if (z < 0) cz--;
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return chunks[(cy * d + cz) * w + cx];
|
return chunks[(cy * d + cz) * w + cx].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunk(int x, int z){
|
Chunk* Chunks::getChunk(int x, int z){
|
||||||
@ -120,7 +113,7 @@ Chunk* Chunks::getChunk(int x, int z){
|
|||||||
z -= oz;
|
z -= oz;
|
||||||
if (x < 0 || z < 0 || x >= w || z >= d)
|
if (x < 0 || z < 0 || x >= w || z >= d)
|
||||||
return nullptr;
|
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){
|
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 (z < 0) cz--;
|
||||||
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
||||||
return;
|
return;
|
||||||
Chunk* chunk = chunks[cz * w + cx];
|
Chunk* chunk = chunks[cz * w + cx].get();
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
return;
|
return;
|
||||||
int lx = x - cx * CHUNK_W;
|
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 stepy = (dy > 0.0f) ? 1.0f : -1.0f;
|
||||||
float stepz = (dz > 0.0f) ? 1.0f : -1.0f;
|
float stepz = (dz > 0.0f) ? 1.0f : -1.0f;
|
||||||
|
|
||||||
float infinity = std::numeric_limits<float>::infinity();
|
constexpr float infinity = std::numeric_limits<float>::infinity();
|
||||||
|
|
||||||
float txDelta = (dx == 0.0f) ? infinity : abs(1.0f / dx);
|
float txDelta = (dx == 0.0f) ? infinity : abs(1.0f / dx);
|
||||||
float tyDelta = (dy == 0.0f) ? infinity : abs(1.0f / dy);
|
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){
|
void Chunks::translate(WorldFiles* worldFiles, int dx, int dz){
|
||||||
for (unsigned int i = 0; i < volume; i++){
|
for (unsigned int i = 0; i < volume; i++){
|
||||||
chunksSecond[i] = nullptr;
|
chunksSecond[i] = nullptr;
|
||||||
meshesSecond[i] = nullptr;
|
|
||||||
}
|
}
|
||||||
for (int z = 0; z < d; z++){
|
for (int z = 0; z < d; z++){
|
||||||
for (int x = 0; x < w; x++){
|
for (int x = 0; x < w; x++){
|
||||||
Chunk* chunk = chunks[z * w + x];
|
shared_ptr<Chunk> chunk = chunks[z * w + x];
|
||||||
int nx = x - dx;
|
int nx = x - dx;
|
||||||
int nz = z - dz;
|
int nz = z - dz;
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
Mesh* mesh = meshes[z * w + x];
|
|
||||||
if (nx < 0 || nz < 0 || nx >= w || nz >= d){
|
if (nx < 0 || nz < 0 || nx >= w || nz >= d){
|
||||||
worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z);
|
worldFiles->put((const ubyte*)chunk->voxels, chunk->x, chunk->z);
|
||||||
chunk->decref();
|
|
||||||
delete mesh;
|
|
||||||
chunksCount--;
|
chunksCount--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
meshesSecond[nz * w + nx] = mesh;
|
|
||||||
chunksSecond[nz * w + nx] = chunk;
|
chunksSecond[nz * w + nx] = chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Chunk** ctemp = chunks;
|
shared_ptr<Chunk>* ctemp = chunks;
|
||||||
chunks = chunksSecond;
|
chunks = chunksSecond;
|
||||||
chunksSecond = ctemp;
|
chunksSecond = ctemp;
|
||||||
|
|
||||||
Mesh** mtemp = meshes;
|
|
||||||
meshes = meshesSecond;
|
|
||||||
meshesSecond = mtemp;
|
|
||||||
|
|
||||||
ox += dx;
|
ox += dx;
|
||||||
oz += dz;
|
oz += dz;
|
||||||
}
|
}
|
||||||
@ -294,7 +278,7 @@ void Chunks::_setOffset(int x, int z){
|
|||||||
oz = z;
|
oz = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunks::putChunk(Chunk* chunk) {
|
bool Chunks::putChunk(shared_ptr<Chunk> chunk) {
|
||||||
int x = chunk->x;
|
int x = chunk->x;
|
||||||
int z = chunk->z;
|
int z = chunk->z;
|
||||||
x -= ox;
|
x -= ox;
|
||||||
@ -306,14 +290,9 @@ bool Chunks::putChunk(Chunk* chunk) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::clear(bool freeMemory){
|
void Chunks::clear(){
|
||||||
for (size_t i = 0; i < volume; i++){
|
for (size_t i = 0; i < volume; i++){
|
||||||
if (freeMemory){
|
|
||||||
chunks[i]->decref();
|
|
||||||
delete meshes[i];
|
|
||||||
}
|
|
||||||
chunks[i] = nullptr;
|
chunks[i] = nullptr;
|
||||||
meshes[i] = nullptr;
|
|
||||||
}
|
}
|
||||||
chunksCount = 0;
|
chunksCount = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,10 @@
|
|||||||
#define VOXELS_CHUNKS_H_
|
#define VOXELS_CHUNKS_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <memory>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
using namespace glm;
|
|
||||||
|
|
||||||
class Mesh;
|
|
||||||
class VoxelRenderer;
|
class VoxelRenderer;
|
||||||
|
|
||||||
class Chunk;
|
class Chunk;
|
||||||
@ -15,10 +14,8 @@ class WorldFiles;
|
|||||||
|
|
||||||
class Chunks {
|
class Chunks {
|
||||||
public:
|
public:
|
||||||
Chunk** chunks;
|
std::shared_ptr<Chunk>* chunks;
|
||||||
Chunk** chunksSecond;
|
std::shared_ptr<Chunk>* chunksSecond;
|
||||||
Mesh** meshes;
|
|
||||||
Mesh** meshesSecond;
|
|
||||||
size_t volume;
|
size_t volume;
|
||||||
size_t chunksCount;
|
size_t chunksCount;
|
||||||
int w,d;
|
int w,d;
|
||||||
@ -27,15 +24,15 @@ public:
|
|||||||
Chunks(int w, int d, int ox, int oz);
|
Chunks(int w, int d, int ox, int oz);
|
||||||
~Chunks();
|
~Chunks();
|
||||||
|
|
||||||
bool putChunk(Chunk* chunk);
|
bool putChunk(std::shared_ptr<Chunk> chunk);
|
||||||
|
|
||||||
Chunk* getChunk(int x, int z);
|
Chunk* getChunk(int x, int z);
|
||||||
Chunk* getChunkByVoxel(int x, int y, int z);
|
Chunk* getChunkByVoxel(int x, int y, int z);
|
||||||
voxel* get(int x, int y, int z);
|
voxel* get(int x, int y, int z);
|
||||||
unsigned short getLight(int x, int y, int z);
|
light_t getLight(int x, int y, int z);
|
||||||
unsigned char getLight(int x, int y, int z, int channel);
|
ubyte getLight(int x, int y, int z, int channel);
|
||||||
void set(int x, int y, int z, int id, uint8_t states);
|
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);
|
bool isObstacle(int x, int y, int z);
|
||||||
|
|
||||||
@ -45,7 +42,7 @@ public:
|
|||||||
void setCenter(WorldFiles* worldFiles, int x, int z);
|
void setCenter(WorldFiles* worldFiles, int x, int z);
|
||||||
void translate(WorldFiles* worldFiles, int x, int z);
|
void translate(WorldFiles* worldFiles, int x, int z);
|
||||||
|
|
||||||
void clear(bool freeMemory);
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* VOXELS_CHUNKS_H_ */
|
#endif /* VOXELS_CHUNKS_H_ */
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
#include "ChunksController.h"
|
#include "ChunksController.h"
|
||||||
|
#include "Block.h"
|
||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
#include "Chunks.h"
|
#include "Chunks.h"
|
||||||
|
#include "ChunksStorage.h"
|
||||||
#include "WorldGenerator.h"
|
#include "WorldGenerator.h"
|
||||||
#include "../graphics/Mesh.h"
|
#include "../graphics/Mesh.h"
|
||||||
#include "../graphics/VoxelRenderer.h"
|
|
||||||
#include "../lighting/Lighting.h"
|
#include "../lighting/Lighting.h"
|
||||||
#include "../files/WorldFiles.h"
|
#include "../files/WorldFiles.h"
|
||||||
#include "ChunksLoader.h"
|
#include "../world/Level.h"
|
||||||
|
#include "../world/World.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(__MINGW32__)
|
#if defined(_WIN32) && defined(__MINGW32__)
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
@ -19,31 +22,13 @@
|
|||||||
|
|
||||||
#define MIN_SURROUNDING 9
|
#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;
|
ChunksController::ChunksController(Level* level, Chunks* chunks, Lighting* lighting) : level(level), chunks(chunks), lighting(lighting){
|
||||||
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(){
|
ChunksController::~ChunksController(){
|
||||||
for (int i = 0; i < loadersCount; i++)
|
|
||||||
delete loaders[i];
|
|
||||||
delete[] loaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChunksController::countFreeLoaders(){
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < loadersCount; i++){
|
|
||||||
if (!loaders[i]->isBusy())
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
||||||
@ -57,16 +42,22 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
|||||||
for (int z = 2; z < d-2; z++){
|
for (int z = 2; z < d-2; z++){
|
||||||
for (int x = 2; x < w-2; x++){
|
for (int x = 2; x < w-2; x++){
|
||||||
int index = z * w + x;
|
int index = z * w + x;
|
||||||
Chunk* chunk = chunks->chunks[index];
|
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||||
if (chunk != nullptr){
|
if (chunk != nullptr){
|
||||||
int surrounding = 0;
|
int surrounding = 0;
|
||||||
for (int oz = -1; oz <= 1; oz++){
|
for (int oz = -1; oz <= 1; oz++){
|
||||||
for (int ox = -1; ox <= 1; ox++){
|
for (int ox = -1; ox <= 1; ox++){
|
||||||
Chunk* other = chunks->getChunk(chunk->x+ox, chunk->z+oz);
|
Chunk* other = chunks->getChunk(chunk->x+ox, chunk->z+oz);
|
||||||
if (other != nullptr && other->isReady()) surrounding++;
|
if (other != nullptr) surrounding++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk->surrounding = 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;
|
continue;
|
||||||
}
|
}
|
||||||
int lx = x - w / 2;
|
int lx = x - w / 2;
|
||||||
@ -81,200 +72,29 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int index = nearZ * w + nearX;
|
int index = nearZ * w + nearX;
|
||||||
Chunk* chunk = chunks->chunks[index];
|
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||||
if (chunk != nullptr)
|
if (chunk != nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ChunksLoader* freeLoader = getFreeLoader();
|
chunk = shared_ptr<Chunk>(new Chunk(nearX+ox, nearZ+oz));
|
||||||
if (freeLoader == nullptr)
|
level->chunksStorage->store(chunk);
|
||||||
return false;
|
if (worldFiles->getChunk(chunk->x, chunk->z, (ubyte*)chunk->voxels))
|
||||||
|
|
||||||
chunk = new Chunk(nearX+ox, nearZ+oz);
|
|
||||||
if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels))
|
|
||||||
chunk->setLoaded(true);
|
chunk->setLoaded(true);
|
||||||
|
|
||||||
chunks->putChunk(chunk);
|
chunks->putChunk(chunk);
|
||||||
|
|
||||||
Chunk* closes[9];
|
if (!chunk->isLoaded()) {
|
||||||
for (int i = 0; i < 9; i++)
|
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, level->world->seed);
|
||||||
closes[i] = nullptr;
|
chunk->setUnsaved(true);
|
||||||
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);
|
|
||||||
|
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);
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
chunk->setModified(false);
|
|
||||||
chunk->renderData.vertices = (float*)1;
|
|
||||||
freeLoader->render(chunk, (Chunk**)closes);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#ifndef VOXELS_CHUNKSCONTROLLER_H_
|
#ifndef VOXELS_CHUNKSCONTROLLER_H_
|
||||||
#define VOXELS_CHUNKSCONTROLLER_H_
|
#define VOXELS_CHUNKSCONTROLLER_H_
|
||||||
|
|
||||||
class World;
|
class Level;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class Lighting;
|
class Lighting;
|
||||||
class WorldFiles;
|
class WorldFiles;
|
||||||
@ -10,19 +10,14 @@ class ChunksLoader;
|
|||||||
|
|
||||||
class ChunksController {
|
class ChunksController {
|
||||||
private:
|
private:
|
||||||
|
Level* level;
|
||||||
Chunks* chunks;
|
Chunks* chunks;
|
||||||
Lighting* lighting;
|
Lighting* lighting;
|
||||||
ChunksLoader** loaders;
|
|
||||||
int loadersCount;
|
|
||||||
public:
|
public:
|
||||||
ChunksController(World* world, Chunks* chunks, Lighting* lighting);
|
ChunksController(Level* level, Chunks* chunks, Lighting* lighting);
|
||||||
~ChunksController();
|
~ChunksController();
|
||||||
|
|
||||||
ChunksLoader* getFreeLoader();
|
|
||||||
int countFreeLoaders();
|
|
||||||
bool loadVisible(WorldFiles* worldFiles);
|
bool loadVisible(WorldFiles* worldFiles);
|
||||||
void calculateLights();
|
|
||||||
bool _buildMeshes();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* VOXELS_CHUNKSCONTROLLER_H_ */
|
#endif /* VOXELS_CHUNKSCONTROLLER_H_ */
|
||||||
|
|||||||
93
src/voxels/ChunksStorage.cpp
Normal file
93
src/voxels/ChunksStorage.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include "ChunksStorage.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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> chunk) {
|
||||||
|
chunksMap[ivec2(chunk->x, chunk->z)] = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Chunk> 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>& 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)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/voxels/ChunksStorage.h
Normal file
29
src/voxels/ChunksStorage.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef VOXELS_CHUNKSSTORAGE_H_
|
||||||
|
#define VOXELS_CHUNKSSTORAGE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "voxel.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include "glm/gtx/hash.hpp"
|
||||||
|
|
||||||
|
class Chunk;
|
||||||
|
class VoxelsVolume;
|
||||||
|
|
||||||
|
class ChunksStorage {
|
||||||
|
std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> chunksMap;
|
||||||
|
public:
|
||||||
|
ChunksStorage();
|
||||||
|
virtual ~ChunksStorage();
|
||||||
|
|
||||||
|
std::shared_ptr<Chunk> get(int x, int y) const;
|
||||||
|
void store(std::shared_ptr<Chunk> chunk);
|
||||||
|
void getVoxels(VoxelsVolume* volume) const;
|
||||||
|
|
||||||
|
light_t getLight(int x, int y, int z, ubyte channel) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VOXELS_CHUNKSSTORAGE_H_
|
||||||
30
src/voxels/VoxelsVolume.cpp
Normal file
30
src/voxels/VoxelsVolume.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
67
src/voxels/VoxelsVolume.h
Normal file
67
src/voxels/VoxelsVolume.h
Normal file
@ -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_
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#ifndef VOXELS_VOXEL_H_
|
#ifndef VOXELS_VOXEL_H_
|
||||||
#define VOXELS_VOXEL_H_
|
#define VOXELS_VOXEL_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct voxel {
|
struct voxel {
|
||||||
uint8_t id;
|
blockid_t id;
|
||||||
uint8_t states;
|
uint8_t states;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
43
src/voxmaths.h
Normal file
43
src/voxmaths.h
Normal file
@ -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_
|
||||||
@ -13,60 +13,15 @@ float Events::y = 0.0f;
|
|||||||
bool Events::_cursor_locked = false;
|
bool Events::_cursor_locked = false;
|
||||||
bool Events::_cursor_started = 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(){
|
int Events::initialize(){
|
||||||
GLFWwindow* window = Window::window;
|
|
||||||
_keys = new bool[1032];
|
_keys = new bool[1032];
|
||||||
_frames = new uint[1032];
|
_frames = new uint[1032];
|
||||||
|
|
||||||
memset(_keys, false, 1032*sizeof(bool));
|
memset(_keys, false, 1032*sizeof(bool));
|
||||||
memset(_frames, 0, 1032*sizeof(uint));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,4 +30,6 @@ public:
|
|||||||
static void toggleCursor();
|
static void toggleCursor();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define _MOUSE_BUTTONS 1024
|
||||||
|
|
||||||
#endif /* WINDOW_EVENTS_H_ */
|
#endif /* WINDOW_EVENTS_H_ */
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
#include "Events.h"
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
@ -7,13 +8,53 @@ GLFWwindow* Window::window = nullptr;
|
|||||||
uint Window::width = 0;
|
uint Window::width = 0;
|
||||||
uint Window::height = 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();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
|
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
|
||||||
glfwWindowHint(GLFW_SAMPLES, 16);
|
glfwWindowHint(GLFW_SAMPLES, samples);
|
||||||
|
|
||||||
window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||||
if (window == nullptr){
|
if (window == nullptr){
|
||||||
@ -35,11 +76,16 @@ int Window::initialize(uint width, uint height, const char* title){
|
|||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
// glDisable(GL_MULTISAMPLE);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
Window::width = width;
|
Window::width = width;
|
||||||
Window::height = height;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@
|
|||||||
class GLFWwindow;
|
class GLFWwindow;
|
||||||
|
|
||||||
class Window {
|
class Window {
|
||||||
|
static GLFWwindow* window;
|
||||||
public:
|
public:
|
||||||
static uint width;
|
static uint width;
|
||||||
static uint height;
|
static uint height;
|
||||||
static GLFWwindow* window; // не лучшее решение делать window публичным
|
static int initialize(uint width, uint height, const char* title, int samples);
|
||||||
static int initialize(uint width, uint height, const char* title);
|
|
||||||
static void terminate();
|
static void terminate();
|
||||||
|
|
||||||
static void viewport(int x, int y, int width, int height);
|
static void viewport(int x, int y, int width, int height);
|
||||||
|
|||||||
@ -3,18 +3,20 @@
|
|||||||
#include "../lighting/Lighting.h"
|
#include "../lighting/Lighting.h"
|
||||||
#include "../voxels/Chunks.h"
|
#include "../voxels/Chunks.h"
|
||||||
#include "../voxels/ChunksController.h"
|
#include "../voxels/ChunksController.h"
|
||||||
|
#include "../voxels/ChunksStorage.h"
|
||||||
#include "../player_control.h"
|
#include "../player_control.h"
|
||||||
#include "../physics/Hitbox.h"
|
#include "../physics/Hitbox.h"
|
||||||
#include "../physics/PhysicsSolver.h"
|
#include "../physics/PhysicsSolver.h"
|
||||||
#include "../objects/Player.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),
|
world(world),
|
||||||
player(player),
|
player(player),
|
||||||
chunks(chunks),
|
chunks(chunks),
|
||||||
|
chunksStorage(chunksStorage),
|
||||||
physics(physics) {
|
physics(physics) {
|
||||||
lighting = new Lighting(chunks);
|
lighting = new Lighting(chunks);
|
||||||
chunksController = new ChunksController(world, chunks, lighting);
|
chunksController = new ChunksController(this, chunks, lighting);
|
||||||
playerController = new PlayerController(this);
|
playerController = new PlayerController(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ Level::~Level(){
|
|||||||
delete player;
|
delete player;
|
||||||
delete lighting;
|
delete lighting;
|
||||||
delete chunksController;
|
delete chunksController;
|
||||||
|
delete chunksStorage;
|
||||||
delete playerController;
|
delete playerController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ class Chunks;
|
|||||||
class Lighting;
|
class Lighting;
|
||||||
class PhysicsSolver;
|
class PhysicsSolver;
|
||||||
class ChunksController;
|
class ChunksController;
|
||||||
|
class ChunksStorage;
|
||||||
class PlayerController;
|
class PlayerController;
|
||||||
|
|
||||||
class Level {
|
class Level {
|
||||||
@ -14,11 +15,12 @@ public:
|
|||||||
World* world;
|
World* world;
|
||||||
Player* player;
|
Player* player;
|
||||||
Chunks* chunks;
|
Chunks* chunks;
|
||||||
|
ChunksStorage* chunksStorage;
|
||||||
PhysicsSolver* physics;
|
PhysicsSolver* physics;
|
||||||
Lighting* lighting;
|
Lighting* lighting;
|
||||||
ChunksController* chunksController;
|
ChunksController* chunksController;
|
||||||
PlayerController* playerController;
|
PlayerController* playerController;
|
||||||
Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics);
|
Level(World* world, Player* player, Chunks* chunks, ChunksStorage* chunksStorage, PhysicsSolver* physics);
|
||||||
~Level();
|
~Level();
|
||||||
|
|
||||||
void update(float delta, bool interactions);
|
void update(float delta, bool interactions);
|
||||||
|
|||||||
@ -1,13 +1,18 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Level.h"
|
||||||
#include "../files/WorldFiles.h"
|
#include "../files/WorldFiles.h"
|
||||||
#include "../voxels/Chunk.h"
|
#include "../voxels/Chunk.h"
|
||||||
#include "../voxels/Chunks.h"
|
#include "../voxels/Chunks.h"
|
||||||
#include "Level.h"
|
#include "../voxels/ChunksStorage.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../physics/PhysicsSolver.h"
|
#include "../physics/PhysicsSolver.h"
|
||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
World::World(std::string name, std::string directory, int seed) : name(name), seed(seed) {
|
World::World(std::string name, std::string directory, int seed) : name(name), seed(seed) {
|
||||||
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_VOL * 2 + 8));
|
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_VOL * 2 + 8));
|
||||||
}
|
}
|
||||||
@ -20,10 +25,10 @@ void World::write(Level* level) {
|
|||||||
Chunks* chunks = level->chunks;
|
Chunks* chunks = level->chunks;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < chunks->volume; i++) {
|
for (unsigned int i = 0; i < chunks->volume; i++) {
|
||||||
Chunk* chunk = chunks->chunks[i];
|
shared_ptr<Chunk> chunk = chunks->chunks[i];
|
||||||
if (chunk == nullptr || !chunk->isUnsaved())
|
if (chunk == nullptr || !chunk->isUnsaved())
|
||||||
continue;
|
continue;
|
||||||
wfile->put((const char*)chunk->voxels, chunk->x, chunk->z);
|
wfile->put((const ubyte*)chunk->voxels, chunk->x, chunk->z);
|
||||||
}
|
}
|
||||||
|
|
||||||
wfile->write();
|
wfile->write();
|
||||||
@ -31,7 +36,8 @@ void World::write(Level* level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Level* World::loadLevel(Player* player) {
|
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);
|
wfile->readPlayer(player);
|
||||||
|
|
||||||
Camera* camera = player->camera;
|
Camera* camera = player->camera;
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
#include "world_render.h"
|
#include "world_render.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "graphics/VoxelRenderer.h"
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "graphics/ChunksRenderer.h"
|
||||||
#include "window/Window.h"
|
#include "window/Window.h"
|
||||||
#include "window/Camera.h"
|
#include "window/Camera.h"
|
||||||
#include "graphics/Mesh.h"
|
#include "graphics/Mesh.h"
|
||||||
@ -20,13 +21,15 @@
|
|||||||
#include "Assets.h"
|
#include "Assets.h"
|
||||||
#include "player_control.h"
|
#include "player_control.h"
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
float _camera_cx;
|
float _camera_cx;
|
||||||
float _camera_cz;
|
float _camera_cz;
|
||||||
|
|
||||||
WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) {
|
WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) {
|
||||||
lineBatch = new LineBatch(4096);
|
lineBatch = new LineBatch(4096);
|
||||||
batch3d = new Batch3D(1024);
|
batch3d = new Batch3D(1024);
|
||||||
renderer = new VoxelRenderer();
|
renderer = new ChunksRenderer(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRenderer::~WorldRenderer() {
|
WorldRenderer::~WorldRenderer() {
|
||||||
@ -38,15 +41,17 @@ WorldRenderer::~WorldRenderer() {
|
|||||||
Chunks* _chunks = nullptr;
|
Chunks* _chunks = nullptr;
|
||||||
|
|
||||||
bool chunks_distance_compare(size_t i, size_t j) {
|
bool chunks_distance_compare(size_t i, size_t j) {
|
||||||
Chunk* a = _chunks->chunks[i];
|
shared_ptr<Chunk> a = _chunks->chunks[i];
|
||||||
Chunk* b = _chunks->chunks[j];
|
shared_ptr<Chunk> b = _chunks->chunks[j];
|
||||||
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz) >
|
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz) >
|
||||||
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
|
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
||||||
Chunk* chunk = level->chunks->chunks[index];
|
shared_ptr<Chunk> chunk = level->chunks->chunks[index];
|
||||||
Mesh* mesh = level->chunks->meshes[index];
|
if (!chunk->isLighted())
|
||||||
|
return false;
|
||||||
|
shared_ptr<Mesh> mesh = renderer->getOrRender(chunk.get());
|
||||||
if (mesh == nullptr)
|
if (mesh == nullptr)
|
||||||
return false;
|
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);
|
shader->uniformMatrix("u_model", model);
|
||||||
glDisable(GL_MULTISAMPLE);
|
glDisable(GL_MULTISAMPLE);
|
||||||
mesh->draw(GL_TRIANGLES);
|
mesh->draw(GL_TRIANGLES);
|
||||||
@ -109,11 +114,10 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
|
|||||||
std::vector<size_t> indices;
|
std::vector<size_t> indices;
|
||||||
|
|
||||||
for (size_t i = 0; i < chunks->volume; i++){
|
for (size_t i = 0; i < chunks->volume; i++){
|
||||||
Chunk* chunk = chunks->chunks[i];
|
shared_ptr<Chunk> chunk = chunks->chunks[i];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
if (chunks->meshes[i] != nullptr)
|
indices.push_back(i);
|
||||||
indices.push_back(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float px = camera->position.x / (float)CHUNK_W;
|
float px = camera->position.x / (float)CHUNK_W;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class Camera;
|
|||||||
class Assets;
|
class Assets;
|
||||||
class LineBatch;
|
class LineBatch;
|
||||||
class Batch3D;
|
class Batch3D;
|
||||||
class VoxelRenderer;
|
class ChunksRenderer;
|
||||||
class Shader;
|
class Shader;
|
||||||
class Texture;
|
class Texture;
|
||||||
class Framebuffer;
|
class Framebuffer;
|
||||||
@ -28,8 +28,8 @@ class WorldRenderer {
|
|||||||
Level* level;
|
Level* level;
|
||||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
|
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
|
||||||
public:
|
public:
|
||||||
VoxelRenderer *renderer;
|
ChunksRenderer* renderer;
|
||||||
LineBatch *lineBatch;
|
LineBatch* lineBatch;
|
||||||
|
|
||||||
WorldRenderer(Level* level, Assets* assets);
|
WorldRenderer(Level* level, Assets* assets);
|
||||||
~WorldRenderer();
|
~WorldRenderer();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user