diff --git a/src/experimental/filament/filament/drawable.cc b/src/experimental/filament/filament/drawable.cc index 7d26e729..cfddafde 100644 --- a/src/experimental/filament/filament/drawable.cc +++ b/src/experimental/filament/filament/drawable.cc @@ -181,6 +181,7 @@ void Drawable::Update(const mjModel* model, const mjvScene* scene, SetTransform(geom); UpdateMaterial(geom, scene->flags[mjRND_IDCOLOR], head_pos); + renderables_.SetWireframe(scene->flags[mjRND_WIREFRAME]); } void Drawable::AddMesh(int data_id) { diff --git a/src/experimental/filament/filament/renderables.cc b/src/experimental/filament/filament/renderables.cc index 8bcf8e3d..77181077 100644 --- a/src/experimental/filament/filament/renderables.cc +++ b/src/experimental/filament/filament/renderables.cc @@ -49,7 +49,10 @@ void Renderables::RemoveLast() { em.destroy(entity); entities_.pop_back(); - UpdateBuffers(owned_buffers_.size() - 1, std::nullopt); + if (owned_buffers_.back().owned) { + engine_->destroy(owned_buffers_.back().buffers.vertex_buffer); + engine_->destroy(owned_buffers_.back().buffers.index_buffer); + } owned_buffers_.pop_back(); } @@ -59,7 +62,7 @@ void Renderables::Update(int index, const FilamentBuffers& buffers) { } utils::Entity& entity = entities_[index]; UpdateEntity(entity, buffers); - UpdateBuffers(index, std::nullopt); + UpdateBuffers(index, buffers, false); } void Renderables::Update(int index, FilamentBuffers&& buffers) { @@ -68,19 +71,19 @@ void Renderables::Update(int index, FilamentBuffers&& buffers) { } utils::Entity& entity = entities_[index]; UpdateEntity(entity, buffers); - UpdateBuffers(index, buffers); + UpdateBuffers(index, buffers, true); } void Renderables::Append(const FilamentBuffers& buffers) { utils::Entity entity = CreateEntity(buffers); entities_.push_back(entity); - owned_buffers_.push_back(std::nullopt); + owned_buffers_.push_back({.owned = false, .buffers = buffers}); } void Renderables::Append(FilamentBuffers&& buffers) { utils::Entity entity = CreateEntity(buffers); entities_.push_back(entity); - owned_buffers_.push_back(buffers); + owned_buffers_.push_back({.owned = true, .buffers = buffers}); } utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) { @@ -129,16 +132,16 @@ void Renderables::UpdateEntity(utils::Entity entity, buffers.index_buffer->getIndexCount()); } -void Renderables::UpdateBuffers(int index, - std::optional buffers) { +void Renderables::UpdateBuffers(int index, FilamentBuffers buffers, bool owned) { if (index < 0 || index >= owned_buffers_.size()) { mju_error("Invalid index %d for renderable.", index); } - if (owned_buffers_[index].has_value()) { - engine_->destroy(owned_buffers_[index]->vertex_buffer); - engine_->destroy(owned_buffers_[index]->index_buffer); + if (owned_buffers_[index].owned) { + engine_->destroy(owned_buffers_[index].buffers.vertex_buffer); + engine_->destroy(owned_buffers_[index].buffers.index_buffer); } - owned_buffers_[index] = buffers; + owned_buffers_[index].buffers = buffers; + owned_buffers_[index].owned = owned; } void Renderables::AddToScene(filament::Scene* scene) { @@ -197,6 +200,27 @@ void Renderables::Show() { } } +void Renderables::SetWireframe(bool wireframe) { + static constexpr auto kWireframeType = + filament::RenderableManager::PrimitiveType::LINES; + + if (wireframe == wireframe_) { + return; + } + wireframe_ = wireframe; + + filament::RenderableManager& rm = engine_->getRenderableManager(); + for (int i = 0; i < entities_.size(); ++i) { + utils::Entity& entity = entities_[i]; + FilamentBuffers& buffers = owned_buffers_[i].buffers; + rm.setGeometryAt(rm.getInstance(entity), 0, + wireframe ? kWireframeType : buffers.type, + buffers.vertex_buffer, buffers.index_buffer, 0, + buffers.index_buffer->getIndexCount()); + } +} + + void Renderables::DisableShadows() { filament::RenderableManager& rm = engine_->getRenderableManager(); for (utils::Entity& entity : entities_) { diff --git a/src/experimental/filament/filament/renderables.h b/src/experimental/filament/filament/renderables.h index 45d3c008..ddb13fb5 100644 --- a/src/experimental/filament/filament/renderables.h +++ b/src/experimental/filament/filament/renderables.h @@ -73,20 +73,31 @@ class Renderables { // Sets the material instance for all managed entities. void SetMaterialInstance(filament::MaterialInstance* material_instance); + // If true, forces all entities to be rendered as lines. + void SetWireframe(bool wireframe); + // Returns the filament Engine managing the entities in this collection. filament::Engine* GetEngine() { return engine_; } private: utils::Entity CreateEntity(const FilamentBuffers& buffers); void UpdateEntity(utils::Entity entity, const FilamentBuffers& buffers); - void UpdateBuffers(int index, std::optional buffers); + void UpdateBuffers(int index, FilamentBuffers buffers, bool owned); + + // Tracks whether of not the filament buffers should be destroyed by this + // class. + struct OwnedBuffers { + bool owned = false; + FilamentBuffers buffers; + }; filament::Engine* engine_ = nullptr; filament::Scene* assigned_scene_ = nullptr; filament::MaterialInstance* material_instance_ = nullptr; std::vector entities_; - std::vector> owned_buffers_; + std::vector owned_buffers_; bool visible_ = true; + bool wireframe_ = false; bool cast_shadows_ = true; };