#include #include "entities/camera.hpp" #include "rendering/gl_renderer.hpp" #include "utils/globals.hpp" #include "utils/light.hpp" #include "utils/math.hpp" #include "wall/wall.hpp" namespace Nimbin { namespace { static void build_Wall(Wall::Surfaces::Quad& out, Wall::Position pos, float world_scale, SDL_FColor col) { const float ws = world_scale; const float inset = 0.01f; Vec3 corners[4]; Vec3 normal; switch (pos) { case Wall::Position::PosX: { float x = ws - inset; corners[0] = { x, -ws, -ws }; // bottom-back corners[1] = { x, -ws, ws }; // bottom-front corners[2] = { x, ws, ws }; // top-front corners[3] = { x, ws, -ws }; // top-back normal = { -1.0, 0.0, 0.0 }; break; } case Wall::Position::NegX: { float x = -ws + inset; corners[0] = { x, -ws, ws }; corners[1] = { x, -ws, -ws }; corners[2] = { x, ws, -ws }; corners[3] = { x, ws, ws }; normal = { 1.0, 0.0, 0.0 }; break; } case Wall::Position::PosZ: { float z = ws - inset; corners[0] = { ws, -ws, z }; corners[1] = { -ws, -ws, z }; corners[2] = { -ws, ws, z }; corners[3] = { ws, ws, z }; normal = { 0.0, 0.0, -1.0 }; break; } case Wall::Position::NegZ: default: { float z = -ws + inset; corners[0] = { -ws, -ws, z }; corners[1] = { ws, -ws, z }; corners[2] = { ws, ws, z }; corners[3] = { -ws, ws, z }; normal = { 0.0, 0.0, 1.0 }; break; } } out.verts.clear(); out.indices.clear(); out.color = col; auto push = [&](const Vec3& p) { out.verts.push_back(static_cast(p.x)); out.verts.push_back(static_cast(p.y)); out.verts.push_back(static_cast(p.z)); out.verts.push_back(static_cast(normal.x)); out.verts.push_back(static_cast(normal.y)); out.verts.push_back(static_cast(normal.z)); out.verts.push_back(static_cast(p.y)); out.verts.push_back(0.0f); out.verts.push_back(0.0f); }; for (const Vec3& c : corners) push(c); out.indices = { 0, 1, 2, 0, 2, 3 }; } } // namespace namespace Wall { void Surfaces::generate(float world_scale) { _walls.clear(); _walls.resize(4); struct Spec { Role role; Position pos; SDL_FColor color; bool is_editor; }; const Spec specs[4] = { { Role::Editor, Position::NegX, Config::Color::editor, false }, { Role::Program, Position::PosX, Config::Color::program, false }, { Role::Info, Position::PosZ, Config::Color::info, false }, { Role::Compiler, Position::NegZ, Config::Color::compiler, false }, }; for (size_t i = 0; i < 4; i++) { _walls[i].role = specs[i].role; _walls[i].is_editor = specs[i].is_editor; build_Wall(_walls[i], specs[i].pos, world_scale, specs[i].color); } } void Surfaces::draw(GlRenderer& gl, const Camera& cam, const Light& light) const { if (_walls.empty()) return; Mat4 view = buildViewMat4 (cam); Mat4 proj = gl.get_Projection(); Mat4 model = Mat4::identity (); Mat4 mvp = Mat4::mul (proj, Mat4::mul(view, model)); gl.set_Wireframe (false); gl.set_MVP (model, mvp); gl.set_NormalMat (model); gl.set_Light (light); gl.set_TextLineSpacing(Config::Wall::text_line_spacing); for (const Quad& w : _walls) { gl.set_Color (w.color.r, w.color.g, w.color.b); gl.enable_WallPaperMode(w.is_editor); gl.set_ColorUseVertex (false); gl.draw_MeshColored (w.verts.data(), static_cast(w.verts.size() / 9), w.indices.data(), static_cast(w.indices.size())); } gl.enable_WallPaperMode(false); } } // Wall } // namespace Nimbin