Remove ModelObjects and ObjectManager members from Drawable.

Split up the Update function into parts and allow SceneBridge
to call them individually, passing in the ModelObjects or
ObjectManager as needed.

PiperOrigin-RevId: 898851732
Change-Id: I25c6bf920b85caa7b2ddee045475f11fb7a8bac8
This commit is contained in:
Haroon Qureshi
2026-04-13 01:51:25 -07:00
committed by Copybara-Service
parent 45c6137ec2
commit 126d5b67e3
3 changed files with 130 additions and 142 deletions
+93 -119
View File
@@ -79,27 +79,16 @@ static float GetPlaneTileSize(const mjModel* model, int matid,
} }
} }
static bool IsBehind(const mjtNum* headpos, const float* pos, const float* mat) { static bool IsBehind(const float* headpos, const float* pos, const float* mat) {
return ((headpos[0] - pos[0]) * mat[2] + return ((headpos[0] - pos[0]) * mat[2] +
(headpos[1] - pos[1]) * mat[5] + (headpos[1] - pos[1]) * mat[5] +
(headpos[2] - pos[2]) * mat[8] < 0.0f); (headpos[2] - pos[2]) * mat[8] < 0.0f);
} }
Drawable::Drawable(ObjectManager* object_mgr, ModelObjects* model_objects, Drawable::Drawable(ModelObjects* model_objects, const mjvScene* scene,
const mjvGeom& geom, const mjvGeom& geom)
const Material::Textures* fallback_textures) : material_(model_objects->GetEngine()),
: material_(object_mgr->GetEngine()), renderables_(model_objects->GetEngine()) {
model_objs_(model_objects),
object_mgr_(object_mgr),
renderables_(object_mgr->GetEngine()) {
material_.SetMaterial(
Material::DrawMode::kDepth,
object_mgr_->GetMaterial(ObjectManager::kUnlitDepth));
material_.SetMaterial(
Material::DrawMode::kSegmentation,
object_mgr_->GetMaterial(ObjectManager::kUnlitSegmentation));
material_.SetFallbackTextures(fallback_textures);
if (geom.category == mjCAT_DECOR) { if (geom.category == mjCAT_DECOR) {
renderables_.SetCastShadows(false); renderables_.SetCastShadows(false);
renderables_.SetReceiveShadows(false); renderables_.SetReceiveShadows(false);
@@ -107,67 +96,69 @@ Drawable::Drawable(ObjectManager* object_mgr, ModelObjects* model_objects,
switch ((mjtGeom)geom.type) { switch ((mjtGeom)geom.type) {
case mjGEOM_MESH: case mjGEOM_MESH:
AddMesh(geom.dataid); AddMesh(model_objects, geom.dataid);
break; break;
case mjGEOM_HFIELD: case mjGEOM_HFIELD:
AddHeightField(geom.dataid); AddHeightField(model_objects, geom.dataid);
break; break;
case mjGEOM_PLANE: case mjGEOM_PLANE:
AddShape(ModelObjects::kPlane); AddShape(model_objects, ModelObjects::kPlane);
break; break;
case mjGEOM_SPHERE: case mjGEOM_SPHERE:
AddShape(ModelObjects::kSphere); AddShape(model_objects, ModelObjects::kSphere);
break; break;
case mjGEOM_ELLIPSOID: case mjGEOM_ELLIPSOID:
AddShape(ModelObjects::kSphere); AddShape(model_objects, ModelObjects::kSphere);
break; break;
case mjGEOM_BOX: case mjGEOM_BOX:
AddShape(ModelObjects::kBox); AddShape(model_objects, ModelObjects::kBox);
break; break;
case mjGEOM_CAPSULE: case mjGEOM_CAPSULE:
AddShape(ModelObjects::kTube); AddShape(model_objects, ModelObjects::kTube);
AddShape(ModelObjects::kDome); AddShape(model_objects, ModelObjects::kDome);
AddShape(ModelObjects::kDome); AddShape(model_objects, ModelObjects::kDome);
break; break;
case mjGEOM_CYLINDER: case mjGEOM_CYLINDER:
AddShape(ModelObjects::kTube); AddShape(model_objects, ModelObjects::kTube);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
break; break;
case mjGEOM_ARROW: case mjGEOM_ARROW:
AddShape(ModelObjects::kTube); AddShape(model_objects, ModelObjects::kTube);
AddShape(ModelObjects::kCone); AddShape(model_objects, ModelObjects::kCone);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
break; break;
case mjGEOM_ARROW1: case mjGEOM_ARROW1:
AddShape(ModelObjects::kTube); AddShape(model_objects, ModelObjects::kTube);
AddShape(ModelObjects::kCone); AddShape(model_objects, ModelObjects::kCone);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
break; break;
case mjGEOM_ARROW2: case mjGEOM_ARROW2:
AddShape(ModelObjects::kTube); AddShape(model_objects, ModelObjects::kTube);
AddShape(ModelObjects::kCone); AddShape(model_objects, ModelObjects::kCone);
AddShape(ModelObjects::kCone); AddShape(model_objects, ModelObjects::kCone);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
AddShape(ModelObjects::kDisk); AddShape(model_objects, ModelObjects::kDisk);
break; break;
case mjGEOM_LINE: case mjGEOM_LINE:
AddShape(ModelObjects::kLine); AddShape(model_objects, ModelObjects::kLine);
break; break;
case mjGEOM_LINEBOX: case mjGEOM_LINEBOX:
AddShape(ModelObjects::kLineBox); AddShape(model_objects, ModelObjects::kLineBox);
break; break;
case mjGEOM_TRIANGLE: case mjGEOM_TRIANGLE:
AddShape(ModelObjects::kTriangle); AddShape(model_objects, ModelObjects::kTriangle);
break; break;
case mjGEOM_FLEX: case mjGEOM_FLEX:
AddGeom(model_objects, scene, geom);
break;
case mjGEOM_SKIN: case mjGEOM_SKIN:
// Flex and skin geometries are dynamically updated every frame. AddGeom(model_objects, scene, geom);
break; break;
case mjGEOM_NONE: case mjGEOM_NONE:
case mjGEOM_LABEL: case mjGEOM_LABEL:
// Do nothing . // Do nothing.
break; break;
case mjGEOM_SDF: case mjGEOM_SDF:
case mjNGEOMTYPES: case mjNGEOMTYPES:
@@ -176,54 +167,38 @@ Drawable::Drawable(ObjectManager* object_mgr, ModelObjects* model_objects,
} }
} }
void Drawable::Update(const mjModel* model, const mjvScene* scene, void Drawable::AddMesh(ModelObjects* model_objs, int data_id) {
const mjvGeom& geom) { const Mesh* mesh = model_objs->GetMeshBuffer(data_id);
// Flex and skin geometries are recreated every frame from the scene data. if (mesh == nullptr) {
if (geom.type == mjGEOM_FLEX) {
if (renderables_.GetNumEntities() == 0) {
renderables_.Append(model_objs_->CreateFlexMesh(scene, geom));
} else {
renderables_.Update(0, model_objs_->CreateFlexMesh(scene, geom));
}
} else if (geom.type == mjGEOM_SKIN) {
if (renderables_.GetNumEntities() == 0) {
renderables_.Append(model_objs_->CreateSkinMesh(scene, geom));
} else {
renderables_.Update(0, model_objs_->CreateSkinMesh(scene, geom));
}
}
mjtNum head_pos[3];
mjv_cameraInModel(head_pos, nullptr, nullptr, scene);
SetTransform(geom);
UpdateMaterial(geom, scene->flags[mjRND_IDCOLOR],
scene->flags[mjRND_REFLECTION], head_pos);
renderables_.SetWireframe(scene->flags[mjRND_WIREFRAME]);
}
void Drawable::AddMesh(int data_id) {
const Mesh* buffers = model_objs_->GetMeshBuffer(data_id);
if (buffers == nullptr) {
mju_error("Unknown mesh %d", data_id); mju_error("Unknown mesh %d", data_id);
} }
renderables_.Append(buffers); renderables_.Append(mesh);
} }
void Drawable::AddHeightField(int hfield_id) { void Drawable::AddGeom(ModelObjects* model_objs, const mjvScene* scene,
const Mesh* buffers = model_objs_->GetHeightFieldBuffer(hfield_id); const mjvGeom& geom) {
if (buffers == nullptr) { if (geom.type == mjGEOM_FLEX) {
renderables_.Append(model_objs->CreateFlexMesh(scene, geom));
} else if (geom.type == mjGEOM_SKIN) {
renderables_.Append(model_objs->CreateSkinMesh(scene, geom));
}
}
void Drawable::AddHeightField(ModelObjects* model_objs, int hfield_id) {
const Mesh* mesh = model_objs->GetHeightFieldBuffer(hfield_id);
if (mesh == nullptr) {
mju_error("Unknown height field %d", hfield_id); mju_error("Unknown height field %d", hfield_id);
} }
renderables_.Append(buffers); renderables_.Append(mesh);
} }
void Drawable::AddShape(ModelObjects::ShapeType shape_type) { void Drawable::AddShape(ModelObjects* model_objs,
const Mesh* buffers = model_objs_->GetShapeBuffer(shape_type); ModelObjects::ShapeType shape_type) {
if (buffers == nullptr) { const Mesh* mesh = model_objs->GetShapeBuffer(shape_type);
if (mesh == nullptr) {
mju_error("Unknown shape %d", shape_type); mju_error("Unknown shape %d", shape_type);
} }
renderables_.Append(buffers); renderables_.Append(mesh);
} }
void Drawable::AddToScene(filament::Scene* scene) { void Drawable::AddToScene(filament::Scene* scene) {
@@ -363,14 +338,12 @@ void Drawable::SetTransform(const mjvGeom& geom) {
} }
} }
void Drawable::SetNormalMaterial(ObjectManager::MaterialType material_type) { void Drawable::UpdateMaterial(const mjModel* model, const mjvGeom& geom,
filament::Material* material = object_mgr_->GetMaterial(material_type); ModelObjects* model_objs, const float headpos[3],
material_.SetMaterial(Material::DrawMode::kNormal, material); const mjtByte render_flags[mjNRNDFLAG],
} ObjectManager::MaterialType* out_material_type) {
const bool use_segid_color = render_flags[mjRND_IDCOLOR];
void Drawable::UpdateMaterial(const mjvGeom& geom, bool use_segid_color, const bool enable_reflection = render_flags[mjRND_REFLECTION];
bool enable_reflection, const mjtNum* headpos) {
const mjModel* model = model_objs_->GetModel();
Material::Params params; Material::Params params;
params.color = ReadFloat4(geom.rgba); params.color = ReadFloat4(geom.rgba);
@@ -385,37 +358,38 @@ void Drawable::UpdateMaterial(const mjvGeom& geom, bool use_segid_color,
enable_reflection && geom.reflectance > 0 && params.color.a == 1.0f; enable_reflection && geom.reflectance > 0 && params.color.a == 1.0f;
} }
} }
renderables_.SetWireframe(render_flags[mjRND_WIREFRAME]);
Material::Textures textures; Material::Textures textures;
if (geom.matid >= 0) { if (geom.matid >= 0) {
textures.color = model_objs_->GetTexture(geom.matid, mjTEXROLE_RGB); textures.color = model_objs->GetTexture(geom.matid, mjTEXROLE_RGB);
textures.normal = model_objs_->GetTexture(geom.matid, mjTEXROLE_NORMAL); textures.normal = model_objs->GetTexture(geom.matid, mjTEXROLE_NORMAL);
textures.emissive = model_objs_->GetTexture(geom.matid, mjTEXROLE_EMISSIVE); textures.emissive = model_objs->GetTexture(geom.matid, mjTEXROLE_EMISSIVE);
textures.orm = model_objs_->GetTexture(geom.matid, mjTEXROLE_ORM); textures.orm = model_objs->GetTexture(geom.matid, mjTEXROLE_ORM);
textures.metallic = model_objs_->GetTexture(geom.matid, mjTEXROLE_METALLIC); textures.metallic = model_objs->GetTexture(geom.matid, mjTEXROLE_METALLIC);
textures.roughness = textures.roughness =
model_objs_->GetTexture(geom.matid, mjTEXROLE_ROUGHNESS); model_objs->GetTexture(geom.matid, mjTEXROLE_ROUGHNESS);
textures.occlusion = textures.occlusion =
model_objs_->GetTexture(geom.matid, mjTEXROLE_OCCLUSION); model_objs->GetTexture(geom.matid, mjTEXROLE_OCCLUSION);
material_.UpdateTextures(textures); material_.UpdateTextures(textures);
} }
if (geom.type == mjGEOM_LINE || geom.type == mjGEOM_LINEBOX) { if (geom.type == mjGEOM_LINE || geom.type == mjGEOM_LINEBOX) {
SetNormalMaterial(ObjectManager::kUnlitLine); *out_material_type = ObjectManager::kUnlitLine;
} else { } else {
bool material_assigned = false; bool material_assigned = false;
if (geom.matid >= 0) { if (geom.matid >= 0) {
material_assigned = true; material_assigned = true;
if (textures.orm) { if (textures.orm) {
SetNormalMaterial(ObjectManager::kPbrPacked); *out_material_type = ObjectManager::kPbrPacked;
} else if (textures.metallic) { } else if (textures.metallic) {
SetNormalMaterial(ObjectManager::kPbr); *out_material_type = ObjectManager::kPbr;
} else if (textures.roughness) { } else if (textures.roughness) {
SetNormalMaterial(ObjectManager::kPbr); *out_material_type = ObjectManager::kPbr;
} else if (model->mat_metallic[geom.matid] >= 0) { } else if (model->mat_metallic[geom.matid] >= 0) {
SetNormalMaterial(ObjectManager::kPbr); *out_material_type = ObjectManager::kPbr;
} else if (model->mat_roughness[geom.matid] >= 0) { } else if (model->mat_roughness[geom.matid] >= 0) {
SetNormalMaterial(ObjectManager::kPbr); *out_material_type = ObjectManager::kPbr;
} else { } else {
material_assigned = false; material_assigned = false;
} }
@@ -434,36 +408,36 @@ void Drawable::UpdateMaterial(const mjvGeom& geom, bool use_segid_color,
if (textures.color == nullptr) { if (textures.color == nullptr) {
if (params.color.a < 1.0f) { if (params.color.a < 1.0f) {
SetNormalMaterial(ObjectManager::kPhongColorFade); *out_material_type = ObjectManager::kPhongColorFade;
} else if (params.reflective) { } else if (params.reflective) {
SetNormalMaterial(ObjectManager::kPhongColorReflect); *out_material_type = ObjectManager::kPhongColorReflect;
} else { } else {
SetNormalMaterial(ObjectManager::kPhongColor); *out_material_type = ObjectManager::kPhongColor;
} }
} else if (textures.color->GetFilamentTexture()->getTarget() == } else if (textures.color->GetFilamentTexture()->getTarget() ==
filament::Texture::Sampler::SAMPLER_CUBEMAP) { filament::Texture::Sampler::SAMPLER_CUBEMAP) {
if (params.color.a < 1.0f) { if (params.color.a < 1.0f) {
SetNormalMaterial(ObjectManager::kPhongCubeFade); *out_material_type = ObjectManager::kPhongCubeFade;
} else if (params.reflective) { } else if (params.reflective) {
SetNormalMaterial(ObjectManager::kPhongCubeReflect); *out_material_type = ObjectManager::kPhongCubeReflect;
} else { } else {
SetNormalMaterial(ObjectManager::kPhongCube); *out_material_type = ObjectManager::kPhongCube;
} }
} else if (has_texcoords) { } else if (has_texcoords) {
if (params.color.a < 1.0f) { if (params.color.a < 1.0f) {
SetNormalMaterial(ObjectManager::kPhong2dUvFade); *out_material_type = ObjectManager::kPhong2dUvFade;
} else if (params.reflective) { } else if (params.reflective) {
SetNormalMaterial(ObjectManager::kPhong2dUvReflect); *out_material_type = ObjectManager::kPhong2dUvReflect;
} else { } else {
SetNormalMaterial(ObjectManager::kPhong2dUv); *out_material_type = ObjectManager::kPhong2dUv;
} }
} else { } else {
if (params.color.a < 1.0f) { if (params.color.a < 1.0f) {
SetNormalMaterial(ObjectManager::kPhong2dFade); *out_material_type = ObjectManager::kPhong2dFade;
} else if (params.reflective) { } else if (params.reflective) {
SetNormalMaterial(ObjectManager::kPhong2dReflect); *out_material_type = ObjectManager::kPhong2dReflect;
} else { } else {
SetNormalMaterial(ObjectManager::kPhong2d); *out_material_type = ObjectManager::kPhong2d;
} }
} }
} }
@@ -565,9 +539,9 @@ void Drawable::UpdateMaterial(const mjvGeom& geom, bool use_segid_color,
} }
// Apply material multipliers from the model. // Apply material multipliers from the model.
params.emissive *= model_objs_->GetEmissiveMultiplier(); params.emissive *= model_objs->GetEmissiveMultiplier();
params.specular *= model_objs_->GetSpecularMultiplier(); params.specular *= model_objs->GetSpecularMultiplier();
params.glossiness *= model_objs_->GetShininessMultiplier(); params.glossiness *= model_objs->GetShininessMultiplier();
material_.UpdateParams(params); material_.UpdateParams(params);
} }
+15 -20
View File
@@ -32,8 +32,8 @@ namespace mujoco {
// Manages the filament Entities and MaterialInstances for a single mjvGeom. // Manages the filament Entities and MaterialInstances for a single mjvGeom.
class Drawable { class Drawable {
public: public:
Drawable(ObjectManager* object_mgr, ModelObjects* model_objects, Drawable(ModelObjects* model_objects, const mjvScene* scene,
const mjvGeom& geom, const Material::Textures* fallback_textures); const mjvGeom& geom);
~Drawable() noexcept = default; ~Drawable() noexcept = default;
Drawable(const Drawable&) = delete; Drawable(const Drawable&) = delete;
@@ -46,9 +46,14 @@ class Drawable {
// Removes the Drawable from the given filament Scene. // Removes the Drawable from the given filament Scene.
void RemoveFromScene(filament::Scene* scene); void RemoveFromScene(filament::Scene* scene);
// Updates the drawable to reflect the current state (e.g. geometry, // Updates the transform of the drawable for rendering.
// transform, material, etc.) of the geom. void SetTransform(const mjvGeom& geom);
void Update(const mjModel* model, const mjvScene* scene, const mjvGeom& geom);
// Updates the material parameters of the drawable for rendering.
void UpdateMaterial(const mjModel* model, const mjvGeom& geom,
ModelObjects* model_objs, const float headpos[3],
const mjtByte render_flags[mjNRNDFLAG],
ObjectManager::MaterialType* out_material_type);
// Returns the transform of the drawable. // Returns the transform of the drawable.
const filament::math::mat4& GetTransform() const { return transform_; } const filament::math::mat4& GetTransform() const { return transform_; }
@@ -66,23 +71,13 @@ class Drawable {
Material& GetMaterial(); Material& GetMaterial();
private: private:
void AddMesh(int data_id); void AddMesh(ModelObjects* model_objs, int data_id);
void AddHeightField(int hfield_id); void AddGeom(ModelObjects* model_objs, const mjvScene* scene,
void AddShape(ModelObjects::ShapeType shape_type); const mjvGeom& geom);
void AddHeightField(ModelObjects* model_objs, int hfield_id);
// Updates the transform of the drawable for rendering. void AddShape(ModelObjects* model_objs, ModelObjects::ShapeType shape_type);
void SetTransform(const mjvGeom& geom);
// Sets the material for the drawable.
void SetNormalMaterial(ObjectManager::MaterialType material_type);
// Updates the material parameters of the drawable for rendering.
void UpdateMaterial(const mjvGeom& geom, bool use_segid_color,
bool enable_reflection, const mjtNum* headpos);
Material material_; Material material_;
ModelObjects* model_objs_ = nullptr;
ObjectManager* object_mgr_ = nullptr;
Renderables renderables_; Renderables renderables_;
filament::math::mat4 transform_; filament::math::mat4 transform_;
}; };
@@ -41,6 +41,7 @@
#include "experimental/filament/filament/drawable.h" #include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/gui_view.h" #include "experimental/filament/filament/gui_view.h"
#include "experimental/filament/filament/light.h" #include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/model_objects.h" #include "experimental/filament/filament/model_objects.h"
#include "experimental/filament/filament/model_util.h" #include "experimental/filament/filament/model_util.h"
@@ -304,6 +305,7 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
mju_n2f(headpos, hpos, 3); mju_n2f(headpos, hpos, 3);
mju_n2f(gazedir, hfwd, 3); mju_n2f(gazedir, hfwd, 3);
const mjModel* model = model_objects_->GetModel();
const mjvGLCamera gl_camera = const mjvGLCamera gl_camera =
mjv_averageCamera(scene->camera, scene->camera + 1); mjv_averageCamera(scene->camera, scene->camera + 1);
clip_from_world_ = CalculateClipFromWorld(viewport, gl_camera); clip_from_world_ = CalculateClipFromWorld(viewport, gl_camera);
@@ -322,9 +324,26 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
} }
} }
auto drawable = std::make_unique<Drawable>( auto drawable =
object_mgr_, model_objects_.get(), *geom, &fallback_textures_); std::make_unique<Drawable>(model_objects_.get(), scene, *geom);
drawable->Update(model_objects_->GetModel(), scene, *geom); drawable->SetTransform(*geom);
ObjectManager::MaterialType material_type = ObjectManager::kNumMaterials;
drawable->UpdateMaterial(model, *geom, model_objects_.get(), headpos,
scene->flags, &material_type);
Material& material = drawable->GetMaterial();
material.SetFallbackTextures(&fallback_textures_);
material.SetMaterial(
Material::DrawMode::kNormal,
object_mgr_->GetMaterial(material_type));
material.SetMaterial(
Material::DrawMode::kDepth,
object_mgr_->GetMaterial(ObjectManager::kUnlitDepth));
material.SetMaterial(
Material::DrawMode::kSegmentation,
object_mgr_->GetMaterial(ObjectManager::kUnlitSegmentation));
scene_view_->AddToScene(drawable.get()); scene_view_->AddToScene(drawable.get());
drawables_.push_back(std::move(drawable)); drawables_.push_back(std::move(drawable));
} }