From 28d8ddcbebeee137c5fdd282c1959571f502a1a9 Mon Sep 17 00:00:00 2001 From: Haroon Qureshi Date: Tue, 7 Apr 2026 03:24:09 -0700 Subject: [PATCH] Rename FilamentBuffers class to Mesh. Update the Mesh class so that it manages the lifetime of the vertex and index buffers. PiperOrigin-RevId: 895794022 Change-Id: I5eda578b8b7ed7f918e792f6181ec724729b5215 --- .../filament/filament/buffer_util.h | 57 +++++++++-- .../filament/filament/builtins.cc | 87 ++++++++--------- src/experimental/filament/filament/builtins.h | 20 ++-- .../filament/filament/drawable.cc | 19 ++-- .../filament/filament/geom_util.cc | 18 ++-- .../filament/filament/geom_util.h | 5 +- .../filament/filament/gui_view.cc | 35 +++---- src/experimental/filament/filament/gui_view.h | 2 +- .../filament/filament/model_objects.cc | 76 ++++++--------- .../filament/filament/model_objects.h | 14 +-- .../filament/filament/renderables.cc | 95 +++++++++---------- .../filament/filament/renderables.h | 31 +++--- 12 files changed, 238 insertions(+), 221 deletions(-) diff --git a/src/experimental/filament/filament/buffer_util.h b/src/experimental/filament/filament/buffer_util.h index b6167ff8..5b5c576b 100644 --- a/src/experimental/filament/filament/buffer_util.h +++ b/src/experimental/filament/filament/buffer_util.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,15 +31,59 @@ // Functions for creating filament vertex and index buffers. namespace mujoco { -// Simple tuple-type of a IndexBuffer+VertexBuffer. -struct FilamentBuffers { - filament::IndexBuffer* index_buffer = nullptr; - filament::VertexBuffer* vertex_buffer = nullptr; - std::optional bounds = std::nullopt; - filament::RenderableManager::PrimitiveType type = +// Owns a Vertex and Index buffer representing a geometry mesh. +class Mesh { + public: + Mesh(filament::Engine* engine, filament::IndexBuffer* index_buffer, + filament::VertexBuffer* vertex_buffer, + std::optional bounds = std::nullopt, + filament::RenderableManager::PrimitiveType type = + filament::RenderableManager::PrimitiveType::TRIANGLES) + : engine_(engine), + index_buffer_(index_buffer), + vertex_buffer_(vertex_buffer), + type_(type), + bounds_(bounds) {} + + ~Mesh() { + if (index_buffer_) { + engine_->destroy(index_buffer_); + } + if (vertex_buffer_) { + engine_->destroy(vertex_buffer_); + } + } + + filament::IndexBuffer* GetFilamentIndexBuffer() const { + return index_buffer_; + } + filament::VertexBuffer* GetFilamentVertexBuffer() const { + return vertex_buffer_; + } + filament::RenderableManager::PrimitiveType GetPrimitiveType() const { + return type_; + } + bool HasBounds() const { + return bounds_.has_value(); + } + filament::Box GetBounds() const { + return bounds_.value(); + } + + Mesh(const Mesh&) = delete; + Mesh& operator=(const Mesh&) = delete; + + private: + filament::Engine* engine_ = nullptr; + filament::IndexBuffer* index_buffer_ = nullptr; + filament::VertexBuffer* vertex_buffer_ = nullptr; + filament::RenderableManager::PrimitiveType type_ = filament::RenderableManager::PrimitiveType::TRIANGLES; + std::optional bounds_; }; +using MeshPtr = std::unique_ptr; + // Function that fills in the given buffer with actual data. using FillBufferFn = std::function; diff --git a/src/experimental/filament/filament/builtins.cc b/src/experimental/filament/filament/builtins.cc index 825aa953..3e4732e4 100644 --- a/src/experimental/filament/filament/builtins.cc +++ b/src/experimental/filament/filament/builtins.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -422,8 +423,8 @@ class ConeBuilder { int idx = 0; for (int j = 0; j < num_slices_; ++j) { - const float angle1 = (j+0) * delta_angle; - const float angle2 = (j+1) * delta_angle; + const float angle1 = (j + 0) * delta_angle; + const float angle2 = (j + 1) * delta_angle; ptr[idx++] = MakeVert(angle1, delta_radius); ptr[idx++] = MakeVert(angle2, delta_radius); @@ -436,12 +437,12 @@ class ConeBuilder { // the rest: use quads for (int i = 1; i < num_stacks_; ++i) { - const float radius1 = delta_radius * (i+0); - const float radius2 = delta_radius * (i+1); + const float radius1 = delta_radius * (i + 0); + const float radius2 = delta_radius * (i + 1); for (int j = 0; j < num_slices_; ++j) { - const float angle1 = (j+0) * delta_angle; - const float angle2 = (j+1) * delta_angle; + const float angle1 = (j + 0) * delta_angle; + const float angle2 = (j + 1) * delta_angle; ptr[idx++] = MakeVert(angle1, radius2); ptr[idx++] = MakeVert(angle2, radius2); @@ -676,34 +677,34 @@ class DomeBuilder { (num_quads_body * kNumIndicesPerQuad); } - void GenerateVertices(VertexType* ptr, size_t num) const { - const float lat_angle_delta = - 0.5 * std::numbers::pi / static_cast(num_stacks_); - const float lon_angle_delta = - 2.0 * std::numbers::pi / static_cast(num_slices_); + void GenerateVertices(VertexType* ptr, size_t num) const { + const float lat_angle_delta = + 0.5 * std::numbers::pi / static_cast(num_stacks_); + const float lon_angle_delta = + 2.0 * std::numbers::pi / static_cast(num_slices_); - // Add the pole. - int idx = 0; - ptr[idx++] = MakeVert(0, 0, 1); + // Add the pole. + int idx = 0; + ptr[idx++] = MakeVert(0, 0, 1); - // Vertices by latitude. - for (int lat = 0; lat < num_stacks_; ++lat) { - // +1 because we handle the north pole (which would be at a lat angle of - // 0-degrees) explicitly. - const float lat_angle = static_cast(lat + 1) * lat_angle_delta; - const float cos_lat_angle = std::cos(lat_angle); - const float sin_lat_angle = std::sin(lat_angle); - const float z = cos_lat_angle; + // Vertices by latitude. + for (int lat = 0; lat < num_stacks_; ++lat) { + // +1 because we handle the north pole (which would be at a lat angle of + // 0-degrees) explicitly. + const float lat_angle = static_cast(lat + 1) * lat_angle_delta; + const float cos_lat_angle = std::cos(lat_angle); + const float sin_lat_angle = std::sin(lat_angle); + const float z = cos_lat_angle; - for (int lon = 0; lon < num_slices_; ++lon) { - const float lon_angle = static_cast(lon) * lon_angle_delta; - const float cos_lon_angle = std::cos(lon_angle); - const float sin_lon_angle = std::sin(lon_angle); + for (int lon = 0; lon < num_slices_; ++lon) { + const float lon_angle = static_cast(lon) * lon_angle_delta; + const float cos_lon_angle = std::cos(lon_angle); + const float sin_lon_angle = std::sin(lon_angle); - const float x = sin_lat_angle * cos_lon_angle; - const float y = sin_lat_angle * sin_lon_angle; - ptr[idx++] = MakeVert(x, y, z); - } + const float x = sin_lat_angle * cos_lon_angle; + const float y = sin_lat_angle * sin_lon_angle; + ptr[idx++] = MakeVert(x, y, z); + } } } @@ -756,9 +757,8 @@ class DomeBuilder { int num_slices_; }; - template -FilamentBuffers CreateFromBuilder(filament::Engine* engine, const T& builder) { +MeshPtr CreateFromBuilder(filament::Engine* engine, const T& builder) { using VertexType = typename T::VertexType; using IndexType = typename T::IndexType; @@ -786,46 +786,47 @@ FilamentBuffers CreateFromBuilder(filament::Engine* engine, const T& builder) { auto vb = CreateVertexBuffer(engine, num_vertices, vertices); auto ib = CreateIndexBuffer(engine, num_indices, indices); - return {ib, vb, builder.GetBounds(), T::kPrimitiveType}; + return std::make_unique(engine, ib, vb, builder.GetBounds(), + T::kPrimitiveType); } -FilamentBuffers CreateLine(filament::Engine* engine) { +MeshPtr CreateLine(filament::Engine* engine) { return CreateFromBuilder(engine, LineBuilder()); } -FilamentBuffers CreatePlane(filament::Engine* engine, int nquad) { +MeshPtr CreatePlane(filament::Engine* engine, int nquad) { return CreateFromBuilder(engine, PlaneBuilder(nquad)); } -FilamentBuffers CreateTriangle(filament::Engine* engine) { +MeshPtr CreateTriangle(filament::Engine* engine) { return CreateFromBuilder(engine, TriangleBuilder()); } -FilamentBuffers CreateBox(filament::Engine* engine, int nquad) { +MeshPtr CreateBox(filament::Engine* engine, int nquad) { return CreateFromBuilder(engine, BoxBuilder(nquad)); } -FilamentBuffers CreateLineBox(filament::Engine* engine) { +MeshPtr CreateLineBox(filament::Engine* engine) { return CreateFromBuilder(engine, LineBoxBuilder()); } -FilamentBuffers CreateSphere(filament::Engine* engine, int nstack, int nslice) { +MeshPtr CreateSphere(filament::Engine* engine, int nstack, int nslice) { return CreateFromBuilder(engine, SphereBuilder(nstack, nslice)); } -FilamentBuffers CreateTube(filament::Engine* engine, int nstack, int nslice) { +MeshPtr CreateTube(filament::Engine* engine, int nstack, int nslice) { return CreateFromBuilder(engine, TubeBuilder(nstack, nslice)); } -FilamentBuffers CreateDisk(filament::Engine* engine, int nslice) { +MeshPtr CreateDisk(filament::Engine* engine, int nslice) { return CreateFromBuilder(engine, DiskBuilder(nslice)); } -FilamentBuffers CreateDome(filament::Engine* engine, int nstack, int nslice) { +MeshPtr CreateDome(filament::Engine* engine, int nstack, int nslice) { return CreateFromBuilder(engine, DomeBuilder(nstack, nslice)); } -FilamentBuffers CreateCone(filament::Engine* engine, int nstack, int nslice) { +MeshPtr CreateCone(filament::Engine* engine, int nstack, int nslice) { return CreateFromBuilder(engine, ConeBuilder(nstack, nslice)); } diff --git a/src/experimental/filament/filament/builtins.h b/src/experimental/filament/filament/builtins.h index 713fa6d1..b79083a3 100644 --- a/src/experimental/filament/filament/builtins.h +++ b/src/experimental/filament/filament/builtins.h @@ -21,16 +21,16 @@ // Generates buffers for built-in shapes. namespace mujoco { -FilamentBuffers CreateLine(filament::Engine* engine); -FilamentBuffers CreatePlane(filament::Engine* engine, int nquad); -FilamentBuffers CreateTriangle(filament::Engine* engine); -FilamentBuffers CreateBox(filament::Engine* engine, int nquad); -FilamentBuffers CreateLineBox(filament::Engine* engine); -FilamentBuffers CreateSphere(filament::Engine* engine, int nstack, int nslice); -FilamentBuffers CreateTube(filament::Engine* engine, int nstack, int nslice); -FilamentBuffers CreateDisk(filament::Engine* engine, int nslice); -FilamentBuffers CreateDome(filament::Engine* engine, int nstack, int nslice); -FilamentBuffers CreateCone(filament::Engine* engine, int nstack, int nslice); +MeshPtr CreateLine(filament::Engine* engine); +MeshPtr CreatePlane(filament::Engine* engine, int nquad); +MeshPtr CreateTriangle(filament::Engine* engine); +MeshPtr CreateBox(filament::Engine* engine, int nquad); +MeshPtr CreateLineBox(filament::Engine* engine); +MeshPtr CreateSphere(filament::Engine* engine, int nstack, int nslice); +MeshPtr CreateTube(filament::Engine* engine, int nstack, int nslice); +MeshPtr CreateDisk(filament::Engine* engine, int nslice); +MeshPtr CreateDome(filament::Engine* engine, int nstack, int nslice); +MeshPtr CreateCone(filament::Engine* engine, int nstack, int nslice); } // namespace mujoco diff --git a/src/experimental/filament/filament/drawable.cc b/src/experimental/filament/filament/drawable.cc index f32afe1a..a377d1f6 100644 --- a/src/experimental/filament/filament/drawable.cc +++ b/src/experimental/filament/filament/drawable.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -173,12 +174,12 @@ void Drawable::Update(const mjModel* model, const mjvScene* scene, if (geom.type == mjGEOM_FLEX || geom.type == mjGEOM_SKIN) { // Flex geometry is updated every frame with new vertex data. filament::Engine* engine = renderables_.GetEngine(); - FilamentBuffers buffers = CreateGeomBuffers(engine, model, scene, geom); + std::unique_ptr mesh = CreateGeomBuffers(engine, model, scene, geom); if (renderables_.GetNumEntities() == 0) { - renderables_.Append(std::move(buffers)); + renderables_.Append(std::move(mesh)); } else { - renderables_.Update(0, std::move(buffers)); + renderables_.Update(0, std::move(mesh)); } } @@ -192,27 +193,27 @@ void Drawable::Update(const mjModel* model, const mjvScene* scene, } void Drawable::AddMesh(int data_id) { - const FilamentBuffers* buffers = model_objs_->GetMeshBuffer(data_id); + const Mesh* buffers = model_objs_->GetMeshBuffer(data_id); if (buffers == nullptr) { mju_error("Unknown mesh %d", data_id); } - renderables_.Append(*buffers); + renderables_.Append(buffers); } void Drawable::AddHeightField(int hfield_id) { - const FilamentBuffers* buffers = model_objs_->GetHeightFieldBuffer(hfield_id); + const Mesh* buffers = model_objs_->GetHeightFieldBuffer(hfield_id); if (buffers == nullptr) { mju_error("Unknown height field %d", hfield_id); } - renderables_.Append(*buffers); + renderables_.Append(buffers); } void Drawable::AddShape(ModelObjects::ShapeType shape_type) { - const FilamentBuffers* buffers = model_objs_->GetShapeBuffer(shape_type); + const Mesh* buffers = model_objs_->GetShapeBuffer(shape_type); if (buffers == nullptr) { mju_error("Unknown shape %d", shape_type); } - renderables_.Append(*buffers); + renderables_.Append(buffers); } void Drawable::AddToScene(filament::Scene* scene) { diff --git a/src/experimental/filament/filament/geom_util.cc b/src/experimental/filament/filament/geom_util.cc index a26fd073..38d7509b 100644 --- a/src/experimental/filament/filament/geom_util.cc +++ b/src/experimental/filament/filament/geom_util.cc @@ -18,8 +18,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -162,9 +164,8 @@ static filament::IndexBuffer* BuildIndexBuffer(filament::Engine* engine, } } -FilamentBuffers CreateGeomBuffers(filament::Engine* engine, - const mjModel* model, const mjvScene* scene, - const mjvGeom& geom) { +MeshPtr CreateGeomBuffers(filament::Engine* engine, const mjModel* model, + const mjvScene* scene, const mjvGeom& geom) { auto positions = GetPositions(model, scene, geom); auto normals = GetNormals(model, scene, geom); auto uvs = GetUvs(model, scene, geom); @@ -175,14 +176,13 @@ FilamentBuffers CreateGeomBuffers(filament::Engine* engine, num_indices = 3 * scene->flexfaceused[geom.objid]; } - FilamentBuffers buffers; float3 vmin = {FLT_MAX, FLT_MAX, FLT_MAX}; float3 vmax = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; - buffers.vertex_buffer = - BuildVertexBuffer(engine, positions, normals, uvs, &vmin, &vmax); - buffers.index_buffer = BuildIndexBuffer(engine, indices, num_indices); - buffers.bounds.emplace().set(vmin, vmax); - return buffers; + auto vertex_buffer = BuildVertexBuffer(engine, positions, normals, uvs, &vmin, &vmax); + auto index_buffer = BuildIndexBuffer(engine, indices, num_indices); + filament::Box bounds; + bounds.set(vmin, vmax); + return std::make_unique(engine, index_buffer, vertex_buffer, bounds); } } // namespace mujoco diff --git a/src/experimental/filament/filament/geom_util.h b/src/experimental/filament/filament/geom_util.h index b6b1e6a1..55c14db0 100644 --- a/src/experimental/filament/filament/geom_util.h +++ b/src/experimental/filament/filament/geom_util.h @@ -22,9 +22,8 @@ namespace mujoco { // Populates the FilamentBuffers for a flex geometry. -FilamentBuffers CreateGeomBuffers(filament::Engine* engine, - const mjModel* model, const mjvScene* scene, - const mjvGeom& geom); +MeshPtr CreateGeomBuffers(filament::Engine* engine, const mjModel* model, + const mjvScene* scene, const mjvGeom& geom); } // namespace mujoco diff --git a/src/experimental/filament/filament/gui_view.cc b/src/experimental/filament/filament/gui_view.cc index 1876936e..2217c95b 100644 --- a/src/experimental/filament/filament/gui_view.cc +++ b/src/experimental/filament/filament/gui_view.cc @@ -62,10 +62,7 @@ GuiView::~GuiView() { } auto& em = utils::EntityManager::get(); em.destroy(renderable_); - for (auto& buffer : buffers_) { - engine_->destroy(buffer.vertex_buffer); - engine_->destroy(buffer.index_buffer); - } + meshes_.clear(); for (auto& instance : instances_) { engine_->destroy(instance); } @@ -84,12 +81,7 @@ void GuiView::ResetRenderable() { em.destroy(renderable_); renderable_ = utils::Entity(); } - - for (auto& buffer : buffers_) { - engine_->destroy(buffer.vertex_buffer); - engine_->destroy(buffer.index_buffer); - } - buffers_.clear(); + meshes_.clear(); } uintptr_t GuiView::UploadImage(uintptr_t tex_id, const uint8_t* pixels, @@ -275,12 +267,7 @@ void GuiView::UpdateRenderable() { builder.build(*engine_, renderable_); scene_->addEntity(renderable_); } - - for (auto& buffer : buffers_) { - engine_->destroy(buffer.vertex_buffer); - engine_->destroy(buffer.index_buffer); - } - buffers_.clear(); + meshes_.clear(); auto ri = rm.getInstance(renderable_); @@ -299,10 +286,13 @@ void GuiView::UpdateRenderable() { } std::memcpy(dst, cmds->IdxBuffer.Data, size); }; - buffers_.push_back( - {CreateIndexBuffer(engine_, cmds->IdxBuffer.Size, ifill), - CreateVertexBuffer(engine_, cmds->VtxBuffer.Size, vfill)}); - const mujoco::FilamentBuffers& buffer = buffers_.back(); + filament::IndexBuffer* index_buffer = + CreateIndexBuffer(engine_, cmds->IdxBuffer.Size, ifill); + filament::VertexBuffer* vertex_buffer = + CreateVertexBuffer(engine_, cmds->VtxBuffer.Size, vfill); + + meshes_.push_back(std::make_unique(engine_, index_buffer, vertex_buffer)); + const auto& mesh = meshes_.back(); int index_offset = 0; for (const ImDrawCmd& command : cmds->CmdBuffer) { @@ -327,8 +317,9 @@ void GuiView::UpdateRenderable() { rm.setMaterialInstanceAt( ri, drawable_index, GetMaterialInstance(drawable_index, clip_rect, command.GetTexID())); - rm.setGeometryAt(ri, drawable_index, kTriangles, buffer.vertex_buffer, - buffer.index_buffer, index_offset, command.ElemCount); + rm.setGeometryAt( + ri, drawable_index, kTriangles, mesh->GetFilamentVertexBuffer(), + mesh->GetFilamentIndexBuffer(), index_offset, command.ElemCount); rm.setBlendOrderAt(ri, drawable_index, drawable_index); index_offset += command.ElemCount; diff --git a/src/experimental/filament/filament/gui_view.h b/src/experimental/filament/filament/gui_view.h index 2b189324..d1f80cd8 100644 --- a/src/experimental/filament/filament/gui_view.h +++ b/src/experimental/filament/filament/gui_view.h @@ -71,7 +71,7 @@ class GuiView { filament::View* view_ = nullptr; filament::Material* material_ = nullptr; utils::Entity renderable_; - std::vector buffers_; + std::vector meshes_; std::vector instances_; std::unordered_map> textures_; int num_elements_ = 0; diff --git a/src/experimental/filament/filament/model_objects.cc b/src/experimental/filament/filament/model_objects.cc index 3df4f2e2..7f8a438c 100644 --- a/src/experimental/filament/filament/model_objects.cc +++ b/src/experimental/filament/filament/model_objects.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include "experimental/filament/filament/model_util.h" #include "experimental/filament/filament/texture.h" - namespace mujoco { ModelObjects::ModelObjects(const mjModel* model, filament::Engine* engine) @@ -73,14 +73,7 @@ ModelObjects::~ModelObjects() { for (auto& iter : indirect_lights_) { engine_->destroy(iter); } - for (auto& iter : meshes_) { - engine_->destroy(iter.second.vertex_buffer); - engine_->destroy(iter.second.index_buffer); - } - for (auto& iter : shapes_) { - engine_->destroy(iter.vertex_buffer); - engine_->destroy(iter.index_buffer); - } + meshes_.clear(); textures_.clear(); } @@ -88,32 +81,25 @@ void ModelObjects::UploadMesh(const mjModel* model, int id) { if (model != model_) { mju_error("Model mismatch."); } - if (id < 0 || id >= model->nmesh) { + if (id < 0 || id >= model->nmesh) { mju_error("Invalid mesh index %d", id); } + meshes_.erase(id); + convex_hulls_.erase(id); - if (auto iter = meshes_.find(id); iter != meshes_.end()) { - engine_->destroy(iter->second.vertex_buffer); - engine_->destroy(iter->second.index_buffer); - } - if (auto iter = convex_hulls_.find(id); iter != convex_hulls_.end()) { - engine_->destroy(iter->second.vertex_buffer); - engine_->destroy(iter->second.index_buffer); - } - - FilamentBuffers& buffers = meshes_[id]; - buffers.vertex_buffer = CreateVertexBuffer( - engine_, model, id, MeshType::kNormal, &buffers.bounds.emplace()); - buffers.index_buffer = - CreateIndexBuffer(engine_, model, id, MeshType::kNormal); + filament::Box bounds; + auto vertex_buffer = + CreateVertexBuffer(engine_, model, id, MeshType::kNormal, &bounds); + auto index_buffer = CreateIndexBuffer(engine_, model, id, MeshType::kNormal); + meshes_[id] = + std::make_unique(engine_, index_buffer, vertex_buffer, bounds); if (model->mesh_graphadr[id] >= 0) { - FilamentBuffers& hull_buffers = convex_hulls_[id]; - hull_buffers.vertex_buffer = - CreateVertexBuffer(engine_, model, id, MeshType::kConvexHull, - &hull_buffers.bounds.emplace()); - hull_buffers.index_buffer = - CreateIndexBuffer(engine_, model, id, MeshType::kConvexHull); + vertex_buffer = + CreateVertexBuffer(engine_, model, id, MeshType::kConvexHull, &bounds); + index_buffer = CreateIndexBuffer(engine_, model, id, MeshType::kConvexHull); + convex_hulls_[id] = + std::make_unique(engine_, index_buffer, vertex_buffer, bounds); } } @@ -172,43 +158,41 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) { mju_error("Invalid height field index %d", id); } - if (auto iter = height_fields_.find(id); iter != height_fields_.end()) { - engine_->destroy(iter->second.vertex_buffer); - engine_->destroy(iter->second.index_buffer); - } + height_fields_.erase(id); - FilamentBuffers& buffers = height_fields_[id]; - buffers.vertex_buffer = CreateVertexBuffer( - engine_, model, id, MeshType::kHeightField, &buffers.bounds.emplace()); - buffers.index_buffer = + filament::Box bounds; + auto vertex_buffer = + CreateVertexBuffer(engine_, model, id, MeshType::kHeightField, &bounds); + auto index_buffer = CreateIndexBuffer(engine_, model, id, MeshType::kHeightField); + height_fields_[id] = + std::make_unique(engine_, index_buffer, vertex_buffer, bounds); } -const FilamentBuffers* ModelObjects::GetMeshBuffer(int data_id) const { +const Mesh* ModelObjects::GetMeshBuffer(int data_id) const { // As defined by mjv_updateScene: // original mesh: mesh_id * 2 // convex hull: (mesh_id * 2) + 1 const int mesh_id = data_id / 2; if (data_id % 2 == 0) { auto it = meshes_.find(mesh_id); - return it != meshes_.end() ? &it->second : nullptr; + return it != meshes_.end() ? it->second.get() : nullptr; } else { auto it = convex_hulls_.find(mesh_id); - return it != convex_hulls_.end() ? &it->second : nullptr; + return it != convex_hulls_.end() ? it->second.get() : nullptr; } } -const FilamentBuffers* ModelObjects::GetHeightFieldBuffer( - int hfield_id) const { +const Mesh* ModelObjects::GetHeightFieldBuffer(int hfield_id) const { auto it = height_fields_.find(hfield_id); - return it != height_fields_.end() ? &it->second : nullptr; + return it != height_fields_.end() ? it->second.get() : nullptr; } -const FilamentBuffers* ModelObjects::GetShapeBuffer(ShapeType shape) const { +const Mesh* ModelObjects::GetShapeBuffer(ShapeType shape) const { if (shape < 0 || shape >= kNumShapes) { mju_error("Invalid shape type: %d", shape); } - return &shapes_[shape]; + return shapes_[shape].get(); } const Texture* ModelObjects::GetTexture(int tex_id) const { diff --git a/src/experimental/filament/filament/model_objects.h b/src/experimental/filament/filament/model_objects.h index 7007e81a..f694b4de 100644 --- a/src/experimental/filament/filament/model_objects.h +++ b/src/experimental/filament/filament/model_objects.h @@ -61,9 +61,9 @@ class ModelObjects { filament::Engine* GetEngine() const { return engine_; } // Returns the cached instance of a filament object created from the mjModel. - const FilamentBuffers* GetShapeBuffer(ShapeType shape) const; - const FilamentBuffers* GetMeshBuffer(int data_id) const; - const FilamentBuffers* GetHeightFieldBuffer(int hfield_id) const; + const Mesh* GetShapeBuffer(ShapeType shape) const; + const Mesh* GetMeshBuffer(int data_id) const; + const Mesh* GetHeightFieldBuffer(int hfield_id) const; const Texture* GetTexture(int tex_id) const; const Texture* GetTexture(int mat_id, int role) const; @@ -84,10 +84,10 @@ class ModelObjects { filament::Engine* engine_ = nullptr; std::vector skyboxes_; std::vector indirect_lights_; - std::array shapes_; - std::unordered_map meshes_; - std::unordered_map convex_hulls_; - std::unordered_map height_fields_; + std::array shapes_; + std::unordered_map meshes_; + std::unordered_map convex_hulls_; + std::unordered_map height_fields_; std::unordered_map> textures_; float specular_multiplier_ = 0.2f; float shininess_multiplier_ = 0.1f; diff --git a/src/experimental/filament/filament/renderables.cc b/src/experimental/filament/filament/renderables.cc index fcce336f..5be61556 100644 --- a/src/experimental/filament/filament/renderables.cc +++ b/src/experimental/filament/filament/renderables.cc @@ -15,7 +15,7 @@ #include "experimental/filament/filament/renderables.h" #include -#include +#include #include #include @@ -49,67 +49,65 @@ void Renderables::RemoveLast() { engine_->destroy(entity); em.destroy(entity); entities_.pop_back(); - - 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(); + meshes_.pop_back(); } -void Renderables::Update(int index, const FilamentBuffers& buffers) { +void Renderables::Update(int index, const Mesh* mesh) { if (index < 0 || index >= entities_.size()) { mju_error("Invalid index %d for renderable.", index); } utils::Entity& entity = entities_[index]; - UpdateEntity(entity, buffers); - UpdateBuffers(index, buffers, false); + UpdateEntity(entity, mesh); + UpdateMeshes(index, mesh); } -void Renderables::Update(int index, FilamentBuffers&& buffers) { +void Renderables::Update(int index, MeshPtr mesh) { if (index < 0 || index >= entities_.size()) { mju_error("Invalid index %d for renderable.", index); } utils::Entity& entity = entities_[index]; - UpdateEntity(entity, buffers); - UpdateBuffers(index, buffers, true); + UpdateEntity(entity, mesh.get()); + UpdateMeshes(index, mesh.get(), std::move(mesh)); } -void Renderables::Append(const FilamentBuffers& buffers) { - utils::Entity entity = CreateEntity(buffers); +void Renderables::Append(const Mesh* mesh) { + utils::Entity entity = CreateEntity(mesh); entities_.push_back(entity); - owned_buffers_.push_back({.owned = false, .buffers = buffers}); + meshes_.emplace_back(nullptr, mesh); } -void Renderables::Append(FilamentBuffers&& buffers) { - utils::Entity entity = CreateEntity(buffers); +void Renderables::Append(MeshPtr mesh) { + utils::Entity entity = CreateEntity(mesh.get()); entities_.push_back(entity); - owned_buffers_.push_back({.owned = true, .buffers = buffers}); + meshes_.emplace_back(std::move(mesh), mesh.get()); } -utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) { - if (buffers.vertex_buffer == nullptr) { +utils::Entity Renderables::CreateEntity(const Mesh* mesh) { + filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer(); + if (vertex_buffer == nullptr) { mju_error("Invalid (null) vertex buffer."); } - if (buffers.index_buffer == nullptr) { + + filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer(); + if (index_buffer == nullptr) { mju_error("Invalid (null) index buffer."); } + utils::Entity entity = utils::EntityManager::get().create(); if (entity.isNull()) { mju_error("Failed to create entity."); } filament::RenderableManager::Builder builder(1); - builder.geometry(0, buffers.type, buffers.vertex_buffer, - buffers.index_buffer); - if (material_instance_) { - builder.material(0, material_instance_); - } - if (buffers.bounds.has_value()) { - builder.boundingBox(buffers.bounds.value()); + builder.geometry(0, mesh->GetPrimitiveType(), vertex_buffer, index_buffer); + if (mesh->HasBounds()) { + builder.boundingBox(mesh->GetBounds()); } else { builder.culling(false); } + if (material_instance_) { + builder.material(0, material_instance_); + } builder.castShadows(cast_shadows_); builder.receiveShadows(receive_shadows_); builder.layerMask(0xff, layer_mask_); @@ -123,30 +121,29 @@ utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) { return entity; } -void Renderables::UpdateEntity(utils::Entity entity, - const FilamentBuffers& buffers) { - if (buffers.vertex_buffer == nullptr) { +void Renderables::UpdateEntity(utils::Entity entity, const Mesh* mesh) { + filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer(); + if (vertex_buffer == nullptr) { mju_error("Invalid (null) vertex buffer."); } - if (buffers.index_buffer == nullptr) { + + filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer(); + if (index_buffer == nullptr) { mju_error("Invalid (null) index buffer."); } + filament::RenderableManager& rm = engine_->getRenderableManager(); - rm.setGeometryAt(rm.getInstance(entity), 0, buffers.type, - buffers.vertex_buffer, buffers.index_buffer, 0, - buffers.index_buffer->getIndexCount()); + rm.setGeometryAt(rm.getInstance(entity), 0, mesh->GetPrimitiveType(), + vertex_buffer, index_buffer, 0, + index_buffer->getIndexCount()); } -void Renderables::UpdateBuffers(int index, FilamentBuffers buffers, bool owned) { - if (index < 0 || index >= owned_buffers_.size()) { +void Renderables::UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh) { + if (index < 0 || index >= meshes_.size()) { mju_error("Invalid index %d for renderable.", index); } - 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 = buffers; - owned_buffers_[index].owned = owned; + meshes_[index].owned_mesh = std::move(owned_mesh); + meshes_[index].mesh = mesh; } void Renderables::AddToScene(filament::Scene* scene) { @@ -239,11 +236,13 @@ void Renderables::SetWireframe(bool 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; + const Mesh* mesh = meshes_[i].mesh; + filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer(); + filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer(); rm.setGeometryAt(rm.getInstance(entity), 0, - wireframe_ ? kWireframeType : buffers.type, - buffers.vertex_buffer, buffers.index_buffer, 0, - buffers.index_buffer->getIndexCount()); + wireframe_ ? kWireframeType : mesh->GetPrimitiveType(), + vertex_buffer, index_buffer, 0, + index_buffer->getIndexCount()); } } } diff --git a/src/experimental/filament/filament/renderables.h b/src/experimental/filament/filament/renderables.h index bd6b3602..2108442a 100644 --- a/src/experimental/filament/filament/renderables.h +++ b/src/experimental/filament/filament/renderables.h @@ -16,7 +16,6 @@ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_ #include -#include #include #include @@ -39,13 +38,13 @@ class Renderables { Renderables(const Renderables&) = delete; Renderables& operator=(const Renderables&) = delete; - // Appends a new renderable entity built from the given buffers. - void Append(const FilamentBuffers& buffers); - void Append(FilamentBuffers&& buffers); + // Appends a new renderable entity built from the given mesh. + void Append(const Mesh* mesh); + void Append(MeshPtr mesh); - // Updates the entity at the index with new buffers. - void Update(int index, const FilamentBuffers& buffers); - void Update(int index, FilamentBuffers&& buffers); + // Updates the entity at the index with new mesh. + void Update(int index, const Mesh* mesh); + void Update(int index, MeshPtr mesh); // Removes the last entity. void RemoveLast(); @@ -53,7 +52,7 @@ class Renderables { // Returns the entity at the given index. utils::Entity operator[](int index) { return entities_[index]; } - // Returns the owned buffers at the given index. + // Returns the number of Entities that make up this renderable. int GetNumEntities() const { return entities_.size(); } // Hides all managed entities. @@ -84,22 +83,20 @@ class Renderables { filament::Engine* GetEngine() { return engine_; } private: - utils::Entity CreateEntity(const FilamentBuffers& buffers); - void UpdateEntity(utils::Entity entity, const FilamentBuffers& buffers); - void UpdateBuffers(int index, FilamentBuffers buffers, bool owned); + utils::Entity CreateEntity(const Mesh* mesh); + void UpdateEntity(utils::Entity entity, const Mesh* mesh); + void UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh = nullptr); - // Tracks whether of not the filament buffers should be destroyed by this - // class. - struct OwnedBuffers { - bool owned = false; - FilamentBuffers buffers; + struct MeshWrapper { + MeshPtr owned_mesh; + const Mesh* mesh = nullptr; }; filament::Engine* engine_ = nullptr; filament::Scene* assigned_scene_ = nullptr; filament::MaterialInstance* material_instance_ = nullptr; std::vector entities_; - std::vector owned_buffers_; + std::vector meshes_; std::uint8_t priority_ = kDefaultPriority; std::uint8_t layer_mask_ = kDefaultLayerMask; bool wireframe_ = false;