VoxelEngine/src/graphics/render/BlocksPreview.cpp
Vyacheslav Ivanov 3d21b7ba6a
fix: optimization: PVS-Studio warning V810
Cached the result of 'glm::vec3(size * 0.63f)' in a temporary variable to avoid multiple identical function calls and improve performance.

Reported by: PVS-Studio
Signed-off-by: Vyacheslav Ivanov <islavaivanov76@gmail.com>
2024-08-02 05:41:47 +03:00

166 lines
6.3 KiB
C++

#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 "../core/Atlas.hpp"
#include "../core/Batch3D.hpp"
#include "../core/Framebuffer.hpp"
#include "../core/DrawContext.hpp"
#include "../core/Shader.hpp"
#include "../core/Texture.hpp"
#include "../core/Viewport.hpp"
#include <glm/ext.hpp>
std::unique_ptr<ImageData> BlocksPreview::draw(
const ContentGfxCache* cache,
Shader* shader,
Framebuffer* fbo,
Batch3D* batch,
const Block* def,
int size
){
Window::clear();
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),
cache->getRegion(id, 4), cache->getRegion(id, 5)};
glm::vec3 offset(0.1f, 0.5f, 0.1f);
switch (def->model) {
case BlockModel::none:
// something went wrong...
break;
case BlockModel::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 BlockModel::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 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->point((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0));
batch->point((points[i * 4 + 1] - poff) * pmul, glm::vec2(reg.u2, reg.v1), glm::vec4(1.0));
batch->point((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0));
batch->point((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0));
batch->point((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0));
batch->point((points[i * 4 + 3] - poff) * pmul, glm::vec2(reg.u1, reg.v2), glm::vec4(1.0));
}
batch->flush();
}
break;
case BlockModel::xsprite: {
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<Atlas> BlocksPreview::build(
const ContentGfxCache* cache,
Assets* assets,
const Content* content
) {
auto indices = content->getIndices();
size_t count = indices->blocks.count();
size_t iconSize = ITEM_ICON_SIZE;
auto shader = assets->get<Shader>("ui3d");
auto atlas = assets->get<Atlas>("blocks");
Viewport viewport(iconSize, iconSize);
DrawContext pctx(nullptr, viewport, 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;
Window::viewport(0, 0, iconSize, iconSize);
Window::setBgColor(glm::vec4(0.0f));
fbo.bind();
for (size_t i = 0; i < count; i++) {
auto def = indices->blocks.get(i);
atlas->getTexture()->bind();
builder.add(def->name, draw(cache, shader, &fbo, &batch, def, iconSize));
}
fbo.unbind();
Window::viewport(0, 0, Window::width, Window::height);
return builder.build(2);
}