diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 68b0289c..a7d258ec 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -19,10 +19,10 @@ #include "graphics/core/Atlas.hpp" #include "graphics/core/Font.hpp" #include "graphics/core/ImageData.hpp" -#include "graphics/core/Model.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" #include "graphics/core/TextureAnimation.hpp" +#include "graphics/commons/Model.hpp" #include "objects/rigging.hpp" #include "util/stringutil.hpp" #include "Assets.hpp" diff --git a/src/coders/obj.cpp b/src/coders/obj.cpp index 19d82f8c..182415df 100644 --- a/src/coders/obj.cpp +++ b/src/coders/obj.cpp @@ -1,6 +1,6 @@ #include "obj.hpp" -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" #include "commons.hpp" using namespace model; diff --git a/src/coders/vec3.cpp b/src/coders/vec3.cpp index 63edc21e..7d0c8c17 100644 --- a/src/coders/vec3.cpp +++ b/src/coders/vec3.cpp @@ -5,7 +5,7 @@ #include "byte_utils.hpp" #include "util/data_io.hpp" #include "util/stringutil.hpp" -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" inline constexpr int VERSION = 1; diff --git a/src/coders/vec3.hpp b/src/coders/vec3.hpp index 1aa3ea9d..dd0bee22 100644 --- a/src/coders/vec3.hpp +++ b/src/coders/vec3.hpp @@ -8,7 +8,7 @@ #include "typedefs.hpp" #include "util/Buffer.hpp" -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" /// See /doc/specs/vec3_model_spec.md namespace vec3 { diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index f855a89d..a801500e 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -219,19 +219,26 @@ void ContentLoader::loadBlock( } // block model - std::string modelName; - root.at("model").get(modelName); - if (auto model = BlockModel_from(modelName)) { + std::string modelTypeName; + root.at("model").get(modelTypeName); + root.at("model-name").get(def.modelName); + if (auto model = BlockModel_from(modelTypeName)) { if (*model == BlockModel::custom) { if (root.has("model-primitives")) { - loadCustomBlockModel(def, root["model-primitives"]); - } else { - logger.error() << name << ": no 'model-primitives' found"; + def.customModelRaw = root["model-primitives"]; + } else if (def.modelName.empty()) { + throw std::runtime_error(name + ": no 'model-primitives' or 'model-name' found"); + } + for (uint i = 0; i < 6; i++) { + std::string& texture = def.textureFaces[i]; + if (texture == TEXTURE_NOTFOUND) { + texture = ""; + } } } def.model = *model; - } else if (!modelName.empty()) { - logger.error() << "unknown model " << modelName; + } else if (!modelTypeName.empty()) { + logger.error() << "unknown model " << modelTypeName; def.model = BlockModel::none; } @@ -277,8 +284,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 +355,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..c5bae880 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -286,6 +286,21 @@ void Engine::loadAssets() { assets = std::move(new_assets); if (content) { + for (auto& [name, def] : content->blocks.getDefs()) { + if (def->model == BlockModel::custom) { + if (def->modelName.empty()) { + assets->store( + std::make_unique( + ModelsGenerator::loadCustomBlockModel( + def->customModelRaw, *assets, !def->shadeless + ) + ), + name + ".model" + ); + def->modelName = def->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..8890a24e 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -1,7 +1,8 @@ #include "ContentGfxCache.hpp" -#include "UiDocument.hpp" +#include +#include "UiDocument.hpp" #include "assets/Assets.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" @@ -10,15 +11,14 @@ #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 +28,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->modelName); } } } @@ -44,3 +40,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..3d3161d3 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -3,15 +3,24 @@ #include "typedefs.hpp" #include +#include +#include + +#include "graphics/commons/Model.hpp" 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 +28,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/core/Model.cpp b/src/graphics/commons/Model.cpp similarity index 97% rename from src/graphics/core/Model.cpp rename to src/graphics/commons/Model.cpp index 3595a8e2..12888d32 100644 --- a/src/graphics/core/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/core/Model.hpp b/src/graphics/commons/Model.hpp similarity index 100% rename from src/graphics/core/Model.hpp rename to src/graphics/commons/Model.hpp diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index 4c772c86..f6816bde 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -60,47 +60,24 @@ std::unique_ptr BlocksPreview::draw( } batch->flush(); break; - case BlockModel::custom: - { - 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()); - } - 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 - ); - } - - 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]; - - 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)); + case BlockModel::custom:{ + glm::vec3 pmul = glm::vec3(size * 0.63f); + glm::vec3 hitbox = glm::vec3(1.0f); + glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f); + offset.y += (1.0f - hitbox).y * 0.5f; + shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); + const auto& model = cache->getModel(def.rt.id); + + for (const auto& mesh : model.meshes) { + for (const auto& vertex : mesh.vertices) { + float d = glm::dot(glm::normalize(vertex.normal), glm::vec3(0.2, 0.8, 0.4)); + d = 0.8f + d * 0.2f; + batch->vertex((vertex.coord - poff)*pmul, vertex.uv, glm::vec4(d, d, d, 1.0f)); } batch->flush(); } break; + } case BlockModel::xsprite: { shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f)); diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 651675c5..f2fa5c6d 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" @@ -180,40 +181,6 @@ void BlocksRenderer::face( index(0, 1, 2, 0, 2, 3); } -void BlocksRenderer::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, - bool lights -) { - const auto fp1 = (p1.x - 0.5f) * X + (p1.y - 0.5f) * Y + (p1.z - 0.5f) * Z; - const auto fp2 = (p2.x - 0.5f) * X + (p2.y - 0.5f) * Y + (p2.z - 0.5f) * Z; - const auto fp3 = (p3.x - 0.5f) * X + (p3.y - 0.5f) * Y + (p3.z - 0.5f) * Z; - const auto fp4 = (p4.x - 0.5f) * X + (p4.y - 0.5f) * Y + (p4.z - 0.5f) * Z; - - glm::vec4 tint(1.0f); - if (lights) { - auto dir = glm::cross(fp2 - fp1, fp3 - fp1); - auto normal = glm::normalize(dir); - - float d = glm::dot(normal, SUN_VECTOR); - d = 0.8f + d * 0.2f; - tint *= d; - tint *= pickLight(coord); - // debug normal - // tint.x = normal.x * 0.5f + 0.5f; - // tint.y = normal.y * 0.5f + 0.5f; - // tint.z = normal.z * 0.5f + 0.5f; - } - vertex(coord + fp1, texreg.u1, texreg.v1, tint); - vertex(coord + fp2, texreg.u2, texreg.v1, tint); - vertex(coord + fp3, texreg.u2, texreg.v2, tint); - vertex(coord + fp4, texreg.u1, texreg.v2, tint); - index(0, 1, 3, 1, 2, 3); -} - void BlocksRenderer::blockXSprite( int x, int y, int z, const glm::vec3& size, @@ -319,29 +286,30 @@ 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) { + auto n = + vertex.normal.x * X + vertex.normal.y * Y + vertex.normal.z * Z; + float d = glm::dot(glm::normalize(n), SUN_VECTOR); + d = 0.8f + d * 0.2f; + const auto& vcoord = vertex.coord - 0.5f; + vertexAO( + coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z, + vertex.uv.x, + vertex.uv.y, + glm::vec4(1, 1, 1, 1), + glm::vec3(1, 0, 0), + 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/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 121190f0..3890349a 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -82,16 +82,6 @@ class BlocksRenderer { 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, - bool lights - ); void blockCube( const glm::ivec3& coord, const UVRegion(&faces)[6], diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index 42ceb921..48133ef9 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -1,8 +1,8 @@ #include "ModelBatch.hpp" #include "assets/assets_util.hpp" +#include "graphics/commons/Model.hpp" #include "graphics/core/Mesh.hpp" -#include "graphics/core/Model.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Texture.hpp" #include "assets/Assets.hpp" diff --git a/src/graphics/render/ModelsGenerator.cpp b/src/graphics/render/ModelsGenerator.cpp index 705cabd3..a1283bac 100644 --- a/src/graphics/render/ModelsGenerator.cpp +++ b/src/graphics/render/ModelsGenerator.cpp @@ -48,6 +48,60 @@ static inline UVRegion get_region_for( return texreg.region; } +model::Model ModelsGenerator::fromCustom( + const Assets& assets, + const std::vector& modelBoxes, + const std::vector& modelTextures, + const std::vector& points, + bool lighting +) { + auto model = model::Model(); + for (size_t i = 0; i < modelBoxes.size(); i++) { + auto& mesh = model.addMesh("blocks:" + modelTextures[i * 6]); + mesh.lighting = lighting; + 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) + }; + mesh.addBox( + modelBoxes[i].center(), modelBoxes[i].size() * 0.5f, boxtexfaces + ); + } + glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f); + glm::vec3 norm {0, 1, 0}; + for (size_t i = 0; i < points.size() / 4; i++) { + auto texture = "blocks:" + modelTextures[modelBoxes.size() * 6 + i]; + + auto& mesh = model.addMesh(texture); + mesh.lighting = lighting; + + auto reg = get_region_for(texture, assets); + mesh.vertices.push_back( + {points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v1), norm} + ); + mesh.vertices.push_back( + {points[i * 4 + 1] - poff, glm::vec2(reg.u2, reg.v1), norm} + ); + mesh.vertices.push_back( + {points[i * 4 + 2] - poff, glm::vec2(reg.u2, reg.v2), norm} + ); + mesh.vertices.push_back( + {points[i * 4 + 3] - poff, glm::vec2(reg.u1, reg.v1), norm} + ); + mesh.vertices.push_back( + {points[i * 4 + 4] - poff, glm::vec2(reg.u2, reg.v2), norm} + ); + mesh.vertices.push_back( + {points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v2), norm} + ); + } + return model; +} + model::Model ModelsGenerator::generate( const ItemDef& def, const Content& content, const Assets& assets ) { @@ -59,55 +113,7 @@ model::Model ModelsGenerator::generate( "blocks:" + blockDef.textureFaces.at(0), assets ); } else if (blockDef.model == BlockModel::custom) { - model = model::Model(); - for (size_t i = 0; i < blockDef.modelBoxes.size(); i++) { - auto& mesh = - model.addMesh("blocks:" + blockDef.modelTextures[i * 6]); - mesh.lighting = !blockDef.shadeless; - const UVRegion (&boxtexfaces)[6] = { - get_region_for(blockDef.modelTextures[i * 6], assets), - get_region_for(blockDef.modelTextures[i * 6 + 1], assets), - get_region_for(blockDef.modelTextures[i * 6 + 2], assets), - get_region_for(blockDef.modelTextures[i * 6 + 3], assets), - get_region_for(blockDef.modelTextures[i * 6 + 4], assets), - get_region_for(blockDef.modelTextures[i * 6 + 5], assets) - }; - mesh.addBox( - blockDef.modelBoxes[i].center(), - blockDef.modelBoxes[i].size()*0.5f, boxtexfaces - ); - } - const auto& points = blockDef.modelExtraPoints; - glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f); - glm::vec3 norm {0, 1, 0}; - for (size_t i = 0; i < blockDef.modelExtraPoints.size() / 4; i++) { - auto texture = - "blocks:" + - blockDef.modelTextures[blockDef.modelBoxes.size() * 6 + i]; - - auto& mesh = model.addMesh(texture); - mesh.lighting = !blockDef.shadeless; - - auto reg = get_region_for(texture, assets); - mesh.vertices.push_back( - {points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v1), norm} - ); - mesh.vertices.push_back( - {points[i * 4 + 1] - poff, glm::vec2(reg.u2, reg.v1), norm} - ); - mesh.vertices.push_back( - {points[i * 4 + 2] - poff, glm::vec2(reg.u2, reg.v2), norm} - ); - mesh.vertices.push_back( - {points[i * 4 + 3] - poff, glm::vec2(reg.u1, reg.v1), norm} - ); - mesh.vertices.push_back( - {points[i * 4 + 4] - poff, glm::vec2(reg.u2, reg.v2), norm} - ); - mesh.vertices.push_back( - {points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v2), norm} - ); - } + model = assets.require(blockDef.modelName); for (auto& mesh : model.meshes) { mesh.scale(glm::vec3(0.3f)); } @@ -135,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 ec7ea873..52bc56d0 100644 --- a/src/graphics/render/ModelsGenerator.hpp +++ b/src/graphics/render/ModelsGenerator.hpp @@ -1,14 +1,29 @@ #pragma once -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" +#include "maths/aabb.hpp" +#include "data/dv.hpp" struct ItemDef; class Assets; class Content; +struct Block; class ModelsGenerator { public: static model::Model generate( const ItemDef& def, const Content& content, const Assets& assets ); + + static model::Model fromCustom( + const Assets& assets, + const std::vector& modelBoxes, + const std::vector& modelTextures, + const std::vector& points, + bool lighting + ); + + static model::Model loadCustomBlockModel( + const dv::value& primitives, const Assets& assets, bool lighting + ); }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 89b5474b..565f1c42 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -31,12 +31,12 @@ #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" +#include "graphics/commons/Model.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/LineBatch.hpp" #include "graphics/core/Mesh.hpp" -#include "graphics/core/Model.hpp" #include "graphics/core/PostProcessing.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" 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/objects/Entities.cpp b/src/objects/Entities.cpp index 7726ce5c..ba7b0eec 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -10,7 +10,7 @@ #include "engine.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/LineBatch.hpp" -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" #include "graphics/render/ModelBatch.hpp" #include "logic/scripting/scripting.hpp" #include "maths/FrustumCulling.hpp" diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 92912f01..8a31aeb8 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -3,7 +3,7 @@ #include "assets/Assets.hpp" #include "coders/json.hpp" #include "data/dv_util.hpp" -#include "graphics/core/Model.hpp" +#include "graphics/commons/Model.hpp" #include "graphics/render/ModelBatch.hpp" #define GLM_ENABLE_EXPERIMENTAL 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..26b38469 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,11 @@ public: /// @brief Block model type BlockModel model = BlockModel::block; + /// @brief Custom model raw data + dv::value customModelRaw = nullptr; + + std::string modelName = ""; + /// @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;