mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-04 18:41:51 +00:00
commit
3542a00445
43 changed files with 620 additions and 449 deletions
|
|
@ -30,8 +30,12 @@ endif()
|
|||
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MT /O2)
|
||||
if((CMAKE_BUILD_TYPE EQUAL "Release") OR (CMAKE_BUILD_TYPE EQUAL "RelWithDebInfo"))
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MT /O2)
|
||||
else()
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /source-charset:UTF-8")
|
||||
else()
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -lstdc++fs
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 124 KiB |
|
|
@ -12,9 +12,6 @@
|
|||
"ru_RU": {
|
||||
"name": "Русский"
|
||||
},
|
||||
"su_SU": {
|
||||
"name": "Советский"
|
||||
},
|
||||
"uk_UA": {
|
||||
"name": "Українська"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
# Общее
|
||||
Yes=Да
|
||||
No=Нет
|
||||
Ok = Понятно
|
||||
Cancel=Отмена
|
||||
Back = Обратно
|
||||
Continue=Продолжить
|
||||
|
||||
error.pack-not-found=Не удалось найти пакет
|
||||
|
||||
# Меню
|
||||
menu.New World = Новый Мир
|
||||
menu.Quit=Выход
|
||||
menu.Continue=Продолжить
|
||||
menu.Save and Quit to Menu=Сохранить и Вернуться на Главную
|
||||
menu.missing-content=Отсутствует некоторое наполнение!
|
||||
menu.Controls=Управление
|
||||
menu.Back to Main Menu=Вернуться на Главную
|
||||
menu.Settings=Настройки
|
||||
menu.Content=Наполнение
|
||||
menu.Seed=Семя
|
||||
menu.Name=Название
|
||||
menu.Create World=Создать Мир
|
||||
|
||||
world.convert-request=Есть изменения в индексах! Преобразовать мир?
|
||||
|
||||
# Настройки
|
||||
settings.Load Distance=Дальность Загрузки
|
||||
settings.Load Speed=Скорость Загрузки
|
||||
settings.Fog Curve=Искривление Тумана
|
||||
settings.Backlight=Подсветка
|
||||
settings.V-Sync=Вертикальная Синхронизация
|
||||
|
||||
settings.FOV=Поле Зрения
|
||||
settings.Mouse Sensitivity=Чувствительность Мыши
|
||||
settings.Language=Язык
|
||||
|
||||
# Управление
|
||||
movement.forward=Вперёд
|
||||
movement.back=Назад
|
||||
movement.left=Влево
|
||||
movement.right=Вправо
|
||||
movement.jump=Прыжок
|
||||
movement.sprint=Ускорение
|
||||
movement.crouch=Красться
|
||||
movement.cheat=Чит
|
||||
hud.inventory=Инвентарь
|
||||
player.pick=Подобрать Блок
|
||||
player.attack=Атаковать / Сломать
|
||||
player.build=Поставить Блок
|
||||
player.flight=Полёт
|
||||
camera.zoom=Приближение
|
||||
camera.mode=Сменить Режим Камеры
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
#include "../graphics/Texture.h"
|
||||
#include "../files/files.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
#ifndef _WIN32
|
||||
#define LIBPNG
|
||||
#endif
|
||||
|
|
@ -18,10 +16,8 @@ using std::unique_ptr;
|
|||
#include <png.h>
|
||||
|
||||
// returns 0 if all-right, 1 otherwise
|
||||
int _png_write(const char* filename, uint width, uint height, const u_char8* data, bool alpha) {
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
uint pixsize = alpha ? 4 : 3;
|
||||
int _png_write(const char* filename, u_int width, u_int height, const u_char8* data, bool alpha) {
|
||||
u_int pixsize = alpha ? 4 : 3;
|
||||
|
||||
// Open file for writing (binary mode)
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
|
|
@ -32,7 +28,7 @@ int _png_write(const char* filename, uint width, uint height, const u_char8* dat
|
|||
}
|
||||
|
||||
// Initialize write structure
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (png_ptr == nullptr) {
|
||||
fprintf(stderr, "Could not allocate write struct\n");
|
||||
fclose(fp);
|
||||
|
|
@ -41,7 +37,7 @@ int _png_write(const char* filename, uint width, uint height, const u_char8* dat
|
|||
}
|
||||
|
||||
// Initialize info structure
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
fprintf(stderr, "Could not allocate info struct\n");
|
||||
fclose(fp);
|
||||
|
|
@ -73,7 +69,7 @@ int _png_write(const char* filename, uint width, uint height, const u_char8* dat
|
|||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
unique_ptr<png_byte[]> row(new png_byte[pixsize * width]);
|
||||
std::unique_ptr<png_byte[]> row(new png_byte[pixsize * width]);
|
||||
|
||||
// Write image data
|
||||
for (uint y = 0; y < height; y++) {
|
||||
|
|
@ -95,15 +91,11 @@ int _png_write(const char* filename, uint width, uint height, const u_char8* dat
|
|||
}
|
||||
|
||||
ImageData* _png_load(const char* file){
|
||||
FILE *f = nullptr;
|
||||
bool is_png = false;
|
||||
int bit_depth, color_type, row_bytes;
|
||||
png_infop info_ptr, end_info;
|
||||
png_uint_32 t_width, t_height;
|
||||
png_byte header[8], *image_data;
|
||||
png_bytepp row_pointers;
|
||||
png_structp png_ptr;
|
||||
png_byte header[8];
|
||||
|
||||
FILE *f = nullptr;
|
||||
if ((f = fopen(file, "r")) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -112,28 +104,28 @@ ImageData* _png_load(const char* file){
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
is_png = (png_sig_cmp(header, 0, 8) == 0);
|
||||
bool is_png = (png_sig_cmp(header, 0, 8) == 0);
|
||||
if (!is_png) {
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
|
||||
png_struct* png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
|
||||
nullptr, nullptr);
|
||||
if (png_ptr == nullptr) {
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
png_info* info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
png_destroy_read_struct( &png_ptr, (png_infopp) nullptr,
|
||||
(png_infopp) nullptr );
|
||||
png_destroy_read_struct(&png_ptr, (png_info**) nullptr,
|
||||
(png_info**) nullptr);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
end_info = png_create_info_struct(png_ptr);
|
||||
png_info* end_info = png_create_info_struct(png_ptr);
|
||||
if (end_info == nullptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) nullptr,
|
||||
(png_infopp) nullptr);
|
||||
png_destroy_read_struct(&png_ptr, (png_info**) nullptr,
|
||||
(png_info**) nullptr);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -144,33 +136,34 @@ ImageData* _png_load(const char* file){
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
png_init_io( png_ptr, f );
|
||||
png_set_sig_bytes( png_ptr, 8 );
|
||||
png_read_info( png_ptr, info_ptr );
|
||||
png_get_IHDR( png_ptr, info_ptr, &t_width, &t_height, &bit_depth,
|
||||
&color_type, nullptr, nullptr, nullptr );
|
||||
png_read_update_info( png_ptr, info_ptr );
|
||||
row_bytes = png_get_rowbytes( png_ptr, info_ptr );
|
||||
image_data = new png_byte[row_bytes * t_height];
|
||||
png_init_io(png_ptr, f);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_get_IHDR(png_ptr, info_ptr, &t_width, &t_height, &bit_depth,
|
||||
&color_type, nullptr, nullptr, nullptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
std::unique_ptr<png_byte[]> image_data (new png_byte[row_bytes * t_height]);
|
||||
if (!image_data) {
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
row_pointers = (png_bytepp) malloc( t_height * sizeof(png_bytep) );
|
||||
if ( row_pointers == nullptr ) {
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
delete[] image_data;
|
||||
|
||||
std::unique_ptr<png_byte*[]> row_pointers (new png_byte*[t_height]);
|
||||
if (row_pointers == nullptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
for (uint i = 0; i < t_height; ++i ) {
|
||||
row_pointers[t_height - 1 - i] = image_data + i * row_bytes;
|
||||
row_pointers[t_height - 1 - i] = image_data.get() + i * row_bytes;
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_read_image(png_ptr, row_pointers.get());
|
||||
|
||||
ImageFormat format;
|
||||
switch ( png_get_color_type( png_ptr, info_ptr ) ) {
|
||||
switch (png_get_color_type(png_ptr, info_ptr)) {
|
||||
case PNG_COLOR_TYPE_RGBA:
|
||||
format = ImageFormat::rgba8888;
|
||||
break;
|
||||
|
|
@ -178,18 +171,15 @@ ImageData* _png_load(const char* file){
|
|||
format = ImageFormat::rgb888;
|
||||
break;
|
||||
default:
|
||||
printf( "Color type %d not supported!\n",
|
||||
png_get_color_type( png_ptr, info_ptr ) );
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
delete[] image_data;
|
||||
free( row_pointers );
|
||||
printf("Color type %d not supported!\n",
|
||||
png_get_color_type(png_ptr, info_ptr));
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
ImageData* image = new ImageData(format, t_width, t_height, (void*)image_data);
|
||||
ImageData* image = new ImageData(format, t_width, t_height, (void*)image_data.release());
|
||||
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
|
||||
free( row_pointers );
|
||||
fclose( f );
|
||||
fclose(f);
|
||||
return image;
|
||||
}
|
||||
#else
|
||||
|
|
@ -335,7 +325,7 @@ ImageData* _png_load(const char* file){
|
|||
flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j];
|
||||
}
|
||||
}
|
||||
delete[] out; // <- finally delete out
|
||||
delete[] out; // <- finally delete out // no, delete spng usage
|
||||
|
||||
ImageData* image = new ImageData(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped);
|
||||
|
||||
|
|
@ -356,7 +346,7 @@ ImageData* png::load_image(std::string filename) {
|
|||
}
|
||||
|
||||
Texture* png::load_texture(std::string filename) {
|
||||
unique_ptr<ImageData> image (_png_load(filename.c_str()));
|
||||
std::unique_ptr<ImageData> image (_png_load(filename.c_str()));
|
||||
if (image == nullptr){
|
||||
std::cerr << "Could not load texture " << filename << std::endl;
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -5,14 +5,17 @@
|
|||
#include "typedefs.h"
|
||||
|
||||
const int ENGINE_VERSION_MAJOR = 0;
|
||||
const int ENGINE_VERSION_MINOR = 16;
|
||||
const int ENGINE_VERSION_MINOR = 17;
|
||||
|
||||
const int CHUNK_W = 16;
|
||||
const int CHUNK_H = 256;
|
||||
const int CHUNK_D = 16;
|
||||
|
||||
const uint VOXEL_USER_BITS = 8;
|
||||
constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS;
|
||||
|
||||
/* Chunk volume (count of voxels per Chunk) */
|
||||
const int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
||||
constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
||||
|
||||
/* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */
|
||||
const blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
|
||||
|
|
|
|||
|
|
@ -8,18 +8,15 @@
|
|||
#include "../content/ContentLUT.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using fs::path;
|
||||
|
||||
WorldConverter::WorldConverter(path folder,
|
||||
WorldConverter::WorldConverter(fs::path folder,
|
||||
const Content* content,
|
||||
const ContentLUT* lut)
|
||||
: lut(lut), content(content) {
|
||||
DebugSettings settings;
|
||||
wfile = new WorldFiles(folder, settings);
|
||||
|
||||
path regionsFolder = wfile->getRegionsFolder();
|
||||
fs::path regionsFolder = wfile->getRegionsFolder();
|
||||
if (!fs::is_directory(regionsFolder)) {
|
||||
std::cerr << "nothing to convert" << std::endl;
|
||||
return;
|
||||
|
|
@ -41,13 +38,13 @@ void WorldConverter::convertNext() {
|
|||
if (!hasNext()) {
|
||||
throw std::runtime_error("no more regions to convert");
|
||||
}
|
||||
path regfile = regions.front();
|
||||
fs::path regfile = regions.front();
|
||||
regions.pop();
|
||||
if (!fs::is_regular_file(regfile))
|
||||
return;
|
||||
int x, y;
|
||||
string name = regfile.stem().string();
|
||||
if (!WorldFiles::parseRegionFilename(name, x, y)) {
|
||||
int x, z;
|
||||
std::string name = regfile.stem().string();
|
||||
if (!WorldFiles::parseRegionFilename(name, x, z)) {
|
||||
std::cerr << "could not parse name " << name << std::endl;
|
||||
return;
|
||||
}
|
||||
|
|
@ -55,11 +52,16 @@ void WorldConverter::convertNext() {
|
|||
for (uint cz = 0; cz < REGION_SIZE; cz++) {
|
||||
for (uint cx = 0; cx < REGION_SIZE; cx++) {
|
||||
int gx = cx + x * REGION_SIZE;
|
||||
int gz = cz + y * REGION_SIZE;
|
||||
unique_ptr<u_char8[]> data (wfile->getChunk(gx, gz));
|
||||
int gz = cz + z * REGION_SIZE;
|
||||
std::unique_ptr<u_char8[]> data (wfile->getChunk(gx, gz));
|
||||
if (data == nullptr)
|
||||
continue;
|
||||
Chunk::convert(data.get(), lut);
|
||||
if (wfile->getVoxelRegionVersion(x, z) != REGION_FORMAT_VERSION) {
|
||||
Chunk::fromOld(data.get());
|
||||
}
|
||||
if (lut) {
|
||||
Chunk::convert(data.get(), lut);
|
||||
}
|
||||
wfile->put(gx, gz, data.get());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,27 @@
|
|||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
regfile::regfile(fs::path filename) : file(filename) {
|
||||
if (file.length() < REGION_HEADER_SIZE)
|
||||
throw std::runtime_error("incomplete region file header");
|
||||
char header[REGION_HEADER_SIZE];
|
||||
file.read(header, REGION_HEADER_SIZE);
|
||||
|
||||
// avoid of use strcmp_s
|
||||
if (std::string(header, strlen(REGION_FORMAT_MAGIC)) != REGION_FORMAT_MAGIC) {
|
||||
throw std::runtime_error("invalid region file magic number");
|
||||
}
|
||||
version = header[8];
|
||||
if (uint(version) > REGION_FORMAT_VERSION) {
|
||||
throw illegal_region_format(
|
||||
"region format "+std::to_string(version)+" is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
WorldRegion::WorldRegion() {
|
||||
chunksData = new u_char8*[REGION_CHUNKS_COUNT]{};
|
||||
sizes = new uint32_t[REGION_CHUNKS_COUNT]{};
|
||||
|
|
@ -112,6 +130,31 @@ u_char8* WorldFiles::decompress(const u_char8* src, size_t srclen, size_t dstlen
|
|||
return decompressed;
|
||||
}
|
||||
|
||||
int WorldFiles::getVoxelRegionVersion(int x, int z) {
|
||||
regfile* rf = getRegFile(glm::ivec3(x, z, REGION_LAYER_VOXELS), getRegionsFolder());
|
||||
if (rf == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return rf->version;
|
||||
}
|
||||
|
||||
int WorldFiles::getVoxelRegionsVersion() {
|
||||
fs::path regionsFolder = getRegionsFolder();
|
||||
if (!fs::is_directory(regionsFolder)) {
|
||||
return REGION_FORMAT_VERSION;
|
||||
}
|
||||
for (auto file : fs::directory_iterator(regionsFolder)) {
|
||||
int x;
|
||||
int z;
|
||||
if (!parseRegionFilename(file.path().stem().string(), x, z)) {
|
||||
continue;
|
||||
}
|
||||
regfile* rf = getRegFile(glm::ivec3(x, z, REGION_LAYER_VOXELS), regionsFolder);
|
||||
return rf->version;
|
||||
}
|
||||
return REGION_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compress and store chunk voxels data in region
|
||||
* @param x chunk.x
|
||||
|
|
@ -172,8 +215,7 @@ fs::path WorldFiles::getLightsFolder() const {
|
|||
}
|
||||
|
||||
fs::path WorldFiles::getRegionFilename(int x, int z) const {
|
||||
std::string filename = std::to_string(x) + "_" + std::to_string(z) + ".bin";
|
||||
return fs::path(filename);
|
||||
return fs::path(std::to_string(x) + "_" + std::to_string(z) + ".bin");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -236,7 +278,6 @@ u_char8* WorldFiles::getData(regionsmap& regions, const fs::path& folder,
|
|||
int localZ = z - (regionZ * REGION_SIZE);
|
||||
|
||||
WorldRegion* region = getOrCreateRegion(regions, regionX, regionZ);
|
||||
|
||||
u_char8* data = region->getChunkData(localX, localZ);
|
||||
if (data == nullptr) {
|
||||
uint32_t size;
|
||||
|
|
@ -252,7 +293,8 @@ u_char8* WorldFiles::getData(regionsmap& regions, const fs::path& folder,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
files::rafile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder) {
|
||||
|
||||
regfile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder) {
|
||||
const auto found = openRegFiles.find(coord);
|
||||
if (found != openRegFiles.end()) {
|
||||
return found->second.get();
|
||||
|
|
@ -266,7 +308,7 @@ files::rafile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder)
|
|||
if (!fs::is_regular_file(filename)) {
|
||||
return nullptr;
|
||||
}
|
||||
openRegFiles[coord] = std::make_unique<files::rafile>(filename);
|
||||
openRegFiles[coord] = std::make_unique<regfile>(filename);
|
||||
return openRegFiles[coord].get();
|
||||
}
|
||||
|
||||
|
|
@ -285,26 +327,27 @@ u_char8* WorldFiles::readChunkData(int x,
|
|||
int chunkIndex = localZ * REGION_SIZE + localX;
|
||||
|
||||
glm::ivec3 coord(regionX, regionZ, layer);
|
||||
files::rafile* file = WorldFiles::getRegFile(coord, folder);
|
||||
if (file == nullptr) {
|
||||
regfile* rfile = WorldFiles::getRegFile(coord, folder);
|
||||
if (rfile == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
files::rafile& file = rfile->file;
|
||||
|
||||
size_t file_size = file->length();
|
||||
size_t file_size = file.length();
|
||||
size_t table_offset = file_size - REGION_CHUNKS_COUNT * 4;
|
||||
|
||||
uint32_t offset;
|
||||
file->seekg(table_offset + chunkIndex * 4);
|
||||
file->read((char*)(&offset), 4);
|
||||
file.seekg(table_offset + chunkIndex * 4);
|
||||
file.read((char*)(&offset), 4);
|
||||
offset = dataio::read_int32_big((const u_char8*)(&offset), 0);
|
||||
if (offset == 0){
|
||||
return nullptr;
|
||||
}
|
||||
file->seekg(offset);
|
||||
file->read((char*)(&offset), 4);
|
||||
file.seekg(offset);
|
||||
file.read((char*)(&offset), 4);
|
||||
length = dataio::read_int32_big((const u_char8*)(&offset), 0);
|
||||
u_char8* data = new u_char8[length];
|
||||
file->read((char*)data, length);
|
||||
file.read((char*)data, length);
|
||||
if (data == nullptr) {
|
||||
std::cerr << "ERROR: failed to read data of chunk x("<< x <<"), z("<< z <<")" << std::endl;
|
||||
}
|
||||
|
|
@ -343,13 +386,13 @@ void WorldFiles::writeRegion(int x, int z, WorldRegion* entry, fs::path folder,
|
|||
openRegFiles.erase(regcoord);
|
||||
}
|
||||
|
||||
char header[10] = REGION_FORMAT_MAGIC;
|
||||
char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC;
|
||||
header[8] = REGION_FORMAT_VERSION;
|
||||
header[9] = 0; // flags
|
||||
std::ofstream file(filename, std::ios::out | std::ios::binary);
|
||||
file.write(header, 10);
|
||||
file.write(header, REGION_HEADER_SIZE);
|
||||
|
||||
size_t offset = 10;
|
||||
size_t offset = REGION_HEADER_SIZE;
|
||||
char intbuf[4]{};
|
||||
uint offsets[REGION_CHUNKS_COUNT]{};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,12 +15,13 @@
|
|||
#include "../typedefs.h"
|
||||
#include "../settings.h"
|
||||
|
||||
const uint REGION_HEADER_SIZE = 10;
|
||||
const uint REGION_LAYER_VOXELS = 0;
|
||||
const uint REGION_LAYER_LIGHTS = 1;
|
||||
const uint REGION_SIZE_BIT = 5;
|
||||
const uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
||||
const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE));
|
||||
const uint REGION_FORMAT_VERSION = 1;
|
||||
const uint REGION_FORMAT_VERSION = 2;
|
||||
const uint WORLD_FORMAT_VERSION = 1;
|
||||
const uint MAX_OPEN_REGION_FILES = 16;
|
||||
|
||||
|
|
@ -33,6 +34,12 @@ class Content;
|
|||
class ContentIndices;
|
||||
class World;
|
||||
|
||||
class illegal_region_format : public std::runtime_error {
|
||||
public:
|
||||
illegal_region_format(const std::string& message)
|
||||
: std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class WorldRegion {
|
||||
u_char8** chunksData;
|
||||
uint32_t* sizes;
|
||||
|
|
@ -52,9 +59,16 @@ public:
|
|||
uint32_t* getSizes() const;
|
||||
};
|
||||
|
||||
struct regfile {
|
||||
files::rafile file;
|
||||
int version;
|
||||
|
||||
regfile(std::filesystem::path filename);
|
||||
};
|
||||
|
||||
typedef std::unordered_map<glm::ivec2, std::unique_ptr<WorldRegion>> regionsmap;
|
||||
class WorldFiles {
|
||||
std::unordered_map<glm::ivec3, std::unique_ptr<files::rafile>> openRegFiles;
|
||||
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
||||
|
||||
void writeWorldInfo(const World* world);
|
||||
std::filesystem::path getLightsFolder() const;
|
||||
|
|
@ -98,8 +112,8 @@ class WorldFiles {
|
|||
const std::filesystem::path& folder,
|
||||
int x, int z, int layer);
|
||||
|
||||
files::rafile* getRegFile(glm::ivec3 coord,
|
||||
const std::filesystem::path& folder);
|
||||
regfile* getRegFile(glm::ivec3 coord,
|
||||
const std::filesystem::path& folder);
|
||||
public:
|
||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||
std::filesystem::path getRegionsFolder() const;
|
||||
|
|
@ -117,6 +131,9 @@ public:
|
|||
void put(Chunk* chunk);
|
||||
void put(int x, int z, const u_char8* voxelData);
|
||||
|
||||
int getVoxelRegionVersion(int x, int z);
|
||||
int getVoxelRegionsVersion();
|
||||
|
||||
u_char8* getChunk(int x, int z);
|
||||
light_t* getLights(int x, int z);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
using std::string;
|
||||
|
||||
void BinaryWriter::put(u_char8 b) {
|
||||
buffer.push_back(b);
|
||||
}
|
||||
|
|
@ -18,7 +16,7 @@ void BinaryWriter::putCStr(const char* str) {
|
|||
}
|
||||
}
|
||||
|
||||
void BinaryWriter::put(const string& s) {
|
||||
void BinaryWriter::put(const std::string& s) {
|
||||
size_t len = s.length();
|
||||
if (len > INT16_MAX) {
|
||||
throw std::domain_error("length > INT16_MAX");
|
||||
|
|
@ -27,7 +25,7 @@ void BinaryWriter::put(const string& s) {
|
|||
put((const u_char8*)s.data(), len);
|
||||
}
|
||||
|
||||
void BinaryWriter::putShortStr(const string& s) {
|
||||
void BinaryWriter::putShortStr(const std::string& s) {
|
||||
size_t len = s.length();
|
||||
if (len > 255) {
|
||||
throw std::domain_error("length > 255");
|
||||
|
|
@ -144,22 +142,22 @@ float BinaryReader::getFloat32() {
|
|||
return value.valfloat;
|
||||
}
|
||||
|
||||
string BinaryReader::getString() {
|
||||
std::string BinaryReader::getString() {
|
||||
uint16_t length = (uint16_t)getInt16();
|
||||
if (pos+length > size) {
|
||||
throw std::underflow_error("unexpected end");
|
||||
}
|
||||
pos += length;
|
||||
return string((const char*)(data+pos-length), length);
|
||||
return std::string((const char*)(data+pos-length), length);
|
||||
}
|
||||
|
||||
string BinaryReader::getShortString() {
|
||||
std::string BinaryReader::getShortString() {
|
||||
u_char8 length = get();
|
||||
if (pos+length > size) {
|
||||
throw std::underflow_error("unexpected end");
|
||||
}
|
||||
pos += length;
|
||||
return string((const char*)(data+pos-length), length);
|
||||
return std::string((const char*)(data+pos-length), length);
|
||||
}
|
||||
|
||||
bool BinaryReader::hasNext() const {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@
|
|||
#include "../coders/toml.h"
|
||||
#include "../coders/json.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
toml::Wrapper* create_wrapper(EngineSettings& settings) {
|
||||
std::unique_ptr<toml::Wrapper> wrapper (new toml::Wrapper());
|
||||
toml::Section& display = wrapper->add("display");
|
||||
|
|
@ -47,7 +45,7 @@ toml::Wrapper* create_wrapper(EngineSettings& settings) {
|
|||
return wrapper.release();
|
||||
}
|
||||
|
||||
string write_controls() {
|
||||
std::string write_controls() {
|
||||
json::JObject* obj = new json::JObject();
|
||||
for (auto& entry : Events::bindings) {
|
||||
const auto& binding = entry.second;
|
||||
|
|
@ -64,7 +62,7 @@ string write_controls() {
|
|||
return json::stringify(obj, true, " ");
|
||||
}
|
||||
|
||||
void load_controls(string filename, string source) {
|
||||
void load_controls(std::string filename, std::string source) {
|
||||
json::JObject* obj = json::parse(filename, source);
|
||||
for (auto& entry : Events::bindings) {
|
||||
auto& binding = entry.second;
|
||||
|
|
@ -73,7 +71,7 @@ void load_controls(string filename, string source) {
|
|||
if (jentry == nullptr)
|
||||
continue;
|
||||
inputtype type;
|
||||
string typestr;
|
||||
std::string typestr;
|
||||
jentry->str("type", typestr);
|
||||
|
||||
if (typestr == "keyboard") {
|
||||
|
|
@ -87,4 +85,4 @@ void load_controls(string filename, string source) {
|
|||
binding.type = type;
|
||||
jentry->num("code", binding.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
#include "../voxels/Block.h"
|
||||
#include "ContentGfxCache.h"
|
||||
|
||||
using glm::vec4;
|
||||
using glm::vec3;
|
||||
|
||||
BlocksPreview::BlocksPreview(Shader* shader,
|
||||
Atlas* atlas,
|
||||
const ContentGfxCache* cache)
|
||||
|
|
@ -31,19 +28,21 @@ void BlocksPreview::begin(const Viewport* viewport) {
|
|||
glm::ortho(0.0f, float(viewport->getWidth()),
|
||||
0.0f, float(viewport->getHeight()),
|
||||
-1000.0f, 1000.0f) *
|
||||
glm::lookAt(vec3(2, 2, 2), vec3(0.0f), vec3(0, 1, 0)));
|
||||
glm::lookAt(glm::vec3(2, 2, 2), glm::vec3(0.0f), glm::vec3(0, 1, 0)));
|
||||
atlas->getTexture()->bind();
|
||||
}
|
||||
|
||||
/* Draw one block preview at given screen position */
|
||||
void BlocksPreview::draw(const Block* def, int x, int y, int size, vec4 tint) {
|
||||
void BlocksPreview::draw(const Block* def, int x, int y, int size, glm::vec4 tint) {
|
||||
uint width = viewport->getWidth();
|
||||
uint height = viewport->getHeight();
|
||||
|
||||
y = height - y - 1;
|
||||
x += 2;
|
||||
y -= 35;
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), vec3(x/float(width) * 2, y/float(height) * 2, 0.0f)));
|
||||
|
||||
glm::vec3 offset (x/float(width) * 2, y/float(height) * 2, 0.0f);
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||
blockid_t id = def->rt.id;
|
||||
const UVRegion texfaces[6]{ cache->getRegion(id, 0), cache->getRegion(id, 1),
|
||||
cache->getRegion(id, 2), cache->getRegion(id, 3),
|
||||
|
|
@ -54,15 +53,20 @@ void BlocksPreview::draw(const Block* def, int x, int y, int size, vec4 tint) {
|
|||
// something went wrong...
|
||||
break;
|
||||
case BlockModel::block:
|
||||
batch->blockCube(vec3(size * 0.63f), texfaces, tint, !def->rt.emissive);
|
||||
batch->blockCube(glm::vec3(size * 0.63f), texfaces, tint, !def->rt.emissive);
|
||||
break;
|
||||
case BlockModel::aabb:
|
||||
batch->blockCube(def->hitbox.size() * vec3(size * 0.63f), texfaces, tint, !def->rt.emissive);
|
||||
batch->blockCube(def->hitbox.size() * glm::vec3(size * 0.63f),
|
||||
texfaces, tint, !def->rt.emissive);
|
||||
break;
|
||||
case BlockModel::xsprite: {
|
||||
//batch->xSprite(size, size, texfaces[0], tint, !def->rt.emissive);
|
||||
vec3 right = glm::normalize(vec3(1.f, 0.f, -1.f));
|
||||
batch->sprite(right*float(size)*0.43f+vec3(0, size*0.4f, 0), vec3(0.f, 1.f, 0.f), right, size*0.5f, size*0.6f, texfaces[0], tint);
|
||||
glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f));
|
||||
batch->sprite(right*float(size)*0.43f+glm::vec3(0, size*0.4f, 0),
|
||||
glm::vec3(0.f, 1.f, 0.f),
|
||||
right,
|
||||
size*0.5f, size*0.6f,
|
||||
texfaces[0],
|
||||
tint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#include "../graphics/Atlas.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) {
|
||||
const ContentIndices* contentIds = content->indices;
|
||||
sideregions = new UVRegion[contentIds->countBlockDefs() * 6];
|
||||
|
|
@ -17,7 +15,7 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) {
|
|||
for (uint i = 0; i < contentIds->countBlockDefs(); i++) {
|
||||
Block* def = contentIds->getBlockDef(i);
|
||||
for (uint side = 0; side < 6; side++) {
|
||||
string tex = def->textureFaces[side];
|
||||
std::string tex = def->textureFaces[side];
|
||||
if (atlas->has(tex)) {
|
||||
sideregions[i * 6 + side] = atlas->get(tex);
|
||||
} else {
|
||||
|
|
@ -28,7 +26,6 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) {
|
|||
}
|
||||
}
|
||||
|
||||
ContentGfxCache::~ContentGfxCache()
|
||||
{
|
||||
ContentGfxCache::~ContentGfxCache() {
|
||||
delete[] sideregions;
|
||||
}
|
||||
|
|
|
|||
104
src/frontend/InventoryView.cpp
Normal file
104
src/frontend/InventoryView.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#include "InventoryView.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "BlocksPreview.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../assets/Assets.h"
|
||||
#include "../graphics/Shader.h"
|
||||
#include "../graphics/Batch2D.h"
|
||||
#include "../graphics/GfxContext.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
InventoryView::InventoryView(
|
||||
int columns,
|
||||
Player* player,
|
||||
const Assets* assets,
|
||||
const ContentIndices* indices,
|
||||
const ContentGfxCache* cache,
|
||||
std::vector<blockid_t> blocks)
|
||||
: player(player),
|
||||
assets(assets),
|
||||
indices(indices),
|
||||
cache(cache),
|
||||
blocks(blocks),
|
||||
invColumns(columns) {
|
||||
blocksPreview = new BlocksPreview(assets->getShader("ui3d"),
|
||||
assets->getAtlas("blocks"),
|
||||
cache);
|
||||
}
|
||||
|
||||
void InventoryView::setPosition(int x, int y) {
|
||||
this->invX = x;
|
||||
this->invY = y;
|
||||
}
|
||||
|
||||
int InventoryView::getWidth() const {
|
||||
return invColumns * iconSize + (invColumns-1) * interval + padX * 2;
|
||||
}
|
||||
|
||||
int InventoryView::getHeight() const {
|
||||
uint inv_rows = ceildiv(blocks.size(), invColumns);
|
||||
return inv_rows * iconSize + (inv_rows-1) * interval + padY * 2;
|
||||
}
|
||||
|
||||
void InventoryView::actAndDraw(const GfxContext* ctx) {
|
||||
Shader* uiShader = assets->getShader("ui");
|
||||
|
||||
auto viewport = ctx->getViewport();
|
||||
uint inv_w = getWidth();
|
||||
uint inv_h = getHeight();
|
||||
int xs = invX + padX;
|
||||
int ys = invY + padY;
|
||||
|
||||
glm::vec4 tint (1.0f);
|
||||
int mx = Events::cursor.x;
|
||||
int my = Events::cursor.y;
|
||||
|
||||
// background
|
||||
auto batch = ctx->getBatch2D();
|
||||
batch->texture(nullptr);
|
||||
batch->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
batch->rect(invX, invY, inv_w, inv_h);
|
||||
batch->render();
|
||||
|
||||
// blocks & items
|
||||
if (Events::scroll) {
|
||||
inventoryScroll -= Events::scroll * (iconSize+interval);
|
||||
}
|
||||
inventoryScroll = std::min(inventoryScroll, int(inv_h-viewport.getHeight()));
|
||||
inventoryScroll = std::max(inventoryScroll, 0);
|
||||
blocksPreview->begin(&ctx->getViewport());
|
||||
{
|
||||
Window::clearDepth();
|
||||
GfxContext subctx = ctx->sub();
|
||||
subctx.depthTest(true);
|
||||
subctx.cullFace(true);
|
||||
uint index = 0;
|
||||
for (uint i = 0; i < blocks.size(); i++) {
|
||||
Block* cblock = indices->getBlockDef(blocks[i]);
|
||||
int x = xs + (iconSize+interval) * (index % invColumns);
|
||||
int y = ys + (iconSize+interval) * (index / invColumns) - inventoryScroll;
|
||||
if (y < -int(iconSize+interval) || y >= int(viewport.getHeight())) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
if (mx > x && mx < x + (int)iconSize && my > y && my < y + (int)iconSize) {
|
||||
tint.r *= 1.2f;
|
||||
tint.g *= 1.2f;
|
||||
tint.b *= 1.2f;
|
||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||
player->chosenBlock = blocks[i];
|
||||
}
|
||||
} else {
|
||||
tint = glm::vec4(1.0f);
|
||||
}
|
||||
blocksPreview->draw(cblock, x, y, iconSize, tint);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
uiShader->use();
|
||||
}
|
||||
45
src/frontend/InventoryView.h
Normal file
45
src/frontend/InventoryView.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef FRONTEND_INVENTORY_VIEW_H_
|
||||
#define FRONTEND_INVENTORY_VIEW_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
class Player;
|
||||
class Assets;
|
||||
class GfxContext;
|
||||
class ContentIndices;
|
||||
class BlocksPreview;
|
||||
class ContentGfxCache;
|
||||
|
||||
class InventoryView {
|
||||
Player* player;
|
||||
const Assets* assets;
|
||||
const ContentIndices* indices;
|
||||
const ContentGfxCache* const cache;
|
||||
std::vector<blockid_t> blocks;
|
||||
BlocksPreview* blocksPreview;
|
||||
|
||||
int inventoryScroll = 0;
|
||||
int invColumns;
|
||||
uint iconSize = 48;
|
||||
uint interval = 4;
|
||||
int padX = interval;
|
||||
int padY = interval;
|
||||
int invX = 0;
|
||||
int invY = 0;
|
||||
public:
|
||||
InventoryView(
|
||||
int columns,
|
||||
Player* player,
|
||||
const Assets* assets,
|
||||
const ContentIndices* indices,
|
||||
const ContentGfxCache* cache,
|
||||
std::vector<blockid_t> blocks);
|
||||
void setPosition(int x, int y);
|
||||
void actAndDraw(const GfxContext* ctx);
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
};
|
||||
|
||||
#endif // FRONTEND_INVENTORY_VIEW_H_
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "../../window/Events.h"
|
||||
#include "../../assets/Assets.h"
|
||||
#include "../../graphics/Batch2D.h"
|
||||
#include "../../graphics/Font.h"
|
||||
|
|
@ -21,7 +22,9 @@ const uint KEY_BACKSPACE = 259;
|
|||
using namespace gui;
|
||||
|
||||
Label::Label(wstring text, string fontName)
|
||||
: UINode(vec2(), vec2(text.length() * 8, 15)), text_(text), fontName_(fontName) {
|
||||
: UINode(vec2(), vec2(text.length() * 8, 15)),
|
||||
text_(text),
|
||||
fontName_(fontName) {
|
||||
}
|
||||
|
||||
Label& Label::text(wstring text) {
|
||||
|
|
@ -175,6 +178,13 @@ void TextBox::keyPressed(int key) {
|
|||
defocus();
|
||||
break;
|
||||
}
|
||||
// Pasting text from clipboard
|
||||
if (key == keycode::V && Events::pressed(keycode::LEFT_CONTROL)) {
|
||||
const char* text = Window::getClipboardText();
|
||||
if (text) {
|
||||
input += util::str2wstr_utf8(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<UINode> TextBox::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "screens.h"
|
||||
#include "WorldRenderer.h"
|
||||
#include "BlocksPreview.h"
|
||||
#include "InventoryView.h"
|
||||
#include "../engine.h"
|
||||
#include "../core_defs.h"
|
||||
|
||||
|
|
@ -59,13 +60,28 @@ HudRenderer::HudRenderer(Engine* engine,
|
|||
const ContentGfxCache* cache)
|
||||
: level(level),
|
||||
assets(engine->getAssets()),
|
||||
batch(new Batch2D(1024)),
|
||||
gui(engine->getGUI()),
|
||||
cache(cache) {
|
||||
auto menu = gui->getMenu();
|
||||
blocksPreview = new BlocksPreview(assets->getShader("ui3d"),
|
||||
assets->getAtlas("blocks"),
|
||||
cache);
|
||||
auto content = level->content;
|
||||
auto indices = content->indices;
|
||||
std::vector<blockid_t> blocks;
|
||||
for (blockid_t id = 1; id < indices->countBlockDefs(); id++) {
|
||||
const Block* def = indices->getBlockDef(id);
|
||||
if (def->hidden)
|
||||
continue;
|
||||
blocks.push_back(id);
|
||||
}
|
||||
contentAccess.reset(new InventoryView(
|
||||
8,
|
||||
level->player,
|
||||
assets,
|
||||
indices,
|
||||
cache,
|
||||
blocks));
|
||||
|
||||
uicamera = new Camera(vec3(), 1);
|
||||
uicamera->perspective = false;
|
||||
|
|
@ -201,7 +217,6 @@ HudRenderer::HudRenderer(Engine* engine,
|
|||
HudRenderer::~HudRenderer() {
|
||||
gui->remove(debugPanel);
|
||||
delete blocksPreview;
|
||||
delete batch;
|
||||
delete uicamera;
|
||||
}
|
||||
|
||||
|
|
@ -211,72 +226,6 @@ void HudRenderer::drawDebug(int fps){
|
|||
fpsMax = max(fps, fpsMax);
|
||||
}
|
||||
|
||||
/* Inventory temporary replaced with blocks access panel */
|
||||
void HudRenderer::drawContentAccess(const GfxContext& ctx, Player* player) {
|
||||
const Content* content = level->content;
|
||||
const ContentIndices* contentIds = content->indices;
|
||||
|
||||
const Viewport& viewport = ctx.getViewport();
|
||||
const uint width = viewport.getWidth();
|
||||
Shader* uiShader = assets->getShader("ui");
|
||||
|
||||
uint count = contentIds->countBlockDefs();
|
||||
uint icon_size = 48;
|
||||
uint interval = 4;
|
||||
uint inv_cols = 8;
|
||||
uint inv_rows = ceildiv(count-1, inv_cols);
|
||||
int pad_x = interval;
|
||||
int pad_y = interval;
|
||||
uint inv_w = inv_cols * icon_size + (inv_cols-1) * interval + pad_x * 2;
|
||||
uint inv_h = inv_rows * icon_size + (inv_rows-1) * interval + pad_x * 2;
|
||||
int inv_x = (width - (inv_w));
|
||||
int inv_y = 0;
|
||||
int xs = inv_x + pad_x;
|
||||
int ys = inv_y + pad_y;
|
||||
|
||||
vec4 tint = vec4(1.0f);
|
||||
int mx = Events::cursor.x;
|
||||
int my = Events::cursor.y;
|
||||
|
||||
// background
|
||||
batch->texture(nullptr);
|
||||
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
batch->rect(inv_x, inv_y, inv_w, inv_h);
|
||||
batch->render();
|
||||
|
||||
// blocks & items
|
||||
blocksPreview->begin(&ctx.getViewport());
|
||||
{
|
||||
Window::clearDepth();
|
||||
GfxContext subctx = ctx.sub();
|
||||
subctx.depthTest(true);
|
||||
subctx.cullFace(true);
|
||||
uint index = 0;
|
||||
for (uint i = 0; i < count-1; i++) {
|
||||
Block* cblock = contentIds->getBlockDef(i+1);
|
||||
if (cblock == nullptr)
|
||||
break;
|
||||
if (cblock->hidden)
|
||||
continue;
|
||||
int x = xs + (icon_size+interval) * (index % inv_cols);
|
||||
int y = ys + (icon_size+interval) * (index / inv_cols);
|
||||
if (mx > x && mx < x + (int)icon_size && my > y && my < y + (int)icon_size) {
|
||||
tint.r *= 1.2f;
|
||||
tint.g *= 1.2f;
|
||||
tint.b *= 1.2f;
|
||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||
player->chosenBlock = i+1;
|
||||
}
|
||||
} else {
|
||||
tint = vec4(1.0f);
|
||||
}
|
||||
blocksPreview->draw(cblock, x, y, icon_size, tint);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
uiShader->use();
|
||||
}
|
||||
|
||||
void HudRenderer::update() {
|
||||
auto menu = gui->getMenu();
|
||||
if (pause && menu->current().panel == nullptr) {
|
||||
|
|
@ -319,6 +268,7 @@ void HudRenderer::draw(const GfxContext& ctx){
|
|||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
|
||||
auto batch = ctx.getBatch2D();
|
||||
batch->begin();
|
||||
|
||||
// Chosen block preview
|
||||
|
|
@ -358,7 +308,8 @@ void HudRenderer::draw(const GfxContext& ctx){
|
|||
batch->rect(0, 0, width, height);
|
||||
}
|
||||
if (inventoryOpen) {
|
||||
drawContentAccess(ctx, player);
|
||||
contentAccess->setPosition(viewport.getWidth()-contentAccess->getWidth(), 0);
|
||||
contentAccess->actAndDraw(&ctx);
|
||||
}
|
||||
batch->render();
|
||||
}
|
||||
|
|
@ -369,4 +320,4 @@ bool HudRenderer::isInventoryOpen() const {
|
|||
|
||||
bool HudRenderer::isPause() const {
|
||||
return pause;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "../graphics/GfxContext.h"
|
||||
|
||||
class Batch2D;
|
||||
class Camera;
|
||||
class Level;
|
||||
class Block;
|
||||
|
|
@ -17,8 +16,8 @@ class Player;
|
|||
class Level;
|
||||
class Engine;
|
||||
class ContentGfxCache;
|
||||
class WorldRenderer;
|
||||
class BlocksPreview;
|
||||
class InventoryView;
|
||||
|
||||
namespace gui {
|
||||
class GUI;
|
||||
|
|
@ -28,7 +27,6 @@ namespace gui {
|
|||
class HudRenderer {
|
||||
Level* level;
|
||||
Assets* assets;
|
||||
Batch2D* batch;
|
||||
Camera* uicamera;
|
||||
BlocksPreview* blocksPreview;
|
||||
|
||||
|
|
@ -39,6 +37,7 @@ class HudRenderer {
|
|||
bool inventoryOpen = false;
|
||||
bool pause = false;
|
||||
|
||||
std::unique_ptr<InventoryView> contentAccess;
|
||||
std::shared_ptr<gui::UINode> debugPanel;
|
||||
gui::GUI* gui;
|
||||
const ContentGfxCache* const cache;
|
||||
|
|
@ -49,7 +48,6 @@ public:
|
|||
~HudRenderer();
|
||||
|
||||
void update();
|
||||
void drawContentAccess(const GfxContext& ctx, Player* player);
|
||||
void draw(const GfxContext& context);
|
||||
void drawDebug(int fps);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
#include "../util/stringutil.h"
|
||||
#include "../files/engine_paths.h"
|
||||
#include "../files/WorldConverter.h"
|
||||
#include "../files/WorldFiles.h"
|
||||
#include "../world/World.h"
|
||||
#include "../world/Level.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../window/Window.h"
|
||||
#include "../engine.h"
|
||||
|
|
@ -175,8 +177,18 @@ void open_world(std::string name, Engine* engine) {
|
|||
show_convert_request(engine, content, lut, folder);
|
||||
}
|
||||
} else {
|
||||
Level* level = World::load(folder, settings, content, packs);
|
||||
engine->setScreen(std::make_shared<LevelScreen>(engine, level));
|
||||
// TODO: remove in 0.18
|
||||
int version;
|
||||
{
|
||||
WorldFiles wfile(folder, settings.debug);
|
||||
version = wfile.getVoxelRegionsVersion();
|
||||
}
|
||||
if (version != REGION_FORMAT_VERSION) {
|
||||
show_convert_request(engine, content, lut, folder);
|
||||
} else {
|
||||
Level* level = World::load(folder, settings, content, packs);
|
||||
engine->setScreen(std::make_shared<LevelScreen>(engine, level));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,20 +41,24 @@ using glm::vec3;
|
|||
using glm::vec4;
|
||||
using std::shared_ptr;
|
||||
|
||||
Screen::Screen(Engine* engine) : engine(engine), batch(new Batch2D(1024)) {
|
||||
}
|
||||
|
||||
Screen::~Screen() {
|
||||
}
|
||||
|
||||
MenuScreen::MenuScreen(Engine* engine_) : Screen(engine_) {
|
||||
auto menu = engine->getGUI()->getMenu();
|
||||
menus::refresh_menus(engine, menu);
|
||||
menu->reset();
|
||||
menu->set("main");
|
||||
|
||||
batch = new Batch2D(1024);
|
||||
uicamera = new Camera(vec3(), Window::height);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
}
|
||||
|
||||
MenuScreen::~MenuScreen() {
|
||||
delete batch;
|
||||
delete uicamera;
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +159,7 @@ void LevelScreen::draw(float delta) {
|
|||
Camera* camera = level->player->currentViewCamera;
|
||||
|
||||
Viewport viewport(Window::width, Window::height);
|
||||
GfxContext ctx(nullptr, viewport, nullptr);
|
||||
GfxContext ctx(nullptr, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, camera);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,15 @@ class LevelController;
|
|||
class Screen {
|
||||
protected:
|
||||
Engine* engine;
|
||||
std::unique_ptr<Batch2D> batch;
|
||||
public:
|
||||
Screen(Engine* engine) : engine(engine) {};
|
||||
virtual ~Screen() {};
|
||||
Screen(Engine* engine);
|
||||
virtual ~Screen();
|
||||
virtual void update(float delta) = 0;
|
||||
virtual void draw(float delta) = 0;
|
||||
};
|
||||
|
||||
class MenuScreen : public Screen {
|
||||
Batch2D* batch;
|
||||
Camera* uicamera;
|
||||
public:
|
||||
MenuScreen(Engine* engine);
|
||||
|
|
@ -42,6 +42,7 @@ class LevelScreen : public Screen {
|
|||
WorldRenderer* worldRenderer;
|
||||
HudRenderer* hud;
|
||||
ContentGfxCache* cache;
|
||||
|
||||
bool hudVisible = true;
|
||||
void updateHotkeys();
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -82,9 +82,39 @@ void ImageData::flipY() {
|
|||
}
|
||||
|
||||
void ImageData::blit(const ImageData* image, int x, int y) {
|
||||
if (format != image->format) {
|
||||
throw std::runtime_error("mismatching format");
|
||||
if (format == image->format) {
|
||||
blitMatchingFormat(image, x, y);
|
||||
return;
|
||||
}
|
||||
if (format == ImageFormat::rgba8888 &&
|
||||
image->format == ImageFormat::rgb888) {
|
||||
blitRGB_on_RGBA(image, x, y);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("mismatching format");
|
||||
}
|
||||
|
||||
void ImageData::blitRGB_on_RGBA(const ImageData* image, int x, int y) {
|
||||
ubyte* pixels = static_cast<ubyte*>(data);
|
||||
ubyte* source = static_cast<ubyte*>(image->getData());
|
||||
uint srcwidth = image->getWidth();
|
||||
uint srcheight = image->getHeight();
|
||||
|
||||
for (uint srcy = max(0, -y); (int)srcy < min(srcheight, height-y); srcy++) {
|
||||
for (uint srcx = max(0, -x); (int)srcx < min(srcwidth, width-x); srcx++) {
|
||||
uint dstx = srcx + x;
|
||||
uint dsty = srcy + y;
|
||||
uint dstidx = (dsty * width + dstx) * 4;
|
||||
uint srcidx = (srcy * srcwidth + srcx) * 3;
|
||||
for (uint c = 0; c < 3; c++) {
|
||||
pixels[dstidx + c] = source[srcidx + c];
|
||||
}
|
||||
pixels[dstidx + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageData::blitMatchingFormat(const ImageData* image, int x, int y) {
|
||||
uint comps;
|
||||
switch (format) {
|
||||
case ImageFormat::rgb888: comps = 3; break;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ public:
|
|||
void flipX();
|
||||
void flipY();
|
||||
|
||||
void blitRGB_on_RGBA(const ImageData* image, int x, int y);
|
||||
void blitMatchingFormat(const ImageData* image, int x, int y);
|
||||
void blit(const ImageData* image, int x, int y);
|
||||
void extrude(int x, int y, int w, int h);
|
||||
void fixAlphaColor();
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ void BlocksController::updateBlock(int x, int y, int z) {
|
|||
if (vox == nullptr)
|
||||
return;
|
||||
const Block* def = level->content->indices->getBlockDef(vox->id);
|
||||
if (def->grounded && !chunks->isSolid(x, y-1, z)) {
|
||||
if (def->grounded && !chunks->isSolidBlock(x, y-1, z)) {
|
||||
breakBlock(nullptr, def, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ void PlayerController::updateInteraction(){
|
|||
if (!level->physics->isBlockInside(x,y,z, player->hitbox)
|
||||
|| !def->obstacle){
|
||||
Block* def = contentIds->getBlockDef(chosenBlock);
|
||||
if (def->grounded && !chunks->isSolid(x, y-1, z)) {
|
||||
if (def->grounded && !chunks->isSolidBlock(x, y-1, z)) {
|
||||
chosenBlock = 0;
|
||||
}
|
||||
if (chosenBlock != vox->id) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ int l_is_solid_at(lua_State* L) {
|
|||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolid(x, y, z));
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +60,13 @@ int l_get_block(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int l_get_player_pos(lua_State* L) {
|
||||
glm::vec3 pos = scripting::level->player->hitbox->position;
|
||||
lua_pushnumber(L, pos.x);
|
||||
|
|
@ -103,12 +110,13 @@ int l_get_block_states(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int l_is_replaceable_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isReplaceable(x, y, z));
|
||||
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +235,7 @@ inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
|||
lua_pushinteger(L, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int l_get_block_x(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
|
|
@ -288,6 +297,9 @@ void apilua::create_funcs(lua_State* L) {
|
|||
lua_addfunc(L, l_is_replaceable_at, "is_replaceable_at");
|
||||
lua_addfunc(L, l_set_block, "set_block");
|
||||
lua_addfunc(L, l_get_block, "get_block");
|
||||
lua_addfunc(L, l_get_block_x, "get_block_X");
|
||||
lua_addfunc(L, l_get_block_y, "get_block_Y");
|
||||
lua_addfunc(L, l_get_block_z, "get_block_Z");
|
||||
lua_addfunc(L, l_get_player_pos, "get_player_pos");
|
||||
lua_addfunc(L, l_set_player_pos, "set_player_pos");
|
||||
lua_addfunc(L, l_get_player_rot, "get_player_rot");
|
||||
|
|
@ -306,4 +318,6 @@ void apilua::create_funcs(lua_State* L) {
|
|||
lua_addfunc(L, l_get_block_x, "get_block_X");
|
||||
lua_addfunc(L, l_get_block_y, "get_block_Y");
|
||||
lua_addfunc(L, l_get_block_z, "get_block_Z");
|
||||
lua_addfunc(L, l_get_block_custom_bits, "get_block_custom_bits");
|
||||
lua_addfunc(L, l_set_block_custom_bits, "set_block_custom_bits");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,10 +53,14 @@ void scripting::initialize(EnginePaths* paths) {
|
|||
if (L == nullptr) {
|
||||
throw std::runtime_error("could not to initialize Lua");
|
||||
}
|
||||
|
||||
// Allowed standard libraries
|
||||
luaopen_base(L);
|
||||
luaopen_math(L);
|
||||
luaopen_table(L);
|
||||
luaopen_string(L);
|
||||
luaopen_table(L);
|
||||
|
||||
// io-manipulations will be implemented via api functions
|
||||
|
||||
std::cout << LUA_VERSION << std::endl;
|
||||
# ifdef LUAJIT_VERSION
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ struct AABB {
|
|||
}
|
||||
|
||||
/* Check if given point is inside */
|
||||
inline bool inside(const glm::vec3 pos) const {
|
||||
inline bool contains(const glm::vec3 pos) const {
|
||||
const glm::vec3 p = min();
|
||||
const glm::vec3 s = size();
|
||||
return !(pos.x < p.x || pos.y < p.y || pos.z < p.z ||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
std::unordered_map<rayvec3, AABBFaces> Ray::raysBoxCache_ = {};
|
||||
const rayvec3 X_AXIS = rayvec3(1,0,0), Y_AXIS = rayvec3(0,1,0), Z_AXIS = rayvec3(0,0,1);
|
||||
static const rayvec3 X_AXIS = rayvec3(1,0,0), Y_AXIS = rayvec3(0,1,0), Z_AXIS = rayvec3(0,0,1);
|
||||
|
||||
Ray::Ray(const rayvec3& origin, const rayvec3& dir) : origin(origin), dir(dir) {}
|
||||
|
||||
|
|
@ -17,21 +16,21 @@ AABBFaces::AABBFaces(const rayvec3& parentBoxPos, const AABB& parentBox){
|
|||
rayvec2 yzMax = rayvec2(parentBoxPos.y + pbMax.y, parentBoxPos.z + pbMax.z ),
|
||||
xzMax = rayvec2(parentBoxPos.x + pbMax.x, parentBoxPos.z + pbMax.z ),
|
||||
xyMax = rayvec2(parentBoxPos.x + pbMax.x, parentBoxPos.y + pbMax.y );
|
||||
faces[0] = {pbRealPos, yzMax}; //in order of AABBFaces::KINDS_ORDER!
|
||||
faces[0] = { parentBoxPos + rayvec3(pbMax.x, pbMin.y, pbMin.z), yzMax };
|
||||
|
||||
faces[1] = {parentBoxPos + rayvec3(pbMax.x, pbMin.y, pbMin.z), yzMax};
|
||||
faces[1] = {pbRealPos, yzMax};
|
||||
|
||||
faces[2] = {pbRealPos, xzMax};
|
||||
faces[2] = { parentBoxPos + rayvec3(pbMin.x, pbMax.y, pbMin.z), xzMax };
|
||||
|
||||
faces[3] = {parentBoxPos + rayvec3(pbMin.x, pbMax.y, pbMin.z), xzMax};
|
||||
faces[3] = {pbRealPos, xzMax};
|
||||
|
||||
faces[4] = {pbRealPos, xyMax};
|
||||
faces[4] = { parentBoxPos + rayvec3(pbMin.x, pbMin.y, pbMax.z), xyMax };
|
||||
|
||||
faces[5] = {pbRealPos, xyMax};
|
||||
|
||||
faces[5] = {parentBoxPos + rayvec3(pbMin.x, pbMin.y, pbMax.z), xyMax};
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::intersectAAFace<AAFaceKind::Xperp>(
|
||||
RayRelation Ray::intersectYZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner, //y and z global coords of opposite corner
|
||||
glm::ivec3& normal_ret,
|
||||
|
|
@ -59,8 +58,7 @@ RayRelation Ray::intersectAAFace<AAFaceKind::Xperp>(
|
|||
return RayRelation::None;
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::intersectAAFace<AAFaceKind::Yperp>(
|
||||
RayRelation Ray::intersectXZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner, //x and z global coords of opposite corner
|
||||
glm::ivec3& normal_ret,
|
||||
|
|
@ -88,8 +86,7 @@ RayRelation Ray::intersectAAFace<AAFaceKind::Yperp>(
|
|||
return RayRelation::None;
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::intersectAAFace<AAFaceKind::Zperp>(
|
||||
RayRelation Ray::intersectXYFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner, //x and y global coords of opposite corner
|
||||
glm::ivec3& normal_ret,
|
||||
|
|
@ -117,8 +114,7 @@ RayRelation Ray::intersectAAFace<AAFaceKind::Zperp>(
|
|||
return RayRelation::None;
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::isIntersectsAAFace<AAFaceKind::Xperp>(
|
||||
RayRelation Ray::isIntersectsYZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner
|
||||
){
|
||||
|
|
@ -141,8 +137,7 @@ RayRelation Ray::isIntersectsAAFace<AAFaceKind::Xperp>(
|
|||
return RayRelation::None;
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::isIntersectsAAFace<AAFaceKind::Yperp>(
|
||||
RayRelation Ray::isIntersectsXZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner
|
||||
) {
|
||||
|
|
@ -165,8 +160,7 @@ RayRelation Ray::isIntersectsAAFace<AAFaceKind::Yperp>(
|
|||
return RayRelation::None;
|
||||
}
|
||||
|
||||
template <>
|
||||
RayRelation Ray::isIntersectsAAFace<AAFaceKind::Zperp>(
|
||||
RayRelation Ray::isIntersectsXYFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner
|
||||
) {
|
||||
|
|
@ -195,29 +189,15 @@ RayRelation Ray::intersectAABB(
|
|||
float maxDist,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret){
|
||||
if constexpr (IS_RAYS_BOX_CACHE_ON){
|
||||
|
||||
if (raysBoxCache_.find(boxPos) != raysBoxCache_.end()){
|
||||
const AABBFaces& boxFaces = raysBoxCache_[boxPos];
|
||||
return intersectAABBFaces(boxFaces, maxDist, normal_ret, distance_ret);
|
||||
} else {
|
||||
const AABBFaces& boxFaces = AABBFaces(boxPos, box);
|
||||
raysBoxCache_[boxPos] = boxFaces;
|
||||
return intersectAABBFaces(boxFaces, maxDist, normal_ret, distance_ret);
|
||||
}
|
||||
|
||||
} else {
|
||||
const AABBFaces& boxFaces = AABBFaces(boxPos, box);
|
||||
return intersectAABBFaces(boxFaces, maxDist, normal_ret, distance_ret);
|
||||
}
|
||||
|
||||
const AABBFaces& boxFaces = AABBFaces(boxPos, box);
|
||||
return intersectAABBFaces(boxFaces, maxDist, normal_ret, distance_ret);
|
||||
}
|
||||
|
||||
RayRelation Ray::intersectAABBFaces(
|
||||
const AABBFaces& boxFaces,
|
||||
float maxDist,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret){//TODO: points returning
|
||||
scalar_t& distance_ret){
|
||||
|
||||
scalar_t faceDist;
|
||||
distance_ret = maxDist;
|
||||
|
|
@ -225,7 +205,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
//unsigned char intersectedCount = 0; //this code is very uncomfortable, DONT LEARN IT!
|
||||
bool isIntersect = false;
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[0]>(
|
||||
if (intersectYZFace(
|
||||
boxFaces.faces[0].first, boxFaces.faces[0].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret){
|
||||
isIntersect = true;
|
||||
|
|
@ -233,7 +213,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
distance_ret = faceDist;
|
||||
}
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[1]>(
|
||||
if (intersectYZFace(
|
||||
boxFaces.faces[1].first, boxFaces.faces[1].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret) {
|
||||
isIntersect = true;
|
||||
|
|
@ -241,7 +221,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
distance_ret = faceDist;
|
||||
}
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[2]>(
|
||||
if (intersectXZFace(
|
||||
boxFaces.faces[2].first, boxFaces.faces[2].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret) {
|
||||
isIntersect = true;
|
||||
|
|
@ -249,7 +229,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
distance_ret = faceDist;
|
||||
}
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[3]>(
|
||||
if (intersectXZFace(
|
||||
boxFaces.faces[3].first, boxFaces.faces[3].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret) {
|
||||
isIntersect = true;
|
||||
|
|
@ -257,7 +237,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
distance_ret = faceDist;
|
||||
}
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[4]>(
|
||||
if (intersectXYFace(
|
||||
boxFaces.faces[4].first, boxFaces.faces[4].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret) {
|
||||
isIntersect = true;
|
||||
|
|
@ -265,7 +245,7 @@ RayRelation Ray::intersectAABBFaces(
|
|||
distance_ret = faceDist;
|
||||
}
|
||||
|
||||
if (intersectAAFace<AABBFaces::KINDS_ORDER[5]>(
|
||||
if (intersectXYFace(
|
||||
boxFaces.faces[5].first, boxFaces.faces[5].second, bufNormal, faceDist
|
||||
) > RayRelation::None && faceDist < distance_ret) {
|
||||
isIntersect = true;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "glm/gtx/hash.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
typedef glm::highp_dvec3 rayvec3;
|
||||
typedef glm::highp_dvec2 rayvec2;
|
||||
|
|
@ -17,31 +16,18 @@ typedef double scalar_t;
|
|||
enum class RayRelation{
|
||||
Embed=2, Intersect=1, Parallel=0, None=0
|
||||
};
|
||||
enum class AAFaceKind : unsigned char{
|
||||
Xperp=0, Yperp=1, Zperp=2 //perpendicular faces to corresponding axis
|
||||
};
|
||||
|
||||
const unsigned char AABBFACES_COUNT = 6;
|
||||
|
||||
class AABBFaces{
|
||||
static const unsigned char AABBFACES_COUNT = 6;
|
||||
public:
|
||||
std::array<std::pair<rayvec3, rayvec2>, AABBFACES_COUNT> faces; // every face is min-point and opposite corner point
|
||||
|
||||
static constexpr std::array<AAFaceKind,AABBFACES_COUNT> KINDS_ORDER = {
|
||||
AAFaceKind::Xperp, AAFaceKind::Xperp,
|
||||
AAFaceKind::Yperp, AAFaceKind::Yperp,
|
||||
AAFaceKind::Zperp, AAFaceKind::Zperp};
|
||||
|
||||
AABBFaces(){};
|
||||
AABBFaces(const rayvec3& parentBoxPos, const AABB& parentBox);
|
||||
|
||||
};
|
||||
|
||||
class Ray{
|
||||
protected:
|
||||
static const bool IS_RAYS_BOX_CACHE_ON = false; // Now not working properly because not observe updates
|
||||
static std::unordered_map<rayvec3, AABBFaces> raysBoxCache_; //[boxPos]: faces array
|
||||
|
||||
public:
|
||||
rayvec3 origin;
|
||||
rayvec3 dir;
|
||||
|
|
@ -49,39 +35,32 @@ public:
|
|||
Ray(const rayvec3& rayOrigin,
|
||||
const rayvec3& rayDir);
|
||||
|
||||
//optimized, NOT returns intersectPoint coordinates and normal vector
|
||||
template <AAFaceKind faceKind>
|
||||
RayRelation isIntersectsAAFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner
|
||||
);
|
||||
|
||||
//returns only normal
|
||||
template <AAFaceKind faceKind>
|
||||
RayRelation intersectAAFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret
|
||||
);
|
||||
RayRelation isIntersectsYZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner);
|
||||
RayRelation isIntersectsXZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner);
|
||||
RayRelation isIntersectsXYFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner);
|
||||
|
||||
//returns normal and distance
|
||||
template <AAFaceKind faceKind>
|
||||
RayRelation intersectAAFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret
|
||||
);
|
||||
|
||||
// returns normal, distance and intersection point
|
||||
template <AAFaceKind faceKind>
|
||||
RayRelation intersectAAFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret,
|
||||
rayvec3& intersectPoint_ret
|
||||
);
|
||||
RayRelation intersectYZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret);
|
||||
RayRelation intersectXZFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret);
|
||||
RayRelation intersectXYFace(
|
||||
const rayvec3& faceMin,
|
||||
const rayvec2& faceOppositeCorner,
|
||||
glm::ivec3& normal_ret,
|
||||
scalar_t& distance_ret);
|
||||
|
||||
RayRelation intersectAABB(
|
||||
const rayvec3& boxPos,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void PhysicsSolver::step(
|
|||
hitbox->grounded = false;
|
||||
for (float x = (px-half.x+E); x <= (px+half.x-E); x+=s){
|
||||
for (float z = (pos.z-half.z+E); z <= (pos.z+half.z-E); z+=s){
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
if (chunks->isObstacleAt(x,y,z)){
|
||||
hitbox->grounded = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ void PhysicsSolver::step(
|
|||
hitbox->grounded = false;
|
||||
for (float x = (pos.x-half.x+E); x <= (pos.x+half.x-E); x+=s){
|
||||
for (float z = (pz-half.z+E); z <= (pz+half.z-E); z+=s){
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
if (chunks->isObstacleAt(x,y,z)){
|
||||
hitbox->grounded = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float y = (pos.y-half.y+E); y <= (pos.y+half.y-E); y+=s){
|
||||
for (float z = (pos.z-half.z+E); z <= (pos.z+half.z-E); z+=s){
|
||||
float x = (pos.x-half.x-E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.x *= 0.0f;
|
||||
pos.x = floor(x) + aabb->max().x + half.x + E;
|
||||
break;
|
||||
|
|
@ -100,7 +100,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float y = (pos.y-half.y+E); y <= (pos.y+half.y-E); y+=s){
|
||||
for (float z = (pos.z-half.z+E); z <= (pos.z+half.z-E); z+=s){
|
||||
float x = (pos.x+half.x+E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.x *= 0.0f;
|
||||
pos.x = floor(x) - half.x + aabb->min().x - E;
|
||||
break;
|
||||
|
|
@ -113,7 +113,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float y = (pos.y-half.y+E); y <= (pos.y+half.y-E); y+=s){
|
||||
for (float x = (pos.x-half.x+E); x <= (pos.x+half.x-E); x+=s){
|
||||
float z = (pos.z-half.z-E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.z *= 0.0f;
|
||||
pos.z = floor(z) + aabb->max().z + half.z + E;
|
||||
break;
|
||||
|
|
@ -126,7 +126,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float y = (pos.y-half.y+E); y <= (pos.y+half.y-E); y+=s){
|
||||
for (float x = (pos.x-half.x+E); x <= (pos.x+half.x-E); x+=s){
|
||||
float z = (pos.z+half.z+E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.z *= 0.0f;
|
||||
pos.z = floor(z) - half.z + aabb->min().z - E;
|
||||
break;
|
||||
|
|
@ -139,7 +139,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float x = (pos.x-half.x+E); x <= (pos.x+half.x-E); x+=s){
|
||||
for (float z = (pos.z-half.z+E); z <= (pos.z+half.z-E); z+=s){
|
||||
float y = (pos.y-half.y-E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.y *= 0.0f;
|
||||
pos.y = floor(y) + aabb->max().y + half.y;
|
||||
hitbox->grounded = true;
|
||||
|
|
@ -152,7 +152,7 @@ void PhysicsSolver::colisionCalc(
|
|||
for (float x = (pos.x-half.x+E); x <= (pos.x+half.x-E); x+=s){
|
||||
for (float z = (pos.z-half.z+E); z <= (pos.z+half.z-E); z+=s){
|
||||
float y = (pos.y+half.y+E);
|
||||
if ((aabb = chunks->isObstacle(x,y,z))){
|
||||
if ((aabb = chunks->isObstacleAt(x,y,z))){
|
||||
vel.y *= 0.0f;
|
||||
pos.y = floor(y) - half.y + aabb->min().y - E;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,8 @@ typedef uint16_t u_short16;
|
|||
typedef uint32_t u_int32;
|
||||
typedef uint64_t u_long64;
|
||||
|
||||
// typedef unsigned int uint;
|
||||
// typedef unsigned short ushort;
|
||||
// typedef unsigned char ubyte;
|
||||
|
||||
typedef uint16_t blockid_t;
|
||||
typedef uint16_t blockstate_t;
|
||||
typedef uint16_t light_t;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,42 +4,36 @@
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using std::filesystem::path;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
bool parse_cmdline(int argc, char** argv, EnginePaths& paths) {
|
||||
ArgsReader reader(argc, argv);
|
||||
reader.skip();
|
||||
while (reader.hasNext()) {
|
||||
string token = reader.next();
|
||||
std::string token = reader.next();
|
||||
if (reader.isKeywordArg()) {
|
||||
if (token == "--res") {
|
||||
token = reader.next();
|
||||
if (!fs::is_directory(path(token))) {
|
||||
if (!fs::is_directory(fs::path(token))) {
|
||||
throw std::runtime_error(token+" is not a directory");
|
||||
}
|
||||
paths.setResources(path(token));
|
||||
cout << "resources folder: " << token << std::endl;
|
||||
paths.setResources(fs::path(token));
|
||||
std::cout << "resources folder: " << token << std::endl;
|
||||
} else if (token == "--dir") {
|
||||
token = reader.next();
|
||||
if (!fs::is_directory(path(token))) {
|
||||
fs::create_directories(path(token));
|
||||
if (!fs::is_directory(fs::path(token))) {
|
||||
fs::create_directories(fs::path(token));
|
||||
}
|
||||
paths.setUserfiles(path(token));
|
||||
cout << "userfiles folder: " << token << endl;
|
||||
paths.setUserfiles(fs::path(token));
|
||||
std::cout << "userfiles folder: " << token << std::endl;
|
||||
} else if (token == "--help" || token == "-h") {
|
||||
cout << "VoxelEngine command-line arguments:" << endl;
|
||||
cout << " --res [path] - set resources directory" << endl;
|
||||
cout << " --dir [path] - set userfiles directory" << endl;
|
||||
std::cout << "VoxelEngine command-line arguments:" << std::endl;
|
||||
std::cout << " --res [path] - set resources directory" << std::endl;
|
||||
std::cout << " --dir [path] - set userfiles directory" << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
cerr << "unknown argument " << token << endl;
|
||||
std::cerr << "unknown argument " << token << std::endl;
|
||||
}
|
||||
} else {
|
||||
cerr << "unexpected token" << endl;
|
||||
std::cerr << "unexpected token" << std::endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -6,17 +6,11 @@
|
|||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::stringstream;
|
||||
using std::wstring;
|
||||
using std::wstringstream;
|
||||
|
||||
wstring util::lfill(wstring s, uint length, wchar_t c) {
|
||||
std::wstring util::lfill(std::wstring s, uint length, wchar_t c) {
|
||||
if (s.length() >= length) {
|
||||
return s;
|
||||
}
|
||||
wstringstream ss;
|
||||
std::wstringstream ss;
|
||||
for (uint i = 0; i < length-s.length(); i++) {
|
||||
ss << c;
|
||||
}
|
||||
|
|
@ -24,11 +18,11 @@ wstring util::lfill(wstring s, uint length, wchar_t c) {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
wstring util::rfill(wstring s, uint length, wchar_t c) {
|
||||
std::wstring util::rfill(std::wstring s, uint length, wchar_t c) {
|
||||
if (s.length() >= length) {
|
||||
return s;
|
||||
}
|
||||
wstringstream ss;
|
||||
std::wstringstream ss;
|
||||
ss << s;
|
||||
for (uint i = 0; i < length-s.length(); i++) {
|
||||
ss << c;
|
||||
|
|
@ -103,8 +97,8 @@ extern uint32_t util::decode_utf8(uint& size, const char* chr) {
|
|||
return code;
|
||||
}
|
||||
|
||||
string util::wstr2str_utf8(const wstring ws) {
|
||||
vector<char> chars;
|
||||
std::string util::wstr2str_utf8(const std::wstring ws) {
|
||||
std::vector<char> chars;
|
||||
char buffer[4];
|
||||
for (wchar_t wc : ws) {
|
||||
uint size = encode_utf8((uint)wc, (u_char8*)buffer);
|
||||
|
|
@ -112,21 +106,21 @@ string util::wstr2str_utf8(const wstring ws) {
|
|||
chars.push_back(buffer[i]);
|
||||
}
|
||||
}
|
||||
return string(chars.data(), chars.size());
|
||||
return std::string(chars.data(), chars.size());
|
||||
}
|
||||
|
||||
wstring util::str2wstr_utf8(const string s) {
|
||||
vector<wchar_t> chars;
|
||||
std::wstring util::str2wstr_utf8(const std::string s) {
|
||||
std::vector<wchar_t> chars;
|
||||
size_t pos = 0;
|
||||
uint size = 0;
|
||||
while (pos < s.length()) {
|
||||
chars.push_back(decode_utf8(size, &s.at(pos)));
|
||||
pos += size;
|
||||
}
|
||||
return wstring(chars.data(), chars.size());
|
||||
return std::wstring(chars.data(), chars.size());
|
||||
}
|
||||
|
||||
bool util::is_integer(string text) {
|
||||
bool util::is_integer(std::string text) {
|
||||
for (char c : text) {
|
||||
if (c < '0' || c > '9')
|
||||
return false;
|
||||
|
|
@ -134,7 +128,7 @@ bool util::is_integer(string text) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool util::is_integer(wstring text) {
|
||||
bool util::is_integer(std::wstring text) {
|
||||
for (wchar_t c : text) {
|
||||
if (c < L'0' || c > L'9')
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ void CoordSystem::transform(AABB& aabb) const {
|
|||
aabb.b += fix;
|
||||
}
|
||||
|
||||
const BlockRotProfile BlockRotProfile::PIPE {"pipe", {//TODO consexpr or init-time fix calculations
|
||||
const BlockRotProfile BlockRotProfile::PIPE {"pipe", {
|
||||
{ { 1, 0, 0 }, { 0, 0, 1 }, { 0, -1, 0 }}, // North
|
||||
{ { 0, 0, 1 }, {-1, 0, 0 }, { 0, -1, 0 }}, // East
|
||||
{ { -1, 0, 0 }, { 0, 0,-1 }, { 0, -1, 0 }}, // South
|
||||
{ { 0, 0, -1 }, { 1, 0, 0 }, { 0, -1, 0 }}, // West
|
||||
{ { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }}, // Up
|
||||
{ { 1, 0, 0 }, { 0,-1, 0 }, { 0, 0,-1 }}, // Down
|
||||
{ {-1, 0, 0 }, { 0, 0,-1 }, { 0, -1, 0 }}, // South
|
||||
{ { 0, 0,-1 }, { 1, 0, 0 }, { 0, -1, 0 }}, // West
|
||||
{ { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }}, // Up
|
||||
{ { 1, 0, 0 }, { 0,-1, 0 }, { 0, 0,-1 }}, // Down
|
||||
}};
|
||||
|
||||
const BlockRotProfile BlockRotProfile::PANE {"pane", {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ struct CoordSystem {
|
|||
};
|
||||
|
||||
struct BlockRotProfile {
|
||||
static const int MAX_COUNT = 16;
|
||||
static const int MAX_COUNT = 8;
|
||||
std::string name;
|
||||
CoordSystem variants[MAX_COUNT];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "Chunk.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "voxel.h"
|
||||
#include "../content/ContentLUT.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
|
|
@ -22,7 +25,7 @@ Chunk::~Chunk(){
|
|||
|
||||
bool Chunk::isEmpty(){
|
||||
int id = -1;
|
||||
for (int i = 0; i < CHUNK_VOL; i++){
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++){
|
||||
if (voxels[i].id != id){
|
||||
if (id != -1)
|
||||
return false;
|
||||
|
|
@ -34,14 +37,14 @@ bool Chunk::isEmpty(){
|
|||
}
|
||||
|
||||
void Chunk::updateHeights() {
|
||||
for (int i = 0; i < CHUNK_VOL; i++) {
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
if (voxels[i].id != 0) {
|
||||
bottom = i / (CHUNK_D * CHUNK_W);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = CHUNK_VOL - 1; i > -1; i--) {
|
||||
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
|
||||
if (voxels[i].id != 0) {
|
||||
top = i / (CHUNK_D * CHUNK_W) + 1;
|
||||
break;
|
||||
|
|
@ -51,7 +54,7 @@ void Chunk::updateHeights() {
|
|||
|
||||
Chunk* Chunk::clone() const {
|
||||
Chunk* other = new Chunk(x,z);
|
||||
for (int i = 0; i < CHUNK_VOL; i++)
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++)
|
||||
other->voxels[i] = voxels[i];
|
||||
other->lightmap->set(lightmap);
|
||||
return other;
|
||||
|
|
@ -59,32 +62,68 @@ Chunk* Chunk::clone() const {
|
|||
|
||||
/**
|
||||
Current chunk format:
|
||||
[voxel_ids...][voxel_states...];
|
||||
- byte-order: big-endian
|
||||
- [don't panic!] first and second bytes are separated for RLE efficiency
|
||||
|
||||
```cpp
|
||||
uint8_t voxel_id_first_byte[CHUNK_VOL];
|
||||
uint8_t voxel_id_second_byte[CHUNK_VOL];
|
||||
uint8_t voxel_states_first_byte[CHUNK_VOL];
|
||||
uint8_t voxel_states_second_byte[CHUNK_VOL];
|
||||
```
|
||||
|
||||
Total size: (CHUNK_VOL * 4) bytes
|
||||
*/
|
||||
u_char8* Chunk::encode() const {
|
||||
u_char8* buffer = new u_char8[CHUNK_DATA_LEN];
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
((u_short16*)buffer)[i] = voxels[i].id;
|
||||
((u_short16*)buffer)[CHUNK_VOL + i] = voxels[i].states;
|
||||
buffer[i] = voxels[i].id >> 8;
|
||||
buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF;
|
||||
buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8;
|
||||
buffer[CHUNK_VOL*3 + i] = voxels[i].states & 0xFF;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if all is fine
|
||||
*/
|
||||
/**
|
||||
* @return true if all is fine
|
||||
**/
|
||||
bool Chunk::decode(u_char8* data) {
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
voxel& vox = voxels[i];
|
||||
vox.id = ((u_short16*)data)[i];
|
||||
vox.states = ((u_short16*)data)[CHUNK_VOL + i];
|
||||
|
||||
u_char8 bid1 = data[i];
|
||||
u_char8 bid2 = data[CHUNK_VOL + i];
|
||||
|
||||
u_char8 bst1 = data[CHUNK_VOL*2 + i];
|
||||
u_char8 bst2 = data[CHUNK_VOL*3 + i];
|
||||
|
||||
vox.id = (blockid_t(bid1) << 8) | (blockid_t(bid2));
|
||||
vox.states = (blockstate_t(bst1) << 8) | (blockstate_t(bst2));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Chunk::convert(u_char8* data, const ContentLUT* lut) {
|
||||
/*
|
||||
* Convert chunk voxels data from 16 bit to 32 bit
|
||||
*/
|
||||
void Chunk::fromOld(u_char8* data) {
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
blockid_t id = ((u_short16*)data)[i];
|
||||
((u_short16*)data)[i] = lut->getBlockId(id);
|
||||
data[i + CHUNK_VOL*3] = data[i + CHUNK_VOL];
|
||||
data[i + CHUNK_VOL] = data[i];
|
||||
data[i + CHUNK_VOL*2] = 0;
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Chunk::convert(u_char8* data, const ContentLUT* lut) {
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
// see encode method to understand what the hell is going on here
|
||||
blockid_t id = ((blockid_t(data[i]) << 8) |
|
||||
blockid_t(data[CHUNK_VOL+i]));
|
||||
blockid_t replacement = lut->getBlockId(id);
|
||||
data[i] = replacement >> 8;
|
||||
data[CHUNK_VOL+i] = replacement & 0xFF;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ public:
|
|||
u_char8* encode() const;
|
||||
bool decode(u_char8* data);
|
||||
|
||||
static void fromOld(u_char8* data);
|
||||
static void convert(u_char8* data, const ContentLUT* lut);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,17 +45,15 @@ Chunks::~Chunks(){
|
|||
chunks[i] = nullptr;
|
||||
}
|
||||
delete[] chunks;
|
||||
delete[] chunksSecond;
|
||||
}
|
||||
|
||||
voxel* Chunks::get(int x, int y, int z){
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
int cz = z / CHUNK_D;
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
int cy = floordiv(y, CHUNK_H);
|
||||
int cz = floordiv(z, CHUNK_D);
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||
return nullptr;
|
||||
shared_ptr<Chunk> chunk = chunks[cz * w + cx]; // chunks is 2D-array
|
||||
|
|
@ -67,7 +65,7 @@ voxel* Chunks::get(int x, int y, int z){
|
|||
return &chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
}
|
||||
|
||||
const AABB* Chunks::isObstacle(float x, float y, float z){
|
||||
const AABB* Chunks::isObstacleAt(float x, float y, float z){
|
||||
int ix = floor(x);
|
||||
int iy = floor(y);
|
||||
int iz = floor(z);
|
||||
|
|
@ -82,7 +80,7 @@ const AABB* Chunks::isObstacle(float x, float y, float z){
|
|||
if (def->rt.solid) {
|
||||
return &hitbox;
|
||||
} else {
|
||||
if (hitbox.inside({x - ix, y - iy, z - iz}))
|
||||
if (hitbox.contains({x - ix, y - iy, z - iz}))
|
||||
return &hitbox;
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -90,20 +88,27 @@ const AABB* Chunks::isObstacle(float x, float y, float z){
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool Chunks::isSolid(int x, int y, int z) {
|
||||
bool Chunks::isSolidBlock(int x, int y, int z) {
|
||||
voxel* v = get(x, y, z);
|
||||
if (v == nullptr)
|
||||
return false;
|
||||
return contentIds->getBlockDef(v->id)->rt.solid;
|
||||
}
|
||||
|
||||
bool Chunks::isReplaceable(int x, int y, int z) {
|
||||
bool Chunks::isReplaceableBlock(int x, int y, int z) {
|
||||
voxel* v = get(x, y, z);
|
||||
if (v == nullptr)
|
||||
return false;
|
||||
return contentIds->getBlockDef(v->id)->replaceable;
|
||||
}
|
||||
|
||||
bool Chunks::isObstacleBlock(int x, int y, int z) {
|
||||
voxel* v = get(x, y, z);
|
||||
if (v == nullptr)
|
||||
return false;
|
||||
return contentIds->getBlockDef(v->id)->obstacle;
|
||||
}
|
||||
|
||||
u_char8 Chunks::getLight(int x, int y, int z, int channel){
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
|
|
@ -233,7 +238,7 @@ voxel* Chunks::rayCast(vec3 start,
|
|||
|
||||
while (t <= maxDist){
|
||||
voxel* voxel = get(ix, iy, iz);
|
||||
if (!voxel){ return nullptr; }
|
||||
if (voxel == nullptr){ return nullptr; }
|
||||
|
||||
const Block* def = contentIds->getBlockDef(voxel->id);
|
||||
if (def->selectable){
|
||||
|
|
@ -338,7 +343,7 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
|
|||
|
||||
while (t <= maxDist) {
|
||||
voxel* voxel = get(ix, iy, iz);
|
||||
if (!voxel) { return vec3(px + t * dx, py + t * dy, pz + t * dz); }
|
||||
if (voxel == nullptr) { return vec3(px + t * dx, py + t * dy, pz + t * dz); }
|
||||
|
||||
const Block* def = contentIds->getBlockDef(voxel->id);
|
||||
if (def->obstacle) {
|
||||
|
|
|
|||
|
|
@ -53,9 +53,10 @@ public:
|
|||
|
||||
glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist);
|
||||
|
||||
const AABB* isObstacle(float x, float y, float z);
|
||||
bool isSolid(int x, int y, int z);
|
||||
bool isReplaceable(int x, int y, int z);
|
||||
const AABB* isObstacleAt(float x, float y, float z);
|
||||
bool isSolidBlock(int x, int y, int z);
|
||||
bool isReplaceableBlock(int x, int y, int z);
|
||||
bool isObstacleBlock(int x, int y, int z);
|
||||
|
||||
// does not move chunks inside
|
||||
void _setOffset(int x, int z);
|
||||
|
|
|
|||
|
|
@ -43,27 +43,28 @@ void ChunksStorage::remove(int x, int z) {
|
|||
}
|
||||
}
|
||||
|
||||
void verifyLoadedChunk(ContentIndices* indices, Chunk* chunk) {
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
blockid_t id = chunk->voxels[i].id;
|
||||
if (indices->getBlockDef(id) == nullptr) {
|
||||
std::cout << "corruped block detected at " << i << " of chunk ";
|
||||
std::cout << chunk->x << "x" << chunk->z;
|
||||
std::cout << " -> " << (int)id << std::endl;
|
||||
chunk->voxels[i].id = 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
World* world = level->world;
|
||||
|
||||
auto chunk = shared_ptr<Chunk>(new Chunk(x, z));
|
||||
auto chunk = std::make_shared<Chunk>(x, z);
|
||||
store(chunk);
|
||||
unique_ptr<u_char8> data(world->wfile->getChunk(chunk->x, chunk->z));
|
||||
std::unique_ptr<u_char8[]> data(world->wfile->getChunk(chunk->x, chunk->z));
|
||||
if (data) {
|
||||
chunk->decode(data.get());
|
||||
chunk->setLoaded(true);
|
||||
}
|
||||
|
||||
// Verifying and converting data
|
||||
ContentIndices* indices = level->content->indices;
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||
blockid_t id = chunk->voxels[i].id;
|
||||
if (indices->getBlockDef(id) == nullptr) {
|
||||
std::cout << "corruped block detected at " << i << " of chunk ";
|
||||
std::cout << chunk->x << "x" << chunk->z;
|
||||
std::cout << " -> " << (int)id << std::endl;
|
||||
chunk->voxels[i].id = 11;
|
||||
}
|
||||
verifyLoadedChunk(level->content->indices, chunk.get());
|
||||
}
|
||||
|
||||
light_t* lights = world->wfile->getLights(chunk->x, chunk->z);
|
||||
|
|
|
|||
|
|
@ -298,6 +298,10 @@ ImageData* Window::takeScreenshot() {
|
|||
return new ImageData(ImageFormat::rgb888, width, height, data);
|
||||
}
|
||||
|
||||
const char* Window::getClipboardText() {
|
||||
return glfwGetClipboardString(window);
|
||||
}
|
||||
|
||||
bool Window::tryToMaximize(GLFWwindow* window, GLFWmonitor* monitor) {
|
||||
glm::ivec4 windowFrame(0);
|
||||
glm::ivec4 workArea(0);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
static void clearDepth();
|
||||
static void setBgColor(glm::vec3 color);
|
||||
static double time();
|
||||
static const char* getClipboardText();
|
||||
static DisplaySettings* getSettings();
|
||||
|
||||
static glm::vec2 size() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue