diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index f855a89d..c9f09ae2 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -224,9 +224,9 @@ void ContentLoader::loadBlock( if (auto model = BlockModel_from(modelName)) { if (*model == BlockModel::custom) { if (root.has("model-primitives")) { - loadCustomBlockModel(def, root["model-primitives"]); + def.customModelRaw = root["model-primitives"]; } else { - logger.error() << name << ": no 'model-primitives' found"; + throw std::runtime_error(name + ": no 'model-primitives' found"); } } def.model = *model; @@ -277,8 +277,6 @@ void ContentLoader::loadBlock( ); aabb.b += aabb.a; def.hitboxes = {aabb}; - } else if (!def.modelBoxes.empty()) { - def.hitboxes = def.modelBoxes; } else { def.hitboxes = {AABB()}; } @@ -350,61 +348,6 @@ void ContentLoader::loadBlock( } } -void ContentLoader::loadCustomBlockModel(Block& def, const dv::value& primitives) { - if (primitives.has("aabbs")) { - const auto& modelboxes = primitives["aabbs"]; - for (uint i = 0; i < modelboxes.size(); i++) { - // Parse aabb - const auto& boxarr = modelboxes[i]; - AABB modelbox; - modelbox.a = glm::vec3( - boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber() - ); - modelbox.b = glm::vec3( - boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber() - ); - modelbox.b += modelbox.a; - def.modelBoxes.push_back(modelbox); - - if (boxarr.size() == 7) { - for (uint j = 6; j < 12; j++) { - def.modelTextures.emplace_back(boxarr[6].asString()); - } - } else if (boxarr.size() == 12) { - for (uint j = 6; j < 12; j++) { - def.modelTextures.emplace_back(boxarr[j].asString()); - } - } else { - for (uint j = 6; j < 12; j++) { - def.modelTextures.emplace_back("notfound"); - } - } - } - } - if (primitives.has("tetragons")) { - const auto& modeltetragons = primitives["tetragons"]; - for (uint i = 0; i < modeltetragons.size(); i++) { - // Parse tetragon to points - const auto& tgonobj = modeltetragons[i]; - glm::vec3 p1( - tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber() - ); - glm::vec3 xw( - tgonobj[3].asNumber(), tgonobj[4].asNumber(), tgonobj[5].asNumber() - ); - glm::vec3 yh( - tgonobj[6].asNumber(), tgonobj[7].asNumber(), tgonobj[8].asNumber() - ); - def.modelExtraPoints.push_back(p1); - def.modelExtraPoints.push_back(p1 + xw); - def.modelExtraPoints.push_back(p1 + xw + yh); - def.modelExtraPoints.push_back(p1 + yh); - - def.modelTextures.emplace_back(tgonobj[9].asString()); - } - } -} - void ContentLoader::loadItem( ItemDef& def, const std::string& name, const fs::path& file ) { diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index 1b011cbb..22cb33ef 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -42,7 +42,6 @@ class ContentLoader { GeneratorDef& def, const std::string& full, const std::string& name ); - static void loadCustomBlockModel(Block& def, const dv::value& primitives); static void loadBlockMaterial(BlockMaterial& def, const fs::path& file); void loadBlock( Block& def, const std::string& name, const fs::path& file diff --git a/src/engine.cpp b/src/engine.cpp index 0cfc6733..a75d90ff 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -286,6 +286,18 @@ void Engine::loadAssets() { assets = std::move(new_assets); if (content) { + for (auto& [name, def] : content->blocks.getDefs()) { + if (def->model == BlockModel::custom) { + assets->store( + std::make_unique( + ModelsGenerator::loadCustomBlockModel( + def->customModelRaw, *assets, !def->shadeless + ) + ), + name + ".model" + ); + } + } for (auto& [name, def] : content->items.getDefs()) { assets->store( std::make_unique( diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index f45259e1..1fccefcf 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -1,24 +1,25 @@ #include "ContentGfxCache.hpp" -#include "UiDocument.hpp" +#include +#include "UiDocument.hpp" #include "assets/Assets.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" #include "core_defs.hpp" +#include "graphics/commons/Model.hpp" #include "graphics/core/Atlas.hpp" #include "maths/UVRegion.hpp" #include "voxels/Block.hpp" -#include - -ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) : content(content) { +ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) + : content(content) { auto indices = content->getIndices(); sideregions = std::make_unique(indices->blocks.count() * 6); auto atlas = assets->get("blocks"); - + const auto& blocks = indices->blocks.getIterable(); - for (uint i = 0; i < blocks.size(); i++) { + for (blockid_t i = 0; i < blocks.size(); i++) { auto def = blocks[i]; for (uint side = 0; side < 6; side++) { const std::string& tex = def->textureFaces[side]; @@ -28,13 +29,9 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) : conte sideregions[i * 6 + side] = atlas->get(TEXTURE_NOTFOUND); } } - for (uint side = 0; side < def->modelTextures.size(); side++) { - const std::string& tex = def->modelTextures[side]; - if (atlas->has(tex)) { - def->modelUVs.push_back(atlas->get(tex)); - } else if (atlas->has(TEXTURE_NOTFOUND)) { - def->modelUVs.push_back(atlas->get(TEXTURE_NOTFOUND)); - } + if (def->model == BlockModel::custom) { + models[def->rt.id] = + assets->require(def->name + ".model"); } } } @@ -44,3 +41,11 @@ ContentGfxCache::~ContentGfxCache() = default; const Content* ContentGfxCache::getContent() const { return content; } + +const model::Model& ContentGfxCache::getModel(blockid_t id) const { + const auto& found = models.find(id); + if (found == models.end()) { + throw std::runtime_error("model not found"); + } + return found->second; +} diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index 8d92d1a3..a268b2f6 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -3,15 +3,22 @@ #include "typedefs.hpp" #include +#include +#include class Content; class Assets; struct UVRegion; +namespace model { + struct Model; +} + class ContentGfxCache { const Content* content; // array of block sides uv regions (6 per block) std::unique_ptr sideregions; + std::unordered_map models; public: ContentGfxCache(const Content* content, Assets* assets); ~ContentGfxCache(); @@ -19,6 +26,8 @@ public: inline const UVRegion& getRegion(blockid_t id, int side) const { return sideregions[id * 6 + side]; } + + const model::Model& getModel(blockid_t id) const; const Content* getContent() const; }; diff --git a/src/graphics/commons/Model.cpp b/src/graphics/commons/Model.cpp index 3595a8e2..12888d32 100644 --- a/src/graphics/commons/Model.cpp +++ b/src/graphics/commons/Model.cpp @@ -36,7 +36,7 @@ void Mesh::addPlane( vertices.push_back({pos-right-up, {uv.u1, uv.v1}, norm}); vertices.push_back({pos+right+up, {uv.u2, uv.v2}, norm}); - vertices.push_back({pos-right+up, {uv.u1, uv.u2}, norm}); + vertices.push_back({pos-right+up, {uv.u1, uv.v2}, norm}); } void Mesh::addBox(const glm::vec3& pos, const glm::vec3& size) { diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index 4c772c86..637c5635 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -64,41 +64,41 @@ std::unique_ptr BlocksPreview::draw( { glm::vec3 pmul = glm::vec3(size * 0.63f); glm::vec3 hitbox = glm::vec3(); - for (const auto& box : def.modelBoxes) { - hitbox = glm::max(hitbox, box.size()); - } + // for (const auto& box : def.modelBoxes) { + // hitbox = glm::max(hitbox, box.size()); + // } offset.y += (1.0f - hitbox).y * 0.5f; shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); - for (size_t i = 0; i < def.modelBoxes.size(); i++) { - const UVRegion (&boxtexfaces)[6] = { - def.modelUVs[i * 6], - def.modelUVs[i * 6 + 1], - def.modelUVs[i * 6 + 2], - def.modelUVs[i * 6 + 3], - def.modelUVs[i * 6 + 4], - def.modelUVs[i * 6 + 5] - }; - batch->cube( - def.modelBoxes[i].a * glm::vec3(1.0f, 1.0f, -1.0f) * pmul, - def.modelBoxes[i].size() * pmul, - boxtexfaces, glm::vec4(1.0f), !def.rt.emissive - ); - } + // for (size_t i = 0; i < def.modelBoxes.size(); i++) { + // const UVRegion (&boxtexfaces)[6] = { + // def.modelUVs[i * 6], + // def.modelUVs[i * 6 + 1], + // def.modelUVs[i * 6 + 2], + // def.modelUVs[i * 6 + 3], + // def.modelUVs[i * 6 + 4], + // def.modelUVs[i * 6 + 5] + // }; + // batch->cube( + // def.modelBoxes[i].a * glm::vec3(1.0f, 1.0f, -1.0f) * pmul, + // def.modelBoxes[i].size() * pmul, + // boxtexfaces, glm::vec4(1.0f), !def.rt.emissive + // ); + // } - auto& points = def.modelExtraPoints; - glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f); + // auto& points = def.modelExtraPoints; + // glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f); - for (size_t i = 0; i < def.modelExtraPoints.size() / 4; i++) { - const UVRegion& reg = def.modelUVs[def.modelBoxes.size() * 6 + i]; + // for (size_t i = 0; i < def.modelExtraPoints.size() / 4; i++) { + // const UVRegion& reg = def.modelUVs[def.modelBoxes.size() * 6 + i]; - batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0)); - batch->vertex((points[i * 4 + 1] - poff) * pmul, glm::vec2(reg.u2, reg.v1), glm::vec4(1.0)); - batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0)); - batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0)); - batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0)); - batch->vertex((points[i * 4 + 3] - poff) * pmul, glm::vec2(reg.u1, reg.v2), glm::vec4(1.0)); - } - batch->flush(); + // batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0)); + // batch->vertex((points[i * 4 + 1] - poff) * pmul, glm::vec2(reg.u2, reg.v1), glm::vec4(1.0)); + // batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0)); + // batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0)); + // batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0)); + // batch->vertex((points[i * 4 + 3] - poff) * pmul, glm::vec2(reg.u1, reg.v2), glm::vec4(1.0)); + // } + // batch->flush(); } break; case BlockModel::xsprite: { diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 651675c5..c3d7a33b 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -1,6 +1,7 @@ #include "BlocksRenderer.hpp" #include "graphics/core/Mesh.hpp" +#include "graphics/commons/Model.hpp" #include "maths/UVRegion.hpp" #include "constants.hpp" #include "content/Content.hpp" @@ -303,6 +304,7 @@ void BlocksRenderer::blockAABB( } } +#include void BlocksRenderer::blockCustomModel( const glm::ivec3& icoord, const Block* block, ubyte rotation, bool lights, bool ao ) { @@ -319,29 +321,31 @@ void BlocksRenderer::blockCustomModel( Z = orient.axisZ; } - for (size_t i = 0; i < block->modelBoxes.size(); i++) { - AABB box = block->modelBoxes[i]; - auto size = box.size(); - if (block->rotatable) { - orient.transform(box); + const auto& model = cache->getModel(block->rt.id); + for (const auto& mesh : model.meshes) { + if (vertexOffset + BlocksRenderer::VERTEX_SIZE * mesh.vertices.size() > capacity) { + overflow = true; + return; + } + int i = 0; + for (const auto& vertex : mesh.vertices) { + if ((i++) % 6 < 3) { + // continue; + } + float d = glm::dot(glm::normalize(vertex.normal), SUN_VECTOR); + d = 0.8f + d * 0.2f; + const auto& n = vertex.normal; + vertexAO( + coord + vertex.coord - 0.5f, + vertex.uv.x, + vertex.uv.y, + glm::vec4(1, 1, 1, 0), + glm::vec3(n.x, -n.z, n.y), + glm::vec3(0, 1, 0), + n + ); + indexBuffer[indexSize++] = indexOffset++; } - glm::vec3 center_coord = coord - glm::vec3(0.5f) + box.center(); - faceAO(center_coord, X * size.x, Y * size.y, Z * size.z, block->modelUVs[i * 6 + 5], lights); // north - faceAO(center_coord, -X * size.x, Y * size.y, -Z * size.z, block->modelUVs[i * 6 + 4], lights); // south - faceAO(center_coord, X * size.x, -Z * size.z, Y * size.y, block->modelUVs[i * 6 + 3], lights); // top - faceAO(center_coord, -X * size.x, -Z * size.z, -Y * size.y, block->modelUVs[i * 6 + 2], lights); // bottom - faceAO(center_coord, -Z * size.z, Y * size.y, X * size.x, block->modelUVs[i * 6 + 1], lights); // west - faceAO(center_coord, Z * size.z, Y * size.y, -X * size.x, block->modelUVs[i * 6 + 0], lights); // east - } - - for (size_t i = 0; i < block->modelExtraPoints.size()/4; i++) { - tetragonicFace(coord, - block->modelExtraPoints[i * 4 + 0], - block->modelExtraPoints[i * 4 + 1], - block->modelExtraPoints[i * 4 + 2], - block->modelExtraPoints[i * 4 + 3], - X, Y, Z, - block->modelUVs[block->modelBoxes.size()*6 + i], lights); } } diff --git a/src/graphics/render/ModelsGenerator.cpp b/src/graphics/render/ModelsGenerator.cpp index 7da57d24..84faa380 100644 --- a/src/graphics/render/ModelsGenerator.cpp +++ b/src/graphics/render/ModelsGenerator.cpp @@ -59,13 +59,14 @@ model::Model ModelsGenerator::fromCustom( for (size_t i = 0; i < modelBoxes.size(); i++) { auto& mesh = model.addMesh("blocks:" + modelTextures[i * 6]); mesh.lighting = lighting; - const UVRegion(&boxtexfaces)[6] = { + const UVRegion boxtexfaces[6] = { get_region_for(modelTextures[i * 6], assets), get_region_for(modelTextures[i * 6 + 1], assets), get_region_for(modelTextures[i * 6 + 2], assets), get_region_for(modelTextures[i * 6 + 3], assets), get_region_for(modelTextures[i * 6 + 4], assets), - get_region_for(modelTextures[i * 6 + 5], assets)}; + get_region_for(modelTextures[i * 6 + 5], assets) + }; mesh.addBox( modelBoxes[i].center(), modelBoxes[i].size() * 0.5f, boxtexfaces ); @@ -112,13 +113,7 @@ model::Model ModelsGenerator::generate( "blocks:" + blockDef.textureFaces.at(0), assets ); } else if (blockDef.model == BlockModel::custom) { - model = fromCustom( - assets, - blockDef.modelBoxes, - blockDef.modelTextures, - blockDef.modelExtraPoints, - !blockDef.shadeless - ); + model = assets.require(blockDef.name+".model"); for (auto& mesh : model.meshes) { mesh.scale(glm::vec3(0.3f)); } @@ -146,3 +141,67 @@ model::Model ModelsGenerator::generate( return model::Model(); } } + +model::Model ModelsGenerator::loadCustomBlockModel( + const dv::value& primitives, const Assets& assets, bool lighting +) { + std::vector modelBoxes; + std::vector modelTextures; + std::vector modelExtraPoints; + + if (primitives.has("aabbs")) { + const auto& modelboxes = primitives["aabbs"]; + for (uint i = 0; i < modelboxes.size(); i++) { + // Parse aabb + const auto& boxarr = modelboxes[i]; + AABB modelbox; + modelbox.a = glm::vec3( + boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber() + ); + modelbox.b = glm::vec3( + boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber() + ); + modelbox.b += modelbox.a; + modelBoxes.push_back(modelbox); + + if (boxarr.size() == 7) { + for (uint j = 6; j < 12; j++) { + modelTextures.emplace_back(boxarr[6].asString()); + } + } else if (boxarr.size() == 12) { + for (uint j = 6; j < 12; j++) { + modelTextures.emplace_back(boxarr[j].asString()); + } + } else { + for (uint j = 6; j < 12; j++) { + modelTextures.emplace_back("notfound"); + } + } + } + } + if (primitives.has("tetragons")) { + const auto& modeltetragons = primitives["tetragons"]; + for (uint i = 0; i < modeltetragons.size(); i++) { + // Parse tetragon to points + const auto& tgonobj = modeltetragons[i]; + glm::vec3 p1( + tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber() + ); + glm::vec3 xw( + tgonobj[3].asNumber(), tgonobj[4].asNumber(), tgonobj[5].asNumber() + ); + glm::vec3 yh( + tgonobj[6].asNumber(), tgonobj[7].asNumber(), tgonobj[8].asNumber() + ); + modelExtraPoints.push_back(p1); + modelExtraPoints.push_back(p1 + xw); + modelExtraPoints.push_back(p1 + xw + yh); + modelExtraPoints.push_back(p1 + yh); + + modelTextures.emplace_back(tgonobj[9].asString()); + } + } + return fromCustom( + assets, modelBoxes, modelTextures, modelExtraPoints, lighting + ); +} diff --git a/src/graphics/render/ModelsGenerator.hpp b/src/graphics/render/ModelsGenerator.hpp index ee19c541..52bc56d0 100644 --- a/src/graphics/render/ModelsGenerator.hpp +++ b/src/graphics/render/ModelsGenerator.hpp @@ -2,10 +2,12 @@ #include "graphics/commons/Model.hpp" #include "maths/aabb.hpp" +#include "data/dv.hpp" struct ItemDef; class Assets; class Content; +struct Block; class ModelsGenerator { public: @@ -20,4 +22,8 @@ public: const std::vector& points, bool lighting ); + + static model::Model loadCustomBlockModel( + const dv::value& primitives, const Assets& assets, bool lighting + ); }; diff --git a/src/maths/UVRegion.hpp b/src/maths/UVRegion.hpp index f7bdb2d0..b11db4aa 100644 --- a/src/maths/UVRegion.hpp +++ b/src/maths/UVRegion.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include struct UVRegion { float u1; @@ -33,4 +34,10 @@ struct UVRegion { u2 = u1 + uvw * w; v2 = v1 + uvh * h; } + + inline glm::vec2 apply(const glm::vec2& uv) { + float w = getWidth(); + float h = getHeight(); + return glm::vec2(u1 + uv.x / w, v1 + uv.y / h); + } }; diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index d94f6c82..86af4374 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -114,12 +114,8 @@ Block::Block(std::string name, const std::string& texture) void Block::cloneTo(Block& dst) { dst.caption = caption; for (int i = 0; i < 6; i++) { - dst.textureFaces[i] = textureFaces[i]; + dst.textureFaces[i] = textureFaces[i]; } - dst.modelTextures = modelTextures; - dst.modelBoxes = modelBoxes; - dst.modelExtraPoints = modelExtraPoints; - dst.modelUVs = modelUVs; dst.material = material; std::copy(&emission[0], &emission[3], dst.emission); dst.size = size; @@ -143,7 +139,10 @@ void Block::cloneTo(Block& dst) { dst.inventorySize = inventorySize; dst.tickInterval = tickInterval; dst.overlayTexture = overlayTexture; - dst.particles = std::make_unique(*particles); + if (particles) { + dst.particles = std::make_unique(*particles); + } + dst.customModelRaw = customModelRaw; } static std::set> RESERVED_BLOCK_FIELDS { diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index d812e48f..74666a38 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -6,6 +6,7 @@ #include #include +#include "data/dv.hpp" #include "maths/UVRegion.hpp" #include "maths/aabb.hpp" #include "typedefs.hpp" @@ -116,12 +117,6 @@ public: /// @brief Textures set applied to block sides std::array textureFaces; // -x,x, -y,y, -z,z - std::vector modelTextures = {}; - std::vector modelBoxes = {}; - // initially made for tetragons - std::vector modelExtraPoints = {}; - std::vector modelUVs = {}; // boxes' tex-UVs also there - /// @brief id of used BlockMaterial, may specify non-existing material std::string material = DEFAULT_MATERIAL; @@ -137,6 +132,9 @@ public: /// @brief Block model type BlockModel model = BlockModel::block; + /// @brief Custom model raw data + dv::value customModelRaw = nullptr; + /// @brief Does the block passing lights into itself bool lightPassing = false; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index a380aeda..53c436f3 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -597,8 +597,7 @@ glm::vec3 Chunks::rayCastToObstacle( if (def.obstacle) { if (!def.rt.solid) { const std::vector& hitboxes = - def.rotatable ? def.rt.hitboxes[voxel->state.rotation] - : def.modelBoxes; + def.rt.hitboxes[voxel->state.rotation]; scalar_t distance; glm::ivec3 norm;