mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 03:52:48 -05:00
WIP (broken): Refactor components
This commit is contained in:
71
entt-question.md
Normal file
71
entt-question.md
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
I have some "composite" objects that I'm not sure how best to map into an ECS. Each composite object has multiple "parts" with various properties. But the parts of a given composite object are intrinsically linked: they transform together and use the same buffers during rendering.
|
||||||
|
|
||||||
|
Note that I'm still pretty early in adopting `entt` for this project, so I'm not particularly tied to any of the architecture here. The only constraint is that, for optimization reasons, I need each composite object to get _one_ buffer on GPU, and each part owns some interval within its parent's buffer. This nested scheme seems the most straightforward way to do that.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
My first attempt has only one entity for each composite object, with a `Parts` component that holds an `std::vector<Part>`.
|
||||||
|
|
||||||
|
Rendering code looks something like this. In reality I save the draw commands in a separate component and re-use those on each frame.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
auto view = registry.view<Parts>();
|
||||||
|
|
||||||
|
for (auto [entity, parts]: view.each()) {
|
||||||
|
std::vector<Command> commands;
|
||||||
|
|
||||||
|
for (auto part: parts.parts) {
|
||||||
|
// assemble draw command
|
||||||
|
commands.emplace_back(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind buffers for entity
|
||||||
|
// issue draw command
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
However it seems appropriate to give each part its own entity. My attempt for this was to switch to `std::vector<entt::entity>` where each entity has a `Part` as a component.
|
||||||
|
|
||||||
|
Rendering code then looks like:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
auto view = registry.view<Parts>();
|
||||||
|
|
||||||
|
for (auto [entity, parts]: view.each()) {
|
||||||
|
std::vector<Command> commands;
|
||||||
|
|
||||||
|
for (auto part_entity: parts.parts) {
|
||||||
|
auto &part = registry.get<Part>(part_entity);
|
||||||
|
// assemble draw command
|
||||||
|
commands.emplace_back(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind buffers for entity
|
||||||
|
// issue draw command with shared buffer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
In my last attempt, I invert this so each `Part` holds only parent entity. The `Parts` component is removed. I can then use a `view<Part>` directly, but it's trickier to organize the draw calls since they must be grouped by the parent entity itself.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
auto view = registry.view<Part>();
|
||||||
|
|
||||||
|
for (auto [entity, part]: view.each()) {
|
||||||
|
// assemble draw command
|
||||||
|
auto &commands = registry.get<Commands>(part.parent);
|
||||||
|
commands.emplace_back(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto [entity, commands]: view
|
||||||
|
for (auto [entity, commands]: commands) {
|
||||||
|
// bind buffers for entity
|
||||||
|
auto &commands = registry.get<Commands>(entity);
|
||||||
|
// issue draw commands
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Is there any more sensible approach to this kind of many-to-one entity composition? Or some way to declare _multiple_ `Part` components on the same entity? It seems like I almost need some group-by kind of operation, but I don't see such on the registry/view docs.
|
||||||
@@ -18,54 +18,44 @@
|
|||||||
#include <shaders.hpp>
|
#include <shaders.hpp>
|
||||||
|
|
||||||
namespace vis {
|
namespace vis {
|
||||||
|
using Color = Eigen::Vector<float, 3>;
|
||||||
|
|
||||||
template<int R_, int D_, int G_>
|
template<int R_, int D_, int G_>
|
||||||
struct Structure {
|
struct Structure {
|
||||||
static constexpr auto Rank = R_;
|
static constexpr auto Rank = R_;
|
||||||
static constexpr auto Dim = D_;
|
static constexpr auto Dim = D_;
|
||||||
static constexpr auto Grade = G_;
|
static constexpr auto Grade = G_;
|
||||||
|
|
||||||
using Affine = Eigen::Transform<float, Dim, Eigen::Affine>;
|
using AffineDf = Eigen::Transform<float, Dim, Eigen::Affine>;
|
||||||
|
|
||||||
using VectorRf = Eigen::Vector<float, Rank>;
|
using VectorRf = Eigen::Vector<float, Rank>;
|
||||||
using MatrixRXf = Eigen::Matrix<float, Rank, Eigen::Dynamic>;
|
|
||||||
using VectorDf = Eigen::Vector<float, Dim>;
|
|
||||||
using MatrixDXf = Eigen::Matrix<float, Dim, Eigen::Dynamic>;
|
|
||||||
using VectorGf = Eigen::Vector<float, Grade>;
|
|
||||||
using MatrixGXf = Eigen::Matrix<float, Grade, Eigen::Dynamic>;
|
|
||||||
|
|
||||||
using ArrayRui = Eigen::Array<GLuint, Rank, 1>;
|
|
||||||
using ArrayRXui = Eigen::Array<GLuint, Rank, Eigen::Dynamic>;
|
|
||||||
using ArrayDui = Eigen::Array<GLuint, Dim, 1>;
|
|
||||||
using ArrayDXui = Eigen::Array<GLuint, Dim, Eigen::Dynamic>;
|
|
||||||
using ArrayGui = Eigen::Array<GLuint, Grade, 1>;
|
|
||||||
using ArrayGXui = Eigen::Array<GLuint, Grade, Eigen::Dynamic>;
|
|
||||||
|
|
||||||
using Color = Eigen::Vector<float, 3>; // todo global typedef
|
|
||||||
|
|
||||||
// todo cache and recompute cells/points on frame (only if changed) in a system.
|
// todo cache and recompute cells/points on frame (only if changed) in a system.
|
||||||
|
|
||||||
tc::Group group;
|
tc::Group group;
|
||||||
VectorRf root;
|
VectorRf root;
|
||||||
|
|
||||||
Affine transform = Affine::Identity();
|
AffineDf transform = AffineDf::Identity();
|
||||||
|
|
||||||
|
explicit Structure(tc::Group const &group, VectorRf root) :
|
||||||
|
group(group), root(root), transform(AffineDf::Identity()) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Str_>
|
||||||
struct Part {
|
struct Part {
|
||||||
|
using Str = Str_;
|
||||||
|
|
||||||
|
entt::entity parent;
|
||||||
|
|
||||||
GLuint first;
|
GLuint first;
|
||||||
GLuint count;
|
GLuint count;
|
||||||
Color color = Color::Ones();
|
Color color = Color::Ones();
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<entt::entity> parts{};
|
struct Command {
|
||||||
|
unsigned int count, instanceCount, first, baseInstance;
|
||||||
explicit Structure(
|
|
||||||
tc::Group group,
|
|
||||||
VectorRf root
|
|
||||||
) :
|
|
||||||
group(group),
|
|
||||||
root(root),
|
|
||||||
transform(Affine::Identity()) {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Str_>
|
template<typename Str_>
|
||||||
@@ -81,10 +71,6 @@ namespace vis {
|
|||||||
Eigen::Vector4f translation;
|
Eigen::Vector4f translation;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Command {
|
|
||||||
unsigned int count, instanceCount, first, baseInstance;
|
|
||||||
};
|
|
||||||
|
|
||||||
cgl::Buffer<VectorDf> vertices;
|
cgl::Buffer<VectorDf> vertices;
|
||||||
cgl::Buffer<Color> colors;
|
cgl::Buffer<Color> colors;
|
||||||
cgl::Buffer<ArrayGui> indices;
|
cgl::Buffer<ArrayGui> indices;
|
||||||
|
|||||||
@@ -21,39 +21,42 @@
|
|||||||
namespace vis {
|
namespace vis {
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
void upload_structure(entt::registry ®istry) {
|
void upload_structure(entt::registry ®istry) {
|
||||||
|
{
|
||||||
|
auto parts = registry.view<Part<Str>>();
|
||||||
|
registry.destroy(parts.begin(), parts.end());
|
||||||
|
}
|
||||||
|
|
||||||
auto view = registry.view<Str, VBOs<Str>>();
|
auto view = registry.view<Str, VBOs<Str>>();
|
||||||
|
|
||||||
for (auto [entity, structure, vbos]: view.each()) {
|
for (auto [entity, structure, vbos]: view.each()) {
|
||||||
Points points(structure.group, structure.root);
|
Points points(structure.group, structure.root);
|
||||||
Hull<Str::Grade> hull(structure.group);
|
Hull<Str::Grade> hull(structure.group);
|
||||||
|
|
||||||
registry.destroy(structure.parts.begin(), structure.parts.end());
|
auto &&vertices = points.verts.colwise();
|
||||||
structure.parts.clear();
|
auto &&indices = hull.inds.colwise();
|
||||||
|
|
||||||
|
vbos.vertices.put(vertices.begin(), vertices.end());
|
||||||
|
vbos.indices.put(indices.begin(), indices.end());
|
||||||
|
|
||||||
for (const auto &tiling: hull.tilings) {
|
for (const auto &tiling: hull.tilings) {
|
||||||
auto part_entity = registry.create();
|
auto part_entity = registry.create();
|
||||||
registry.emplace<typename Str::Part>(
|
registry.emplace<Part<Str>>(
|
||||||
part_entity,
|
part_entity,
|
||||||
|
entity,
|
||||||
tiling.first,
|
tiling.first,
|
||||||
tiling.count
|
tiling.count
|
||||||
);
|
);
|
||||||
structure.parts.push_back(part_entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vbos.vertices.put(
|
|
||||||
points.verts.colwise().begin(),
|
|
||||||
points.verts.colwise().end()
|
|
||||||
);
|
|
||||||
vbos.indices.put(
|
|
||||||
hull.inds.colwise().begin(),
|
|
||||||
hull.inds.colwise().end()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
void upload_uniforms(entt::registry ®istry) {
|
void upload_uniforms(entt::registry ®istry) {
|
||||||
auto view = registry.view<Str, VBOs<Str>>();
|
auto view = registry.view<Part<Str>>();
|
||||||
|
|
||||||
|
for (auto [entity, part]: view.each()) {
|
||||||
|
auto &vbos = registry.get<VBOs<Str>>(part.parent);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto [entity, structure, vbos]: view.each()) {
|
for (auto [entity, structure, vbos]: view.each()) {
|
||||||
std::vector<typename Str::Color> colors;
|
std::vector<typename Str::Color> colors;
|
||||||
@@ -73,6 +76,11 @@ namespace vis {
|
|||||||
|
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
void upload_commands(entt::registry ®istry) {
|
void upload_commands(entt::registry ®istry) {
|
||||||
|
auto view = registry.view<Part<Str>>();
|
||||||
|
for (auto [entity, part]: view.each()) {
|
||||||
|
Command comm(part.count, 1, part.first, )
|
||||||
|
}
|
||||||
|
|
||||||
auto view = registry.view<Str, VBOs<Str>>();
|
auto view = registry.view<Str, VBOs<Str>>();
|
||||||
|
|
||||||
for (auto [entity, structure, vbos]: view.each()) {
|
for (auto [entity, structure, vbos]: view.each()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user