X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fmodel%2Fmodel.cpp;h=22d2bedfc54211cbc68202ac04a0074a768829a6;hb=b61d462707dd3d40a32a6104d88eb24f6a52df63;hp=cc6e20e788d2ca6e721c943f871b209920dfdac5;hpb=957b1df87d9a692c517a269221da81227100240e;p=blank.git diff --git a/src/model/model.cpp b/src/model/model.cpp index cc6e20e..22d2bed 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -1,157 +1,204 @@ -#include "BlockModel.hpp" -#include "EntityModel.hpp" -#include "OutlineModel.hpp" -#include "SkyBoxModel.hpp" -#include "SpriteModel.hpp" +#include "Model.hpp" +#include "Instance.hpp" +#include "Skeletons.hpp" -#include "shapes.hpp" +#include "bounds.hpp" +#include "../graphics/DirectionalLighting.hpp" +#include "../graphics/EntityMesh.hpp" -#include -#include +#include namespace blank { -void EntityModel::Update(const Buffer &buf) noexcept { -#ifndef NDEBUG - if (buf.tex_coords.size() < buf.vertices.size()) { - std::cerr << "EntityModel: not enough tex coords!" << std::endl; - } - if (buf.hsl_mods.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough HSL modifiers!" << std::endl; - } - if (buf.rgb_mods.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough RGB modifiers!" << std::endl; - } - if (buf.normals.size() < buf.vertices.size()) { - std::cerr << "EntityModel: not enough normals!" << std::endl; - } -#endif +Model::Model() +: parent(nullptr) +, node_mesh(nullptr) +, id(0) +, bounds{{ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }} +, position(0.0f) +, orientation(1.0f, 0.0f, 0.0f, 0.0f) +, parts() { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords); - vao.PushAttribute(ATTRIB_HSL, buf.hsl_mods); - vao.PushAttribute(ATTRIB_RGB, buf.rgb_mods); - vao.PushAttribute(ATTRIB_NORMAL, buf.normals); - vao.PushIndices(ATTRIB_INDEX, buf.indices); } -void EntityModel::Draw() const noexcept { - vao.DrawTriangleElements(); +Model &Model::AddPart() { + parts.emplace_back(); + parts.back().parent = this; + return parts.back(); } -void BlockModel::Update(const Buffer &buf) noexcept { -#ifndef NDEBUG - if (buf.tex_coords.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough tex coords!" << std::endl; - } - if (buf.hsl_mods.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough HSL modifiers!" << std::endl; - } - if (buf.rgb_mods.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough RGB modifiers!" << std::endl; - } - if (buf.lights.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough lights!" << std::endl; - } -#endif +glm::mat4 Model::LocalTransform() const noexcept { + glm::mat4 transform(toMat4(orientation)); + transform[3].x = position.x; + transform[3].y = position.y; + transform[3].z = position.z; + return transform; +} - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords); - vao.PushAttribute(ATTRIB_HSL, buf.hsl_mods); - vao.PushAttribute(ATTRIB_RGB, buf.rgb_mods); - vao.PushAttribute(ATTRIB_LIGHT, buf.lights); - vao.PushIndices(ATTRIB_INDEX, buf.indices); +glm::mat4 Model::GlobalTransform() const noexcept { + if (HasParent()) { + return Parent().GlobalTransform() * LocalTransform(); + } else { + return LocalTransform(); + } } -void BlockModel::Draw() const noexcept { - vao.DrawTriangleElements(); +void Model::Instantiate(Instance &inst) const { + inst.part_model = this; + inst.position = position; + inst.orientation = orientation; + inst.parts.clear(); + inst.parts.reserve(parts.size()); + for (const Model &part : parts) { + part.Instantiate(inst.AddPart()); + } } -void OutlineModel::Update(const Buffer &buf) noexcept { -#ifndef NDEBUG - if (buf.colors.size() < buf.vertices.size()) { - std::cerr << "OutlineModel: not enough colors!" << std::endl; - } -#endif +Instance::Instance() +: part_model(nullptr) +, parent(nullptr) +, position(0.0f) +, orientation(1.0f, 0.0f, 0.0f, 0.0f) +, parts() { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_COLOR, buf.colors); - vao.PushIndices(ATTRIB_INDEX, buf.indices); } -void OutlineModel::Draw() noexcept { - glEnable(GL_LINE_SMOOTH); - glLineWidth(2.0f); - vao.DrawLineElements(); +Instance &Instance::AddPart() { + parts.emplace_back(); + parts.back().parent = this; + return parts.back(); } -void SkyBoxModel::LoadUnitBox() { - Buffer buffer; - CuboidShape shape({{ -1, -1, -1 }, { 1, 1, 1 }}); - shape.Vertices(buffer); - Update(buffer); +glm::mat4 Instance::LocalTransform() const noexcept { + glm::mat4 transform(toMat4(orientation)); + transform[3].x = position.x; + transform[3].y = position.y; + transform[3].z = position.z; + return transform; } -void SkyBoxModel::Update(const Buffer &buf) noexcept { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushIndices(ATTRIB_INDEX, buf.indices); +glm::mat4 Instance::GlobalTransform() const noexcept { + if (HasParent()) { + return Parent().GlobalTransform() * LocalTransform(); + } else { + return LocalTransform(); + } } -void SkyBoxModel::Draw() const noexcept { - vao.DrawTriangleElements(); + +void Instance::Render(const glm::mat4 &M, DirectionalLighting &prog) const { + glm::mat4 transform(M * LocalTransform()); + if (part_model->HasNodeMesh()) { + prog.SetM(transform); + part_model->NodeMesh().Draw(); + } + for (const Instance &part : parts) { + part.Render(transform, prog); + } } -void SpriteModel::Buffer::LoadRect( - float w, float h, - const glm::vec2 &pivot, - const glm::vec2 &tex_begin, - const glm::vec2 &tex_end -) { - Clear(); - Reserve(4, 6); +Skeletons::Skeletons() +: skeletons() +, meshes() { - vertices.emplace_back( -pivot.x, -pivot.y, 0.0f); - vertices.emplace_back(w-pivot.x, -pivot.y, 0.0f); - vertices.emplace_back( -pivot.x, h-pivot.y, 0.0f); - vertices.emplace_back(w-pivot.x, h-pivot.y, 0.0f); +} - coords.emplace_back(tex_begin.x, tex_begin.y); - coords.emplace_back(tex_end.x, tex_begin.y); - coords.emplace_back(tex_begin.x, tex_end.y); - coords.emplace_back(tex_end.x, tex_end.y); +Skeletons::~Skeletons() { - indices.assign({ 0, 2, 1, 1, 2, 3 }); } - -void SpriteModel::Update(const Buffer &buf) noexcept { -#ifndef NDEBUG - if (buf.coords.size() < buf.vertices.size()) { - std::cerr << "SpriteModel: not enough coords!" << std::endl; +void Skeletons::LoadHeadless() { + skeletons.clear(); + skeletons.reserve(4); + { + AABB bounds{{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}; + skeletons.emplace_back(new Model); + skeletons[0]->ID(1); + skeletons[0]->Bounds(bounds); + } + { + AABB bounds{{ -0.5f, -0.25f, -0.5f }, { 0.5f, 0.25f, 0.5f }}; + skeletons.emplace_back(new Model); + skeletons[1]->ID(2); + skeletons[1]->Bounds(bounds); } -#endif + { + AABB bounds{{ -0.25f, -0.5f, -0.25f }, { 0.25f, 0.5f, 0.25f }}; + skeletons.emplace_back(new Model); + skeletons[2]->ID(3); + skeletons[2]->Bounds(bounds); + } + { + AABB bounds{{ -0.25f, -0.5f, -0.35f }, { 0.25f, 0.5f, 0.35f }}; + skeletons.emplace_back(new Model); + skeletons[3]->ID(4); + skeletons[3]->Bounds(bounds); + } +} - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.coords); - vao.PushIndices(ATTRIB_INDEX, buf.indices); +void Skeletons::Load() { + LoadHeadless(); + meshes.resize(4); + EntityMesh::Buffer buf; + { + CuboidBounds shape(skeletons[0]->Bounds()); + shape.Vertices(buf, 3.0f); + buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f }); + buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 1.0f, 0.0f }); + meshes[0].Update(buf); + skeletons[0]->SetNodeMesh(&meshes[0]); + } + { + CuboidBounds shape(skeletons[1]->Bounds()); + buf.Clear(); + shape.Vertices(buf, 0.0f); + buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f }); + buf.rgb_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f }); + meshes[1].Update(buf); + skeletons[1]->SetNodeMesh(&meshes[1]); + } + { + StairBounds shape(skeletons[2]->Bounds(), { 0.4f, 0.4f }); + buf.Clear(); + shape.Vertices(buf, 1.0f); + buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f }); + buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 0.0f, 1.0f }); + meshes[2].Update(buf); + skeletons[2]->SetNodeMesh(&meshes[2]); + } + { + CuboidBounds shape(skeletons[3]->Bounds()); + buf.Clear(); + shape.Vertices(buf, 2.0f); + buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f }); + buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 0.25f, 0.5f }); + meshes[3].Update(buf); + skeletons[3]->SetNodeMesh(&meshes[3]); + } } +Model *Skeletons::ByID(std::uint16_t id) noexcept { + if (id == 0 || id > skeletons.size()) { + return nullptr; + } else { + return skeletons[id - 1].get(); + } +} -void SpriteModel::Draw() noexcept { - vao.DrawTriangleElements(); +const Model *Skeletons::ByID(std::uint16_t id) const noexcept { + if (id == 0 || id > skeletons.size()) { + return nullptr; + } else { + return skeletons[id - 1].get(); + } } }