#include "BlocksPreview.hpp" #include "assets/Assets.hpp" #include "constants.hpp" #include "content/Content.hpp" #include "frontend/ContentGfxCache.hpp" #include "voxels/Block.hpp" #include "window/Camera.hpp" #include "window/Window.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" #include "graphics/commons/Model.hpp" #include std::unique_ptr BlocksPreview::draw( const ContentGfxCache& cache, Shader& shader, const Framebuffer& fbo, Batch3D& batch, const Block& def, int size ){ display::clear(); blockid_t id = def.rt.id; const UVRegion texfaces[6] { cache.getRegion(id, 0, 0, true), cache.getRegion(id, 0, 1, true), cache.getRegion(id, 0, 2, true), cache.getRegion(id, 0, 3, true), cache.getRegion(id, 0, 4, true), cache.getRegion(id, 0, 5, true)}; glm::vec3 offset(0.1f, 0.5f, 0.1f); switch (def.defaults.model.type) { case BlockModelType::NONE: // something went wrong... break; case BlockModelType::BLOCK: shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); batch.blockCube(glm::vec3(size * 0.63f), texfaces, glm::vec4(1.0f), !def.rt.emissive); batch.flush(); break; case BlockModelType::AABB: { glm::vec3 hitbox {}; for (const auto& box : def.hitboxes) { hitbox = glm::max(hitbox, box.size()); } offset = glm::vec3(1, 1, 0.0f); shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); glm::vec3 scaledSize = glm::vec3(size * 0.63f); batch.cube( -hitbox * scaledSize * 0.5f * glm::vec3(1,1,-1), hitbox * scaledSize, texfaces, glm::vec4(1.0f), !def.rt.emissive ); } batch.flush(); break; case BlockModelType::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, 0); 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 BlockModelType::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)); 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], glm::vec4(1.0f) ); batch.flush(); break; } } return fbo.getTexture()->readData(); } std::unique_ptr BlocksPreview::build( Window& window, const ContentGfxCache& cache, const Assets& assets, const ContentIndices& indices ) { size_t count = indices.blocks.count(); size_t iconSize = ITEM_ICON_SIZE; auto& shader = assets.require("ui3d"); const auto& atlas = assets.require("blocks"); DrawContext pctx(nullptr, window, nullptr); DrawContext ctx = pctx.sub(); ctx.setCullFace(true); ctx.setDepthTest(true); Framebuffer fbo(iconSize, iconSize, true); Batch3D batch(1024); batch.begin(); shader.use(); shader.uniformMatrix("u_projview", glm::ortho(0.0f, float(iconSize), 0.0f, float(iconSize), -100.0f, 100.0f) * glm::lookAt(glm::vec3(0.57735f), glm::vec3(0.0f), glm::vec3(0, 1, 0))); AtlasBuilder builder; ctx.setViewport({iconSize, iconSize}); display::setBgColor(glm::vec4(0.0f)); fbo.bind(); for (size_t i = 0; i < count; i++) { auto& def = indices.blocks.require(i); atlas.getTexture()->bind(); builder.add(def.name, draw(cache, shader, fbo, batch, def, iconSize)); } fbo.unbind(); return builder.build(ATLAS_EXTRUSION); }