diff --git a/src/coders/json.cpp b/src/coders/json.cpp index 3cfd3765..a4559771 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -465,6 +465,10 @@ JObject* Parser::parseObject() { unique_ptr obj(new JObject()); unordered_map& map = obj->map; while (peek() != '}') { + if (peek() == '#') { + skipLine(); + continue; + } string key = parseName(); char next = peek(); if (next != ':') { @@ -490,6 +494,10 @@ JArray* Parser::parseArray() { unique_ptr arr(new JArray()); vector& values = arr->values; while (peek() != ']') { + if (peek() == '#') { + skipLine(); + continue; + } values.push_back(parseValue()); char next = peek(); diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 08009520..6fd0a6f5 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -85,13 +85,18 @@ Block* ContentLoader::loadBlock(std::string name, fs::path file) { if (root->has("texture")) { std::string texture; root->str("texture", texture); - for (uint i = 0; i < 6; i++) + for (uint i = 0; i < 6; i++) { def->textureFaces[i] = texture; + } } else if (root->has("texture-faces")) { json::JArray* texarr = root->arr("texture-faces"); for (uint i = 0; i < 6; i++) { def->textureFaces[i] = texarr->str(i); } + for (uint i = 6; i < texarr->values.size(); i++) + { + def->textureMoreFaces.push_back(texarr->str(i)); + } } // block model @@ -99,6 +104,16 @@ Block* ContentLoader::loadBlock(std::string name, fs::path file) { root->str("model", model); if (model == "block") def->model = BlockModel::block; else if (model == "aabb") def->model = BlockModel::aabb; + else if (model == "custom") { + def->model = BlockModel::customfaces; + json::JArray* pointarr = root->arr("faces-points"); + for (uint i = 0; i < pointarr->values.size(); i+=3) + { + def->customfacesPoints.push_back(glm::vec3(pointarr->num(i), + pointarr->num(i+1), + pointarr->num(i + 2))); + } + } else if (model == "X") def->model = BlockModel::xsprite; else if (model == "none") def->model = BlockModel::none; else { diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index ff935f9c..5b74a129 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -23,6 +23,16 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) { sideregions[i * 6 + side] = atlas->get("notfound"); } } + for (uint side = 0; side < def->textureMoreFaces.size(); side++) + { + std::string tex = def->textureMoreFaces[side]; + if (atlas->has(tex)) { + def->customfacesExtraUVs.push_back(atlas->get(tex)); + } else { + if (atlas->has("notfound")) + def->customfacesExtraUVs.push_back(atlas->get("notfound")); + } + } } } diff --git a/src/graphics/BlocksRenderer.cpp b/src/graphics/BlocksRenderer.cpp index ae064844..0c35ddaf 100644 --- a/src/graphics/BlocksRenderer.cpp +++ b/src/graphics/BlocksRenderer.cpp @@ -147,6 +147,19 @@ void BlocksRenderer::face(const vec3& coord, index(0, 1, 2, 0, 2, 3); } +void BlocksRenderer::tetragonicFace(const vec3& coord, const vec3& p1, + const vec3& p2, const vec3& p3, const vec3& p4, + const vec3& X, + const vec3& Y, + const vec3& Z, + const UVRegion& texreg, + const vec4& tint) { + vertex(coord + (p1.x - 0.5f) * X + (p1.y - 0.5f) * Y + (p1.z - 0.5f) * Z, texreg.u1, texreg.v1, tint); + vertex(coord + (p2.x - 0.5f) * X + (p2.y - 0.5f) * Y + (p2.z - 0.5f) * Z, texreg.u2, texreg.v1, tint); + vertex(coord + (p3.x - 0.5f) * X + (p3.y - 0.5f) * Y + (p3.z - 0.5f) * Z, texreg.u2, texreg.v2, tint); + vertex(coord + (p4.x - 0.5f) * X + (p4.y - 0.5f) * Y + (p4.z - 0.5f) * Z, texreg.u1, texreg.v2, tint); + index(0, 1, 3, 1, 2, 3); +} void BlocksRenderer::blockXSprite(int x, int y, int z, const vec3& size, @@ -217,6 +230,38 @@ void BlocksRenderer::blockAABB(const ivec3& icoord, face(coord, Z*size.z, Y*size.y, -X*size.x, texfaces[0], lights); // east } +void BlocksRenderer::blockCustomFaces(const ivec3& icoord, const UVRegion(&texfaces)[6], + const Block* block, ubyte rotation, bool lights) { + const float tint = 1.0f; + vec3 X(1, 0, 0); + vec3 Y(0, 1, 0); + vec3 Z(0, 0, 1); + vec3 coord(icoord); + if (block->rotatable) { + auto& rotations = block->rotations; + auto& orient = rotations.variants[rotation]; + X = orient.axisX; + Y = orient.axisY; + Z = orient.axisZ; + } + + for (uint i = 0; i < 6; i++) + { + tetragonicFace(coord, + block->customfacesPoints[i * 4 + 0], + block->customfacesPoints[i * 4 + 1], + block->customfacesPoints[i * 4 + 2], + block->customfacesPoints[i * 4 + 3],X,Y,Z, texfaces[i], vec4(tint)); + } + for (uint i = 0; i < block->textureMoreFaces.size(); i++) { + tetragonicFace(coord, + block->customfacesPoints[i * 4 + 24], + block->customfacesPoints[i * 4 + 25], + block->customfacesPoints[i * 4 + 26], + block->customfacesPoints[i * 4 + 27], X, Y, Z, block->customfacesExtraUVs[i], vec4(tint)); + } +} + /* Fastest solid shaded blocks render method */ void BlocksRenderer::blockCube(int x, int y, int z, const UVRegion(&texfaces)[6], @@ -327,7 +372,7 @@ void BlocksRenderer::render(const voxel* voxels) { const voxel& vox = voxels[i]; blockid_t id = vox.id; const Block& def = *blockDefsCache[id]; - if (!id || def.drawGroup != drawGroup) + if (id == 0 || def.drawGroup != drawGroup) continue; const UVRegion texfaces[6]{ cache->getRegion(id, 0), cache->getRegion(id, 1), @@ -351,6 +396,10 @@ void BlocksRenderer::render(const voxel* voxels) { blockAABB(ivec3(x,y,z), texfaces, &def, vox.rotation(), !def.rt.emissive); break; } + case BlockModel::customfaces: { + blockCustomFaces(ivec3(x, y, z), texfaces, &def, vox.rotation(), !def.rt.emissive); + break; + } default: break; } diff --git a/src/graphics/BlocksRenderer.h b/src/graphics/BlocksRenderer.h index 23a380f0..176e32d3 100644 --- a/src/graphics/BlocksRenderer.h +++ b/src/graphics/BlocksRenderer.h @@ -2,6 +2,7 @@ #define GRAPHICS_BLOCKS_RENDERER_H #include +#include #include #include "UVRegion.h" #include "../typedefs.h" @@ -59,6 +60,15 @@ class BlocksRenderer { const glm::vec3& axisZ, const UVRegion& region, bool lights); + + void tetragonicFace(const glm::vec3& coord, + const glm::vec3& p1, const glm::vec3& p2, + const glm::vec3& p3, const glm::vec3& p4, + const glm::vec3& X, + const glm::vec3& Y, + const glm::vec3& Z, + const UVRegion& texreg, + const glm::vec4& tint); void blockCube(int x, int y, int z, const UVRegion(&faces)[6], const Block* block, ubyte states, bool lights); void blockAABB(const glm::ivec3& coord, @@ -67,6 +77,10 @@ class BlocksRenderer { ubyte rotation, bool lights); void blockXSprite(int x, int y, int z, const glm::vec3& size, const UVRegion& face1, const UVRegion& face2, float spread); + void blockCustomFaces(const glm::ivec3& icoord, + const UVRegion(&texfaces)[6], + const Block* block, ubyte rotation, + bool lights); bool isOpenForLight(int x, int y, int z) const; bool isOpen(int x, int y, int z, ubyte group) const; diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 80b6d35c..88e3910a 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -2,7 +2,9 @@ #define VOXELS_BLOCK_H_ #include +#include #include +#include "../graphics/UVRegion.h" #include "../maths/aabb.h" #include "../typedefs.h" @@ -61,7 +63,8 @@ enum class BlockModel { none, // invisible block, // default shape xsprite, // X-shape (grass) - aabb // box shaped as block hitbox + aabb, // box shaped as block hitbox + customfaces // set of paired triangles (usual faces) }; class Block { @@ -69,6 +72,9 @@ public: std::string const name; // 0 1 2 3 4 5 std::string textureFaces[6]; // -x,x, -y,y, -z,z + std::vector textureMoreFaces = {}; + std::vector customfacesPoints = {}; + std::vector customfacesExtraUVs = {}; unsigned char emission[4] {0, 0, 0, 0}; unsigned char drawGroup = 0; BlockModel model = BlockModel::block;