X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fmodel%2Fmodel.cpp;h=70a1fc233be73a3de3b407ca3abc8ee516a327af;hb=ba55bf4293f3abc742eef710545a4b207ba2c820;hp=4e000806cff56c2812f9aaa42fc459c642cc29ca;hpb=282d731ea8f10342efa82012028de7043b3dd639;p=blank.git diff --git a/src/model/model.cpp b/src/model/model.cpp index 4e00080..70a1fc2 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -1,401 +1,204 @@ -#include "BlockModel.hpp" #include "Model.hpp" -#include "OutlineModel.hpp" -#include "SpriteModel.hpp" +#include "Instance.hpp" +#include "Skeletons.hpp" -#include +#include "Shape.hpp" +#include "ShapeRegistry.hpp" +#include "../app/TextureIndex.hpp" +#include "../graphics/DirectionalLighting.hpp" +#include "../graphics/EntityMesh.hpp" +#include -namespace blank { - -Model::Model() noexcept -: va(0) -, handle{} -, count(0) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} -Model::~Model() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); -} - -Model::Model(Model &&other) noexcept -: va(other.va) -, count(other.count) { - other.va = 0; - for (int i = 0; i < ATTRIB_COUNT; ++i) { - handle[i] = other.handle[i]; - other.handle[i] = 0; - } -} +namespace blank { -Model &Model::operator =(Model &&other) noexcept { - std::swap(va, other.va); - for (int i = 0; i < ATTRIB_COUNT; ++i) { - std::swap(handle[i], other.handle[i]); - } - count = other.count; - return *this; -} +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() { -void Model::Update(const Buffer &buf) noexcept { - glBindVertexArray(va); - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, buf.vertices.size() * sizeof(glm::vec3), buf.vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (buf.colors.size() < buf.vertices.size()) { - std::cerr << "Model: not enough colors!" << std::endl; - } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, buf.colors.size() * sizeof(glm::vec3), buf.colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (buf.normals.size() < buf.vertices.size()) { - std::cerr << "Model: not enough normals!" << std::endl; - } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_NORMAL]); - glBufferData(GL_ARRAY_BUFFER, buf.normals.size() * sizeof(glm::vec3), buf.normals.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_NORMAL); - glVertexAttribPointer( - ATTRIB_NORMAL, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.indices.size() * sizeof(Index), buf.indices.data(), GL_STATIC_DRAW); - count = buf.indices.size(); } -void Model::Draw() const noexcept { - glBindVertexArray(va); - glDrawElements( - GL_TRIANGLES, // how - count, // count - GL_UNSIGNED_INT, // type - nullptr // offset - ); +Model &Model::AddPart() { + parts.emplace_back(); + parts.back().parent = this; + return parts.back(); } -BlockModel::BlockModel() noexcept -: va(0) -, handle{} -, count(0) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} - -BlockModel::~BlockModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); +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; } -BlockModel::BlockModel(BlockModel &&other) noexcept -: va(other.va) -, count(other.count) { - other.va = 0; - for (int i = 0; i < ATTRIB_COUNT; ++i) { - handle[i] = other.handle[i]; - other.handle[i] = 0; +glm::mat4 Model::GlobalTransform() const noexcept { + if (HasParent()) { + return Parent().GlobalTransform() * LocalTransform(); + } else { + return LocalTransform(); } } -BlockModel &BlockModel::operator =(BlockModel &&other) noexcept { - std::swap(va, other.va); - for (int i = 0; i < ATTRIB_COUNT; ++i) { - std::swap(handle[i], other.handle[i]); - } - count = other.count; - return *this; -} -void BlockModel::Update(const Buffer &buf) noexcept { - glBindVertexArray(va); - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, buf.vertices.size() * sizeof(glm::vec3), buf.vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (buf.colors.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough colors!" << std::endl; - } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, buf.colors.size() * sizeof(glm::vec3), buf.colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (buf.lights.size() < buf.vertices.size()) { - std::cerr << "BlockModel: not enough lights!" << std::endl; +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()); } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_LIGHT]); - glBufferData(GL_ARRAY_BUFFER, buf.lights.size() * sizeof(float), buf.lights.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_LIGHT); - glVertexAttribPointer( - ATTRIB_LIGHT, // location (for shader) - 1, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.indices.size() * sizeof(Index), buf.indices.data(), GL_STATIC_DRAW); - count = buf.indices.size(); } -void BlockModel::Draw() const noexcept { - glBindVertexArray(va); - glDrawElements( - GL_TRIANGLES, // how - count, // count - GL_UNSIGNED_INT, // type - nullptr // offset - ); -} - -OutlineModel::OutlineModel() noexcept -: vertices() -, colors() -, indices() -, va(0) -, handle{} -, dirty(false) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} +Instance::Instance() +: part_model(nullptr) +, parent(nullptr) +, position(0.0f) +, orientation(1.0f, 0.0f, 0.0f, 0.0f) +, parts() { -OutlineModel::~OutlineModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); } -void OutlineModel::Clear() noexcept { - vertices.clear(); - colors.clear(); - indices.clear(); - Invalidate(); +Instance &Instance::AddPart() { + parts.emplace_back(); + parts.back().parent = this; + return parts.back(); } -void OutlineModel::Reserve(int v, int i) { - vertices.reserve(v); - colors.reserve(v); - indices.reserve(i); -} +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 OutlineModel::Update() noexcept { - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (colors.size() < vertices.size()) { - std::cerr << "OutlineModel: not enough colors!" << std::endl; - colors.resize(vertices.size(), { 1, 0, 1 }); +glm::mat4 Instance::GlobalTransform() const noexcept { + if (HasParent()) { + return Parent().GlobalTransform() * LocalTransform(); + } else { + return LocalTransform(); } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), GL_STATIC_DRAW); - - dirty = false; } -void OutlineModel::Draw() noexcept { - glBindVertexArray(va); - - if (dirty) { - Update(); +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); } - - glEnable(GL_LINE_SMOOTH); - glLineWidth(2.0f); - - glDrawElements( - GL_LINES, // how - indices.size(), // count - GL_UNSIGNED_SHORT, // type - nullptr // offset - ); } -SpriteModel::SpriteModel() noexcept -: vertices() -, coords() -, indices() -, va(0) -, handle{} -, dirty(false) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} +Skeletons::Skeletons() +: skeletons() +, meshes() { -SpriteModel::~SpriteModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); } +Skeletons::~Skeletons() { -void SpriteModel::Clear() noexcept { - vertices.clear(); - coords.clear(); - indices.clear(); - Invalidate(); } -void SpriteModel::Reserve(int v, int i) { - vertices.reserve(v); - coords.reserve(v); - indices.reserve(i); +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); + } + { + skeletons.emplace_back(new Model); + skeletons[1]->ID(2); + skeletons[1]->Bounds(bounds); + } + { + skeletons.emplace_back(new Model); + skeletons[2]->ID(3); + skeletons[2]->Bounds(bounds); + } + { + skeletons.emplace_back(new Model); + skeletons[3]->ID(4); + skeletons[3]->Bounds(bounds); + } } - -void SpriteModel::LoadRect( - float w, float h, - const glm::vec2 &pivot, - const glm::vec2 &tex_begin, - const glm::vec2 &tex_end -) { - Clear(); - Reserve(4, 6); - - 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); - - indices.assign({ 0, 2, 1, 1, 2, 3 }); - - Invalidate(); +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]->SetNodeMesh(&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]->SetNodeMesh(&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]->SetNodeMesh(&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]->SetNodeMesh(&meshes[3]); + } } - -void SpriteModel::Update() noexcept { - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Position), vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG - if (coords.size() < vertices.size()) { - std::cerr << "SpriteModel: not enough coords!" << std::endl; - coords.resize(vertices.size(), { 1, 1 }); +Model *Skeletons::ByID(std::uint16_t id) noexcept { + if (id == 0 || id > skeletons.size()) { + return nullptr; + } else { + return skeletons[id - 1].get(); } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_TEXCOORD]); - glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(TexCoord), coords.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexAttribPointer( - ATTRIB_TEXCOORD, // location (for shader) - 2, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), GL_STATIC_DRAW); - - dirty = false; } - -void SpriteModel::Draw() noexcept { - glBindVertexArray(va); - - if (dirty) { - Update(); +const Model *Skeletons::ByID(std::uint16_t id) const noexcept { + if (id == 0 || id > skeletons.size()) { + return nullptr; + } else { + return skeletons[id - 1].get(); } - - glDrawElements( - GL_TRIANGLES, // how - indices.size(), // count - GL_UNSIGNED_SHORT, // type - nullptr // offset - ); } }