From bc2806164f55b7ac48dbb6d224b7d4b55683decf Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Wed, 14 Oct 2015 12:28:40 +0200 Subject: [PATCH] linear model instance state --- src/model/Instance.hpp | 32 ++------- src/model/Model.hpp | 41 +++--------- src/model/Part.hpp | 51 +++++++++++++++ src/model/model.cpp | 144 ++++++++++++++++++++++------------------- 4 files changed, 143 insertions(+), 125 deletions(-) create mode 100644 src/model/Part.hpp diff --git a/src/model/Instance.hpp b/src/model/Instance.hpp index 6c073b8..9de1a5d 100644 --- a/src/model/Instance.hpp +++ b/src/model/Instance.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_MODEL_INSTANCE_HPP_ #define BLANK_MODEL_INSTANCE_HPP_ +#include "Part.hpp" + #include #include #include @@ -11,8 +13,6 @@ namespace blank { class Model; class DirectionalLighting; -// TODO: this doesn't have to be a tree, actually -// linearizing might be a good opportunity to optimize class Instance { friend class Model; @@ -20,34 +20,14 @@ class Instance { public: Instance(); - operator bool() const noexcept { return part_model; } - const Model &GetModel() const noexcept { return *part_model; } - - const glm::vec3 &Position() const noexcept { return position; } - void Position(const glm::vec3 &p) noexcept { position = p; } - - const glm::quat &Orientation() const noexcept { return orientation; } - void Orientation(const glm::quat &o) noexcept { orientation = o; } - - glm::mat4 LocalTransform() const noexcept; - glm::mat4 GlobalTransform() const noexcept; + operator bool() const noexcept { return model; } + const Model &GetModel() const noexcept { return *model; } void Render(const glm::mat4 &, DirectionalLighting &) const; private: - Instance &AddPart(); - bool HasParent() const noexcept { return parent; } - Instance &Parent() const noexcept { return *parent; } - bool IsRoot() const noexcept { return !HasParent(); } - -private: - const Model *part_model; - Instance *parent; - - glm::vec3 position; - glm::quat orientation; - - std::vector parts; + const Model *model; + std::vector state; }; diff --git a/src/model/Model.hpp b/src/model/Model.hpp index 118ac2e..c46caf4 100644 --- a/src/model/Model.hpp +++ b/src/model/Model.hpp @@ -1,10 +1,11 @@ #ifndef BLANK_MODEL_MODEL_HPP_ #define BLANK_MODEL_MODEL_HPP_ -#include "geometry.hpp" +#include "Part.hpp" #include #include +#include #include #include @@ -25,42 +26,18 @@ public: std::uint32_t ID() const noexcept { return id; } void ID(std::uint32_t i) noexcept { id = i; } - const AABB &Bounds() const noexcept { return bounds; } - void Bounds(const AABB &b) noexcept { bounds = b; } - - const glm::vec3 &Position() const noexcept { return position; } - void Position(const glm::vec3 &p) noexcept { position = p; } - - const glm::quat &Orientation() const noexcept { return orientation; } - void Orientation(const glm::quat &o) noexcept { orientation = o; } - - bool HasNodeMesh() const noexcept { return node_mesh; } - void SetNodeMesh(const EntityMesh *m) noexcept { node_mesh = m; } - - const EntityMesh &NodeMesh() const noexcept { return *node_mesh; } - - Model &AddPart(); - bool HasParent() const noexcept { return parent; } - Model &Parent() const noexcept { return *parent; } - bool IsRoot() const noexcept { return !HasParent(); } - - glm::mat4 LocalTransform() const noexcept; - glm::mat4 GlobalTransform() const noexcept; + Part &RootPart() noexcept { return root; } + const Part &RootPart() const noexcept { return root; } + Part &GetPart(std::size_t i) noexcept { return *part[i]; } + const Part &GetPart(std::size_t i) const noexcept { return *part[i]; } + void Enumerate(); void Instantiate(Instance &) const; private: - Model *parent; - const EntityMesh *node_mesh; - std::uint32_t id; - - AABB bounds; - - glm::vec3 position; - glm::quat orientation; - - std::list parts; + Part root; + std::vector part; }; diff --git a/src/model/Part.hpp b/src/model/Part.hpp new file mode 100644 index 0000000..029442b --- /dev/null +++ b/src/model/Part.hpp @@ -0,0 +1,51 @@ +#ifndef BLAMK_MODEL_PART_HPP_ +#define BLAMK_MODEL_PART_HPP_ + +#include "geometry.hpp" + +#include +#include +#include +#include +#include + + +namespace blank { + +class DirectionalLighting; +class EntityMesh; +class Model; + +struct Part { + + std::uint16_t id; + AABB bounds; + struct State { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat orientation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); + } initial; + const EntityMesh *mesh; + + Part(); + ~Part(); + + Part &AddChild(); + const std::list &Children() const noexcept { return children; } + + std::uint16_t Enumerate(std::uint16_t) noexcept; + void Index(std::vector &) noexcept; + + glm::mat4 LocalTransform(const std::vector &) const noexcept; + glm::mat4 GlobalTransform(const std::vector &) const noexcept; + + void Render(const glm::mat4 &, const std::vector &, DirectionalLighting &) const; + +private: + const Part *parent; + std::list children; + +}; + +} + +#endif diff --git a/src/model/model.cpp b/src/model/model.cpp index 70a1fc2..632a5b6 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -13,96 +13,102 @@ namespace blank { -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() { +Instance::Instance() +: model(nullptr) +, state() { } - -Model &Model::AddPart() { - parts.emplace_back(); - parts.back().parent = this; - return parts.back(); +void Instance::Render(const glm::mat4 &M, DirectionalLighting &prog) const { + model->RootPart().Render(M, state, prog); } -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; -} +Model::Model() +: id(0) +, root() +, part() { -glm::mat4 Model::GlobalTransform() const noexcept { - if (HasParent()) { - return Parent().GlobalTransform() * LocalTransform(); - } else { - return LocalTransform(); - } } +void Model::Enumerate() { + part.clear(); + part.resize(root.Enumerate(0), nullptr); + root.Index(part); +} 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()); - } + inst.model = this; + inst.state.clear(); + inst.state.resize(part.size()); } -Instance::Instance() -: part_model(nullptr) +Part::Part() +: id(0) +, bounds{ glm::vec3(0.0f), glm::vec3(0.0f) } +, initial() +, mesh(nullptr) , parent(nullptr) -, position(0.0f) -, orientation(1.0f, 0.0f, 0.0f, 0.0f) -, parts() { +, children() { } +Part::~Part() { + +} + +Part &Part::AddChild() { + children.emplace_back(); + children.back().parent = this; + return children.back(); +} -Instance &Instance::AddPart() { - parts.emplace_back(); - parts.back().parent = this; - return parts.back(); +std::uint16_t Part::Enumerate(std::uint16_t counter) noexcept { + id = counter++; + for (Part &part : children) { + counter = part.Enumerate(counter); + } + return counter; } +void Part::Index(std::vector &index) noexcept { + index[id] = this; + for (Part &part : children) { + part.Index(index); + } +} -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; +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 Instance::GlobalTransform() const noexcept { - if (HasParent()) { - return Parent().GlobalTransform() * LocalTransform(); +glm::mat4 Part::GlobalTransform( + const std::vector &state +) const noexcept { + if (parent) { + return parent->GlobalTransform(state) * LocalTransform(state); } else { - return LocalTransform(); + return LocalTransform(state); } } - -void Instance::Render(const glm::mat4 &M, DirectionalLighting &prog) const { - glm::mat4 transform(M * LocalTransform()); - if (part_model->HasNodeMesh()) { +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); - part_model->NodeMesh().Draw(); + mesh->Draw(); } - for (const Instance &part : parts) { - part.Render(transform, prog); + for (const Part &part : children) { + part.Render(transform, state, prog); } } @@ -124,22 +130,26 @@ void Skeletons::LoadHeadless() { { skeletons.emplace_back(new Model); skeletons[0]->ID(1); - skeletons[0]->Bounds(bounds); + skeletons[0]->RootPart().bounds = bounds; + skeletons[0]->Enumerate(); } { skeletons.emplace_back(new Model); skeletons[1]->ID(2); - skeletons[1]->Bounds(bounds); + skeletons[1]->RootPart().bounds = bounds; + skeletons[1]->Enumerate(); } { skeletons.emplace_back(new Model); skeletons[2]->ID(3); - skeletons[2]->Bounds(bounds); + skeletons[2]->RootPart().bounds = bounds; + skeletons[2]->Enumerate(); } { skeletons.emplace_back(new Model); skeletons[3]->ID(4); - skeletons[3]->Bounds(bounds); + skeletons[3]->RootPart().bounds = bounds; + skeletons[3]->Enumerate(); } } @@ -157,7 +167,7 @@ void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) { 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]); + skeletons[0]->RootPart().mesh = &meshes[0]; } { buf.Clear(); @@ -165,7 +175,7 @@ void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) { 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]); + skeletons[1]->RootPart().mesh = &meshes[1]; } { buf.Clear(); @@ -173,7 +183,7 @@ void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) { 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]); + skeletons[2]->RootPart().mesh = &meshes[2]; } { buf.Clear(); @@ -181,7 +191,7 @@ void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) { 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]); + skeletons[3]->RootPart().mesh = &meshes[3]; } } -- 2.39.2