Manage dynamic meshes (skins, flexes) in model_objects.

Simplifies Renderable as it no longer has the option of owning
any Meshes. Instead, the ModelObjects owns the Meshes for
flex and skin geom (just like it owns all the other mjModel
Meshes).

PiperOrigin-RevId: 902485912
Change-Id: I8b9f9d394de6c46f7e25aa4b3885a374aad05294
This commit is contained in:
Haroon Qureshi
2026-04-20 01:23:20 -07:00
committed by Copybara-Service
parent 6bf31cf68a
commit f3f12bfad6
6 changed files with 30 additions and 51 deletions
@@ -630,20 +630,11 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) {
height_fields_[id] = std::make_unique<Mesh>(engine_, data);
}
MeshPtr ModelObjects::CreateFlexMesh(const mjvScene* scene,
const mjvGeom& geom) {
void ModelObjects::CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom) {
MeshData data;
DefaultMeshData(&data);
UpdateSkinFlexMeshData(&data, model_, scene, geom);
return std::make_unique<Mesh>(engine_, data);
}
MeshPtr ModelObjects::CreateSkinMesh(const mjvScene* scene,
const mjvGeom& geom) {
MeshData data;
DefaultMeshData(&data);
UpdateSkinFlexMeshData(&data, model_, scene, geom);
return std::make_unique<Mesh>(engine_, data);
dynamic_meshes_[geom.objid] = std::make_unique<Mesh>(engine_, data);
}
const Mesh* ModelObjects::GetMeshBuffer(int data_id) const {
@@ -672,6 +663,11 @@ const Mesh* ModelObjects::GetShapeBuffer(ShapeType shape) const {
return shapes_[shape].get();
}
const Mesh* ModelObjects::GetFlexSkinGeomMesh(int geom_id) const {
auto it = dynamic_meshes_.find(geom_id);
return it != dynamic_meshes_.end() ? it->second.get() : nullptr;
}
const Texture* ModelObjects::GetTexture(int tex_id) const {
auto it = textures_.find(tex_id);
return it != textures_.end() ? it->second.get() : nullptr;
@@ -15,6 +15,7 @@
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MODEL_OBJECTS_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MODEL_OBJECTS_H_
#include <array>
#include <memory>
#include <unordered_map>
#include <vector>
@@ -55,6 +56,8 @@ class ModelObjects {
void UploadHeightField(const mjModel* model, int id);
void CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom);
// Returns the filament engine used by the ModelObjects to create filament
// objects.
filament::Engine* GetEngine() const { return engine_; }
@@ -63,12 +66,10 @@ class ModelObjects {
const Mesh* GetShapeBuffer(ShapeType shape) const;
const Mesh* GetMeshBuffer(int data_id) const;
const Mesh* GetHeightFieldBuffer(int hfield_id) const;
const Mesh* GetFlexSkinGeomMesh(int geom_id) const;
const Texture* GetTexture(int tex_id) const;
const Texture* GetTexture(int mat_id, int role) const;
MeshPtr CreateFlexMesh(const mjvScene* scene, const mjvGeom& geom);
MeshPtr CreateSkinMesh(const mjvScene* scene, const mjvGeom& geom);
filament::Skybox* CreateSkybox();
filament::IndirectLight* CreateIndirectLight(int tex_id, float intensity);
@@ -86,10 +87,11 @@ class ModelObjects {
filament::Engine* engine_ = nullptr;
std::vector<filament::Skybox*> skyboxes_;
std::vector<filament::IndirectLight*> indirect_lights_;
std::array<MeshPtr, kNumShapes> shapes_;
std::unordered_map<int, MeshPtr> meshes_;
std::unordered_map<int, MeshPtr> convex_hulls_;
std::unordered_map<int, MeshPtr> height_fields_;
std::array<std::unique_ptr<Mesh>, kNumShapes> shapes_;
std::unordered_map<int, std::unique_ptr<Mesh>> meshes_;
std::unordered_map<int, std::unique_ptr<Mesh>> convex_hulls_;
std::unordered_map<int, std::unique_ptr<Mesh>> height_fields_;
std::unordered_map<int, std::unique_ptr<Mesh>> dynamic_meshes_;
std::unordered_map<int, std::unique_ptr<Texture>> textures_;
float specular_multiplier_ = 0.2f;
float shininess_multiplier_ = 0.1f;
@@ -66,25 +66,12 @@ void Renderable::RemoveLastEntity() {
void Renderable::UpdateMesh(int index, const Mesh* mesh, int elem_offset,
int elem_count) {
MeshInfo& mesh_info = SetMesh(index, mesh, nullptr, elem_offset, elem_count);
UpdateEntity(index, mesh_info);
}
void Renderable::UpdateMesh(int index, MeshPtr mesh, int elem_offset,
int elem_count) {
MeshInfo& mesh_info =
SetMesh(index, mesh.get(), std::move(mesh), elem_offset, elem_count);
MeshInfo& mesh_info = SetMesh(index, mesh, elem_offset, elem_count);
UpdateEntity(index, mesh_info);
}
void Renderable::AppendMesh(const Mesh* mesh, int elem_offset, int elem_count) {
MeshInfo& mesh_info = SetMesh(-1, mesh, nullptr, elem_offset, elem_count);
AppendEntity(mesh_info);
}
void Renderable::AppendMesh(MeshPtr mesh, int elem_offset, int elem_count) {
MeshInfo& mesh_info =
SetMesh(-1, mesh.get(), std::move(mesh), elem_offset, elem_count);
MeshInfo& mesh_info = SetMesh(-1, mesh, elem_offset, elem_count);
AppendEntity(mesh_info);
}
@@ -154,8 +141,7 @@ void Renderable::UpdateEntity(int index, const MeshInfo& mesh_info) {
}
Renderable::MeshInfo& Renderable::SetMesh(int index, const Mesh* mesh,
MeshPtr owned_mesh, int elem_offset,
int elem_count) {
int elem_offset, int elem_count) {
if (index == -1) {
index = meshes_.size();
meshes_.emplace_back();
@@ -165,7 +151,6 @@ Renderable::MeshInfo& Renderable::SetMesh(int index, const Mesh* mesh,
}
MeshInfo* mesh_info = &meshes_[index];
mesh_info->owned_mesh = std::move(owned_mesh);
mesh_info->mesh = mesh;
mesh_info->elem_offset = elem_offset;
mesh_info->elem_count = elem_count;
@@ -60,15 +60,12 @@ class Renderable {
// can be used to specify a submesh to append. If elem_count is 0, assumes
// the entire mesh should be appended.
void AppendMesh(const Mesh* mesh, int elem_offset = 0, int elem_count = 0);
void AppendMesh(MeshPtr mesh, int elem_offset = 0, int elem_count = 0);
// Replaces the mesh at the index with a new mesh. The elem_offset and
// elem_count parameters can be used to specify a submesh to append. If
// elem_count is 0, assumes the entire mesh should be appended.
void UpdateMesh(int index, const Mesh* mesh, int elem_offset = 0,
int elem_count = 0);
void UpdateMesh(int index, MeshPtr mesh, int elem_offset = 0,
int elem_count = 0);
// Returns the number of meshes that define the renderable.
int GetNumMeshes() const { return meshes_.size(); }
@@ -124,7 +121,6 @@ class Renderable {
private:
struct MeshInfo {
MeshPtr owned_mesh;
const Mesh* mesh = nullptr;
int elem_offset = 0;
int elem_count = 0;
@@ -132,8 +128,8 @@ class Renderable {
// Sets the mesh information for the mesh at the given index. If index is -1,
// a new mesh will be appended to the renderable.
MeshInfo& SetMesh(int index, const Mesh* mesh, MeshPtr owned_mesh,
int elem_offset, int elem_count);
MeshInfo& SetMesh(int index, const Mesh* mesh, int elem_offset,
int elem_count);
// Appends a new filament::Entity to the renderable, configured to use the
// given mesh.
@@ -381,6 +381,10 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
}
}
if (geom->type == mjGEOM_FLEX || geom->type == mjGEOM_SKIN) {
model_objects_->CreateSkinFlexMesh(scene, *geom);
}
std::unique_ptr<Renderable> renderable = CreateGeomRenderable(
*geom, scene, object_mgr_, model_objects_.get(), headpos);
@@ -96,13 +96,9 @@ static void AddMesh(Renderable& renderable, ModelObjects* model_objs,
renderable.AppendMesh(mesh);
}
static void AddGeom(Renderable& renderable, ModelObjects* model_objs,
const mjvScene* scene, const mjvGeom& geom) {
if (geom.type == mjGEOM_FLEX) {
renderable.AppendMesh(model_objs->CreateFlexMesh(scene, geom));
} else if (geom.type == mjGEOM_SKIN) {
renderable.AppendMesh(model_objs->CreateSkinMesh(scene, geom));
}
static void AddSkinFlexMesh(Renderable& renderable, ModelObjects* model_objs,
int objid) {
renderable.AppendMesh(model_objs->GetFlexSkinGeomMesh(objid));
}
static void AddHeightField(Renderable& renderable, ModelObjects* model_objs,
@@ -183,10 +179,10 @@ static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
AddShape(renderable, model_objects, ModelObjects::kTriangle);
break;
case mjGEOM_FLEX:
AddGeom(renderable, model_objects, scene, geom);
AddSkinFlexMesh(renderable, model_objects, geom.objid);
break;
case mjGEOM_SKIN:
AddGeom(renderable, model_objects, scene, geom);
AddSkinFlexMesh(renderable, model_objects, geom.objid);
break;
case mjGEOM_NONE:
case mjGEOM_LABEL: