Remove Drawable abstraction.

Instead, use a set of functions to create/update a Renderable
from an mjvGeom.

This completely isolates mjvScene/mjvGeom from SceneView,
making SceneView a more general purpose class.

PiperOrigin-RevId: 899475268
Change-Id: I48a3a45bc8fff3e1f514847c7a1ca8ab3a1ff16e
This commit is contained in:
Haroon Qureshi
2026-04-14 03:13:11 -07:00
committed by Copybara-Service
parent 171e6dc177
commit fd5a7004f8
8 changed files with 227 additions and 246 deletions
+2 -2
View File
@@ -27,8 +27,6 @@ target_sources(${MUJOCO_FILAMENT_TARGET_NAME}
filament/builtins.h
filament/color_grading_options.cc
filament/color_grading_options.h
filament/drawable.cc
filament/drawable.h
filament/filament_context.cc
filament/filament_context.h
filament/filament_platform_factory.cc
@@ -56,6 +54,8 @@ target_sources(${MUJOCO_FILAMENT_TARGET_NAME}
filament/renderable.h
filament/scene_bridge.cc
filament/scene_bridge.h
filament/scene_geom_util.cc
filament/scene_geom_util.h
filament/scene_view.cc
filament/scene_view.h
filament/texture.cc
@@ -1,70 +0,0 @@
// Copyright 2025 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAWABLE_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAWABLE_H_
#include <math/mat4.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjvisualize.h>
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/model_objects.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/renderable.h"
namespace mujoco {
// Manages the filament Entities and MaterialInstances for a single mjvGeom.
class Drawable {
public:
Drawable(ModelObjects* model_objects, const mjvScene* scene,
const mjvGeom& geom);
~Drawable() noexcept = default;
Drawable(const Drawable&) = delete;
Drawable& operator=(const Drawable&) = delete;
// Updates the transform of the drawable for rendering.
void SetTransform(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.
const filament::math::mat4& GetTransform() const { return transform_; }
// Returns the renderable for the drawable.
Renderable& GetRenderable() { return renderable_; }
// Returns the material for the drawable.
Material& GetMaterial() { return renderable_.GetMaterial(); }
private:
void AddMesh(ModelObjects* model_objs, int data_id);
void AddGeom(ModelObjects* model_objs, const mjvScene* scene,
const mjvGeom& geom);
void AddHeightField(ModelObjects* model_objs, int hfield_id);
void AddShape(ModelObjects* model_objs, ModelObjects::ShapeType shape_type);
Renderable renderable_;
filament::math::mat4 transform_;
};
} // namespace mujoco
#endif // MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAWABLE_H_
@@ -29,7 +29,6 @@
#include <filament/RenderTarget.h>
#include <filament/Skybox.h>
#include <filament/View.h>
#include <filament/Viewport.h>
#include <math/TMatHelpers.h>
#include <math/mat4.h>
#include <math/mathfwd.h>
@@ -38,7 +37,6 @@
#include <math/TVecHelpers.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/gui_view.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
@@ -46,6 +44,8 @@
#include "experimental/filament/filament/model_objects.h"
#include "experimental/filament/filament/model_util.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/scene_geom_util.h"
#include "experimental/filament/filament/scene_view.h"
namespace mujoco {
@@ -164,10 +164,10 @@ SceneBridge::~SceneBridge() {
}
lights_.clear();
for (auto& iter : drawables_) {
for (auto& iter : renderables_) {
scene_view_->RemoveFromScene(iter.get());
}
drawables_.clear();
renderables_.clear();
}
void SceneBridge::SetEnvironmentLight(std::string_view filename,
@@ -305,16 +305,15 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
mju_n2f(headpos, hpos, 3);
mju_n2f(gazedir, hfwd, 3);
const mjModel* model = model_objects_->GetModel();
const mjvGLCamera gl_camera =
mjv_averageCamera(scene->camera, scene->camera + 1);
clip_from_world_ = CalculateClipFromWorld(viewport, gl_camera);
// Remove all drawables from previous render and prepare new ones.
for (auto& iter : drawables_) {
for (auto& iter : renderables_) {
scene_view_->RemoveFromScene(iter.get());
}
drawables_.clear();
renderables_.clear();
for (int i = 0; i < scene->ngeom; ++i) {
const mjvGeom* geom = scene->geoms + i;
@@ -324,28 +323,12 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
}
}
auto drawable =
std::make_unique<Drawable>(model_objects_.get(), scene, *geom);
drawable->SetTransform(*geom);
std::unique_ptr<Renderable> renderable =
CreateGeomRenderable(*geom, scene, object_mgr_, model_objects_.get(),
headpos, &fallback_textures_);
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());
drawables_.push_back(std::move(drawable));
scene_view_->AddToScene(renderable.get());
renderables_.push_back(std::move(renderable));
}
bool headlight_enabled = false;
@@ -24,11 +24,11 @@
#include <math/vec3.h>
#include <mujoco/mjvisualize.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/model_objects.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/scene_view.h"
namespace mujoco {
@@ -72,7 +72,7 @@ class SceneBridge {
ObjectManager* object_mgr_ = nullptr;
std::unique_ptr<ModelObjects> model_objects_;
std::vector<std::unique_ptr<Light>> lights_;
std::vector<std::unique_ptr<Drawable>> drawables_;
std::vector<std::unique_ptr<Renderable>> renderables_;
filament::math::mat4 clip_from_world_;
int default_shadow_map_size_ = 2048;
float default_vsm_blur_width_ = 0.0f;
@@ -12,10 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/scene_geom_util.h"
#include <cmath>
#include <cstdint>
#include <memory>
#include <numbers>
#include <filament/Material.h>
@@ -81,80 +82,111 @@ static float GetPlaneTileSize(const mjModel* model, int matid,
}
static bool IsBehind(const float* headpos, const float* pos, const float* mat) {
return ((headpos[0] - pos[0]) * mat[2] +
(headpos[1] - pos[1]) * mat[5] +
(headpos[2] - pos[2]) * mat[8] < 0.0f);
return ((headpos[0] - pos[0]) * mat[2] + (headpos[1] - pos[1]) * mat[5] +
(headpos[2] - pos[2]) * mat[8] <
0.0f);
}
Drawable::Drawable(ModelObjects* model_objects, const mjvScene* scene,
const mjvGeom& geom)
: renderable_(model_objects->GetEngine()) {
if (geom.category == mjCAT_DECOR) {
renderable_.SetCastShadows(false);
renderable_.SetReceiveShadows(false);
static void AddMesh(Renderable& renderable, ModelObjects* model_objs,
int data_id) {
const Mesh* mesh = model_objs->GetMeshBuffer(data_id);
if (mesh == nullptr) {
mju_error("Unknown mesh %d", data_id);
}
renderable.Append(mesh);
}
static void AddGeom(Renderable& renderable, ModelObjects* model_objs,
const mjvScene* scene, const mjvGeom& geom) {
if (geom.type == mjGEOM_FLEX) {
renderable.Append(model_objs->CreateFlexMesh(scene, geom));
} else if (geom.type == mjGEOM_SKIN) {
renderable.Append(model_objs->CreateSkinMesh(scene, geom));
}
}
static void AddHeightField(Renderable& renderable, 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);
}
renderable.Append(mesh);
}
static void AddShape(Renderable& renderable, ModelObjects* model_objs,
ModelObjects::ShapeType shape_type) {
const Mesh* mesh = model_objs->GetShapeBuffer(shape_type);
if (mesh == nullptr) {
mju_error("Unknown shape %d", shape_type);
}
renderable.Append(mesh);
}
static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
const mjvScene* scene,
ModelObjects* model_objects) {
switch ((mjtGeom)geom.type) {
case mjGEOM_MESH:
AddMesh(model_objects, geom.dataid);
AddMesh(renderable, model_objects, geom.dataid);
break;
case mjGEOM_HFIELD:
AddHeightField(model_objects, geom.dataid);
AddHeightField(renderable, model_objects, geom.dataid);
break;
case mjGEOM_PLANE:
AddShape(model_objects, ModelObjects::kPlane);
AddShape(renderable, model_objects, ModelObjects::kPlane);
break;
case mjGEOM_SPHERE:
AddShape(model_objects, ModelObjects::kSphere);
AddShape(renderable, model_objects, ModelObjects::kSphere);
break;
case mjGEOM_ELLIPSOID:
AddShape(model_objects, ModelObjects::kSphere);
AddShape(renderable, model_objects, ModelObjects::kSphere);
break;
case mjGEOM_BOX:
AddShape(model_objects, ModelObjects::kBox);
AddShape(renderable, model_objects, ModelObjects::kBox);
break;
case mjGEOM_CAPSULE:
AddShape(model_objects, ModelObjects::kTube);
AddShape(model_objects, ModelObjects::kDome);
AddShape(model_objects, ModelObjects::kDome);
AddShape(renderable, model_objects, ModelObjects::kTube);
AddShape(renderable, model_objects, ModelObjects::kDome);
AddShape(renderable, model_objects, ModelObjects::kDome);
break;
case mjGEOM_CYLINDER:
AddShape(model_objects, ModelObjects::kTube);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kTube);
AddShape(renderable, model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kDisk);
break;
case mjGEOM_ARROW:
AddShape(model_objects, ModelObjects::kTube);
AddShape(model_objects, ModelObjects::kCone);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kTube);
AddShape(renderable, model_objects, ModelObjects::kCone);
AddShape(renderable, model_objects, ModelObjects::kDisk);
break;
case mjGEOM_ARROW1:
AddShape(model_objects, ModelObjects::kTube);
AddShape(model_objects, ModelObjects::kCone);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kTube);
AddShape(renderable, model_objects, ModelObjects::kCone);
AddShape(renderable, model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kDisk);
break;
case mjGEOM_ARROW2:
AddShape(model_objects, ModelObjects::kTube);
AddShape(model_objects, ModelObjects::kCone);
AddShape(model_objects, ModelObjects::kCone);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kTube);
AddShape(renderable, model_objects, ModelObjects::kCone);
AddShape(renderable, model_objects, ModelObjects::kCone);
AddShape(renderable, model_objects, ModelObjects::kDisk);
AddShape(renderable, model_objects, ModelObjects::kDisk);
break;
case mjGEOM_LINE:
AddShape(model_objects, ModelObjects::kLine);
AddShape(renderable, model_objects, ModelObjects::kLine);
break;
case mjGEOM_LINEBOX:
AddShape(model_objects, ModelObjects::kLineBox);
AddShape(renderable, model_objects, ModelObjects::kLineBox);
break;
case mjGEOM_TRIANGLE:
AddShape(model_objects, ModelObjects::kTriangle);
AddShape(renderable, model_objects, ModelObjects::kTriangle);
break;
case mjGEOM_FLEX:
AddGeom(model_objects, scene, geom);
AddGeom(renderable, model_objects, scene, geom);
break;
case mjGEOM_SKIN:
AddGeom(model_objects, scene, geom);
AddGeom(renderable, model_objects, scene, geom);
break;
case mjGEOM_NONE:
case mjGEOM_LABEL:
@@ -167,56 +199,22 @@ Drawable::Drawable(ModelObjects* model_objects, const mjvScene* scene,
}
}
void Drawable::AddMesh(ModelObjects* model_objs, int data_id) {
const Mesh* mesh = model_objs->GetMeshBuffer(data_id);
if (mesh == nullptr) {
mju_error("Unknown mesh %d", data_id);
}
renderable_.Append(mesh);
}
void Drawable::AddGeom(ModelObjects* model_objs, const mjvScene* scene,
const mjvGeom& geom) {
if (geom.type == mjGEOM_FLEX) {
renderable_.Append(model_objs->CreateFlexMesh(scene, geom));
} else if (geom.type == mjGEOM_SKIN) {
renderable_.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);
}
renderable_.Append(mesh);
}
void Drawable::AddShape(ModelObjects* model_objs,
ModelObjects::ShapeType shape_type) {
const Mesh* mesh = model_objs->GetShapeBuffer(shape_type);
if (mesh == nullptr) {
mju_error("Unknown shape %d", shape_type);
}
renderable_.Append(mesh);
}
void Drawable::SetTransform(const mjvGeom& geom) {
static void SetGeomTransform(Renderable& renderable, const mjvGeom& geom) {
// Flex and skin geometries are in global space.
if (geom.type == mjGEOM_FLEX || geom.type == mjGEOM_SKIN) {
return;
}
transform_ = mat4(ReadMat3(geom.mat), ReadFloat3(geom.pos));
mat4 transform = mat4(ReadMat3(geom.mat), ReadFloat3(geom.pos));
float3 size = ReadFloat3(geom.size);
filament::TransformManager& tm =
renderable_.GetEngine()->getTransformManager();
for (int j = 0; j < renderable_.GetNumEntities(); ++j) {
const utils::Entity& entity = renderable_[j];
renderable.GetEngine()->getTransformManager();
for (int j = 0; j < renderable.GetNumEntities(); ++j) {
const utils::Entity& entity = renderable[j];
// Update object transform.
mat4 entity_transform = transform_;
mat4 entity_transform = transform;
// Some built-in drawables are composed of multiple entities. For example,
// capsules are a combination of a open tube and two dome end caps.
@@ -318,27 +316,34 @@ void Drawable::SetTransform(const mjvGeom& geom) {
}
}
void Drawable::UpdateMaterial(const mjModel* model, const mjvGeom& geom,
ModelObjects* model_objs, const float headpos[3],
const mjtByte render_flags[mjNRNDFLAG],
ObjectManager::MaterialType* out_material_type) {
const bool use_segid_color = render_flags[mjRND_IDCOLOR];
const bool enable_reflection = render_flags[mjRND_REFLECTION];
static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
const mjvScene* scene, ModelObjects* model_objs,
ObjectManager* object_mgr,
const float headpos[3]) {
const mjModel* model = model_objs->GetModel();
Material& material = renderable.GetMaterial();
const bool use_segid_color = scene->flags[mjRND_IDCOLOR];
const bool enable_reflection = scene->flags[mjRND_REFLECTION];
Material::Params params;
params.color = ReadFloat4(geom.rgba);
if (geom.type == mjGEOM_PLANE) {
if (IsBehind(headpos, geom.pos, geom.mat)) {
params.color[3] *= 0.3;
renderable_.SetReceiveShadows(false);
renderable.SetReceiveShadows(false);
params.reflective = false;
} else {
renderable_.SetReceiveShadows(true);
renderable.SetReceiveShadows(true);
params.reflective =
enable_reflection && geom.reflectance > 0 && params.color.a == 1.0f;
}
}
renderable_.SetWireframe(render_flags[mjRND_WIREFRAME]);
renderable.SetWireframe(scene->flags[mjRND_WIREFRAME]);
if (geom.category == mjCAT_DECOR) {
renderable.SetCastShadows(false);
renderable.SetReceiveShadows(false);
}
Material::Textures textures;
if (geom.matid >= 0) {
@@ -351,25 +356,26 @@ void Drawable::UpdateMaterial(const mjModel* model, const mjvGeom& geom,
model_objs->GetTexture(geom.matid, mjTEXROLE_ROUGHNESS);
textures.occlusion =
model_objs->GetTexture(geom.matid, mjTEXROLE_OCCLUSION);
GetMaterial().UpdateTextures(textures);
material.UpdateTextures(textures);
}
ObjectManager::MaterialType material_type = ObjectManager::kNumMaterials;
if (geom.type == mjGEOM_LINE || geom.type == mjGEOM_LINEBOX) {
*out_material_type = ObjectManager::kUnlitLine;
material_type = ObjectManager::kUnlitLine;
} else {
bool material_assigned = false;
if (geom.matid >= 0) {
material_assigned = true;
if (textures.orm) {
*out_material_type = ObjectManager::kPbrPacked;
material_type = ObjectManager::kPbrPacked;
} else if (textures.metallic) {
*out_material_type = ObjectManager::kPbr;
material_type = ObjectManager::kPbr;
} else if (textures.roughness) {
*out_material_type = ObjectManager::kPbr;
material_type = ObjectManager::kPbr;
} else if (model->mat_metallic[geom.matid] >= 0) {
*out_material_type = ObjectManager::kPbr;
material_type = ObjectManager::kPbr;
} else if (model->mat_roughness[geom.matid] >= 0) {
*out_material_type = ObjectManager::kPbr;
material_type = ObjectManager::kPbr;
} else {
material_assigned = false;
}
@@ -388,36 +394,36 @@ void Drawable::UpdateMaterial(const mjModel* model, const mjvGeom& geom,
if (textures.color == nullptr) {
if (params.color.a < 1.0f) {
*out_material_type = ObjectManager::kPhongColorFade;
material_type = ObjectManager::kPhongColorFade;
} else if (params.reflective) {
*out_material_type = ObjectManager::kPhongColorReflect;
material_type = ObjectManager::kPhongColorReflect;
} else {
*out_material_type = ObjectManager::kPhongColor;
material_type = ObjectManager::kPhongColor;
}
} else if (textures.color->GetFilamentTexture()->getTarget() ==
filament::Texture::Sampler::SAMPLER_CUBEMAP) {
filament::Texture::Sampler::SAMPLER_CUBEMAP) {
if (params.color.a < 1.0f) {
*out_material_type = ObjectManager::kPhongCubeFade;
material_type = ObjectManager::kPhongCubeFade;
} else if (params.reflective) {
*out_material_type = ObjectManager::kPhongCubeReflect;
material_type = ObjectManager::kPhongCubeReflect;
} else {
*out_material_type = ObjectManager::kPhongCube;
material_type = ObjectManager::kPhongCube;
}
} else if (has_texcoords) {
if (params.color.a < 1.0f) {
*out_material_type = ObjectManager::kPhong2dUvFade;
material_type = ObjectManager::kPhong2dUvFade;
} else if (params.reflective) {
*out_material_type = ObjectManager::kPhong2dUvReflect;
material_type = ObjectManager::kPhong2dUvReflect;
} else {
*out_material_type = ObjectManager::kPhong2dUv;
material_type = ObjectManager::kPhong2dUv;
}
} else {
if (params.color.a < 1.0f) {
*out_material_type = ObjectManager::kPhong2dFade;
material_type = ObjectManager::kPhong2dFade;
} else if (params.reflective) {
*out_material_type = ObjectManager::kPhong2dReflect;
material_type = ObjectManager::kPhong2dReflect;
} else {
*out_material_type = ObjectManager::kPhong2d;
material_type = ObjectManager::kPhong2d;
}
}
}
@@ -522,7 +528,32 @@ void Drawable::UpdateMaterial(const mjModel* model, const mjvGeom& geom,
params.emissive *= model_objs->GetEmissiveMultiplier();
params.specular *= model_objs->GetSpecularMultiplier();
params.glossiness *= model_objs->GetShininessMultiplier();
material.UpdateParams(params);
GetMaterial().UpdateParams(params);
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));
}
std::unique_ptr<Renderable> CreateGeomRenderable(
const mjvGeom& geom, const mjvScene* scene, ObjectManager* object_mgr,
ModelObjects* model_objs, const float headpos[3],
Material::Textures* fallback_textures) {
auto renderable = std::make_unique<Renderable>(model_objs->GetEngine());
// The order of these calls is important. e.g. We need to create the filament
// renderable entities before we can set their transform.
PrepareGeomMeshes(*renderable, geom, scene, model_objs);
SetGeomTransform(*renderable, geom);
renderable->GetMaterial().SetFallbackTextures(fallback_textures);
UpdateGeomMaterial(*renderable, geom, scene, model_objs, object_mgr, headpos);
return renderable;
}
} // namespace mujoco
@@ -0,0 +1,36 @@
// Copyright 2025 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_SCENE_GEOM_UTIL_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_SCENE_GEOM_UTIL_H_
#include <memory>
#include <mujoco/mjvisualize.h>
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/model_objects.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/renderable.h"
namespace mujoco {
// Creates a Renderable from the given mjvGeom.
std::unique_ptr<Renderable> CreateGeomRenderable(
const mjvGeom& geom, const mjvScene* scene, ObjectManager* object_mgr,
ModelObjects* model_objs, const float headpos[3],
Material::Textures* fallback_textures);
} // namespace mujoco
#endif // MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_SCENE_GEOM_UTIL_H_
@@ -40,7 +40,6 @@
#include <utils/EntityManager.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h"
@@ -162,11 +161,11 @@ SceneView::~SceneView() {
for (auto& light : lights_) {
light->RemoveFromScene(scene_);
}
for (auto& drawable : drawables_) {
drawable->GetRenderable().RemoveFromScene(scene_);
for (auto& renderable : renderables_) {
renderable->RemoveFromScene(scene_);
}
lights_.clear();
drawables_.clear();
renderables_.clear();
reflect_targets_.clear();
engine_->destroyCameraComponent(reflect_camera_->getEntity());
engine_->destroy(reflect_view_);
@@ -192,22 +191,22 @@ void SceneView::RemoveFromScene(Light* light) {
}
}
void SceneView::AddToScene(Drawable* drawable) {
if (drawables_.insert(drawable).second) {
drawable->GetRenderable().AddToScene(scene_);
if (drawable->GetMaterial().GetParams().reflective) {
AddReflectiveDrawable(drawable);
void SceneView::AddToScene(Renderable* renderable) {
if (renderables_.insert(renderable).second) {
renderable->AddToScene(scene_);
if (renderable->GetMaterial().GetParams().reflective) {
AddReflectiveRenderable(renderable);
}
}
}
void SceneView::RemoveFromScene(Drawable* drawable) {
if (drawables_.erase(drawable)) {
auto it = std::find(reflectives_.begin(), reflectives_.end(), drawable);
void SceneView::RemoveFromScene(Renderable* renderable) {
if (renderables_.erase(renderable)) {
auto it = std::find(reflectives_.begin(), reflectives_.end(), renderable);
if (it != reflectives_.end()) {
reflectives_.erase(it);
}
drawable->GetRenderable().RemoveFromScene(scene_);
renderable->RemoveFromScene(scene_);
}
}
@@ -246,11 +245,9 @@ void SceneView::Render(filament::Renderer* renderer,
SetupCamera(request.camera, viewport, camera_);
for (auto& iter : drawables_) {
for (auto& iter : renderables_) {
Material& material = iter->GetMaterial();
Renderable& renderable = iter->GetRenderable();
renderable.SetMaterialInstance(
material.GetMaterialInstance(request.draw_mode));
iter->SetMaterialInstance(material.GetMaterialInstance(request.draw_mode));
}
filament::View* view = views_[static_cast<int>(request.draw_mode)];
@@ -266,13 +263,17 @@ void SceneView::Render(filament::Renderer* renderer,
// Render reflection passes.
if (request.draw_mode == DrawMode::kNormal) {
filament::TransformManager& tm = engine_->getTransformManager();
for (size_t i = 0; i < reflectives_.size(); ++i) {
Drawable* drawable = reflectives_[i];
Renderable* renderable = reflectives_[i];
SetupReflectionCamera(drawable->GetTransform(), camera_, reflect_camera_);
// We assume the 0th entity is the reflective entity.
const utils::Entity entity = (*renderable)[0];
const mat4 transform(tm.getTransform(tm.getInstance(entity)));
SetupReflectionCamera(transform, camera_, reflect_camera_);
// Hide reflective surface from its own reflection pass.
drawable->GetRenderable().SetLayerMask(0x00);
renderable->SetLayerMask(0x00);
// Render the reflection to its render target.
reflect_view_->setRenderTarget(
@@ -280,7 +281,7 @@ void SceneView::Render(filament::Renderer* renderer,
renderer->render(reflect_view_);
// Unhide the reflective surface.
drawable->GetRenderable().SetLayerMask(0x01);
renderable->SetLayerMask(0x01);
}
}
@@ -293,24 +294,24 @@ void SceneView::Render(filament::Renderer* renderer,
}
}
void SceneView::AddReflectiveDrawable(Drawable* drawable) {
void SceneView::AddReflectiveRenderable(Renderable* renderable) {
const int index = reflectives_.size();
reflectives_.push_back(drawable);
reflectives_.push_back(renderable);
// Ensure we have the same number of render targets as we do reflective
// drawables.
// renderables.
while (reflect_targets_.size() < reflectives_.size()) {
reflect_targets_.push_back(std::make_unique<RenderTarget>(
engine_, RenderTargetTextureType::kReflectionColor,
RenderTargetTextureType::kDepth));
}
// Prepare a render target for the reflective drawable.
// Prepare a render target for the reflective renderable.
auto viewport = reflect_view_->getViewport();
auto& target = reflect_targets_[index];
target->Prepare(viewport.width, viewport.height);
Material& material = drawable->GetMaterial();
Material& material = renderable->GetMaterial();
Material::Textures textures = material.GetTextures();
textures.reflection = target->GetColorTexture();
material.UpdateTextures(textures);
@@ -27,9 +27,9 @@
#include <filament/View.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/drawable.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/render_target.h"
namespace mujoco {
@@ -47,8 +47,8 @@ class SceneView {
// Adds/removes entities from the scene.
void AddToScene(Light* light);
void RemoveFromScene(Light* light);
void AddToScene(Drawable* drawable);
void RemoveFromScene(Drawable* drawable);
void AddToScene(Renderable* renderable);
void RemoveFromScene(Renderable* renderable);
void AddToScene(filament::Skybox* skybox);
void RemoveFromScene(filament::Skybox* skybox);
void AddToScene(filament::IndirectLight* indirect_light);
@@ -85,9 +85,9 @@ class SceneView {
SceneView& operator=(const SceneView&) = delete;
private:
// Marks a drawable as reflective. Reflective drawables have to be rendered
// in their own passes to create the reflective texture.
void AddReflectiveDrawable(Drawable* drawable);
// Marks a renderable as reflective. Reflective renderables have to be
// rendered in their own passes to create the reflective texture.
void AddReflectiveRenderable(Renderable* renderable);
filament::Engine* engine_ = nullptr;
filament::Scene* scene_ = nullptr;
@@ -99,7 +99,7 @@ class SceneView {
// Scene objects.
std::unordered_set<Light*> lights_;
std::unordered_set<Drawable*> drawables_;
std::unordered_set<Renderable*> renderables_;
filament::Skybox* skybox_ = nullptr;
filament::IndirectLight* indirect_light_ = nullptr;
@@ -107,8 +107,8 @@ class SceneView {
filament::View* reflect_view_ = nullptr;
filament::Camera* reflect_camera_ = nullptr;
// The list of reflective drawables and their corresponding render targets.
std::vector<Drawable*> reflectives_;
// The list of reflective renderables and their corresponding render targets.
std::vector<Renderable*> reflectives_;
std::vector<std::unique_ptr<RenderTarget>> reflect_targets_;
};
} // namespace mujoco