X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fmodel%2Fmodel.cpp;h=632a5b64289533c343c18fd1a18ef35b28cf0ba2;hb=bc2806164f55b7ac48dbb6d224b7d4b55683decf;hp=7aaf8f613b931a595e16a89800197260dd6fd044;hpb=8ab4ea13545cccbacbd1ed610968d3f481c1b3c8;p=blank.git diff --git a/src/model/model.cpp b/src/model/model.cpp index 7aaf8f6..632a5b6 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -1,149 +1,214 @@ -#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 "Shape.hpp" +#include "ShapeRegistry.hpp" +#include "../app/TextureIndex.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.colors.size() < buf.vertices.size()) { - std::cerr << "EntityModel: not enough colors!" << std::endl; - } - if (buf.normals.size() < buf.vertices.size()) { - std::cerr << "EntityModel: not enough normals!" << std::endl; - } -#endif +Instance::Instance() +: model(nullptr) +, state() { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords); - vao.PushAttribute(ATTRIB_COLOR, buf.colors); - vao.PushAttribute(ATTRIB_NORMAL, buf.normals); - vao.PushIndices(ATTRIB_INDEX, buf.indices); } - -void EntityModel::Draw() const noexcept { - vao.DrawTriangleElements(); +void Instance::Render(const glm::mat4 &M, DirectionalLighting &prog) const { + model->RootPart().Render(M, state, prog); } -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.colors.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough colors!" << std::endl; - } - if (buf.lights.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough lights!" << std::endl; - } -#endif +Model::Model() +: id(0) +, root() +, part() { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords); - vao.PushAttribute(ATTRIB_COLOR, buf.colors); - vao.PushAttribute(ATTRIB_LIGHT, buf.lights); - vao.PushIndices(ATTRIB_INDEX, buf.indices); } +void Model::Enumerate() { + part.clear(); + part.resize(root.Enumerate(0), nullptr); + root.Index(part); +} -void BlockModel::Draw() const noexcept { - vao.DrawTriangleElements(); +void Model::Instantiate(Instance &inst) const { + inst.model = this; + inst.state.clear(); + inst.state.resize(part.size()); } -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 +Part::Part() +: id(0) +, bounds{ glm::vec3(0.0f), glm::vec3(0.0f) } +, initial() +, mesh(nullptr) +, parent(nullptr) +, children() { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_COLOR, buf.colors); - vao.PushIndices(ATTRIB_INDEX, buf.indices); } +Part::~Part() { -void OutlineModel::Draw() noexcept { - glEnable(GL_LINE_SMOOTH); - glLineWidth(2.0f); - vao.DrawLineElements(); } +Part &Part::AddChild() { + children.emplace_back(); + children.back().parent = this; + return children.back(); +} -void SkyBoxModel::LoadUnitBox() { - Buffer buffer; - CuboidShape shape({{ -1, -1, -1 }, { 1, 1, 1 }}); - shape.Vertices(buffer); - Update(buffer); +std::uint16_t Part::Enumerate(std::uint16_t counter) noexcept { + id = counter++; + for (Part &part : children) { + counter = part.Enumerate(counter); + } + return counter; } -void SkyBoxModel::Update(const Buffer &buf) noexcept { - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushIndices(ATTRIB_INDEX, buf.indices); +void Part::Index(std::vector &index) noexcept { + index[id] = this; + for (Part &part : children) { + part.Index(index); + } } -void SkyBoxModel::Draw() const noexcept { - vao.DrawTriangleElements(); +glm::mat4 Part::LocalTransform( + const std::vector &state +) const noexcept { + glm::mat4 transform(toMat4(initial.orientation * state[id].orientation)); + transform[3] = glm::vec4(initial.position + state[id].position, 1.0f); + return transform; } +glm::mat4 Part::GlobalTransform( + const std::vector &state +) const noexcept { + if (parent) { + return parent->GlobalTransform(state) * LocalTransform(state); + } else { + return LocalTransform(state); + } +} -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); +void Part::Render( + const glm::mat4 &M, + const std::vector &state, + DirectionalLighting &prog +) const { + glm::mat4 transform = M * LocalTransform(state); + if (mesh) { + prog.SetM(transform); + mesh->Draw(); + } + for (const Part &part : children) { + part.Render(transform, state, prog); + } +} - 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() +: skeletons() +, meshes() { - indices.assign({ 0, 2, 1, 1, 2, 3 }); } +Skeletons::~Skeletons() { + +} -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]->RootPart().bounds = bounds; + skeletons[0]->Enumerate(); } -#endif + { + skeletons.emplace_back(new Model); + skeletons[1]->ID(2); + skeletons[1]->RootPart().bounds = bounds; + skeletons[1]->Enumerate(); + } + { + skeletons.emplace_back(new Model); + skeletons[2]->ID(3); + skeletons[2]->RootPart().bounds = bounds; + skeletons[2]->Enumerate(); + } + { + skeletons.emplace_back(new Model); + skeletons[3]->ID(4); + skeletons[3]->RootPart().bounds = bounds; + skeletons[3]->Enumerate(); + } +} - vao.Bind(); - vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); - vao.PushAttribute(ATTRIB_TEXCOORD, buf.coords); - vao.PushIndices(ATTRIB_INDEX, buf.indices); +void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) { + LoadHeadless(); + meshes.resize(4); + const Shape &shape = shapes.Get("player_head_block"); + EntityMesh::Buffer buf; + std::vector tex_map; + tex_map.push_back(tex_index.GetID("rock-1")); + tex_map.push_back(tex_index.GetID("rock-face")); + buf.Reserve(shape.VertexCount(), shape.IndexCount()); + { + shape.Fill(buf, tex_map); + 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]->RootPart().mesh = &meshes[0]; + } + { + buf.Clear(); + shape.Fill(buf, tex_map); + 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]->RootPart().mesh = &meshes[1]; + } + { + buf.Clear(); + shape.Fill(buf, tex_map); + 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]->RootPart().mesh = &meshes[2]; + } + { + buf.Clear(); + shape.Fill(buf, tex_map); + 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]->RootPart().mesh = &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(); + } } }