diff --git a/src/experimental/filament/CMakeLists.txt b/src/experimental/filament/CMakeLists.txt index ebd544f2..d1105e06 100644 --- a/src/experimental/filament/CMakeLists.txt +++ b/src/experimental/filament/CMakeLists.txt @@ -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 diff --git a/src/experimental/filament/filament/drawable.h b/src/experimental/filament/filament/drawable.h deleted file mode 100644 index 29829c78..00000000 --- a/src/experimental/filament/filament/drawable.h +++ /dev/null @@ -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 -#include -#include -#include -#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_ diff --git a/src/experimental/filament/filament/scene_bridge.cc b/src/experimental/filament/filament/scene_bridge.cc index acd71d31..8ac95d60 100644 --- a/src/experimental/filament/filament/scene_bridge.cc +++ b/src/experimental/filament/filament/scene_bridge.cc @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include #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(model_objects_.get(), scene, *geom); - drawable->SetTransform(*geom); + std::unique_ptr 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; diff --git a/src/experimental/filament/filament/scene_bridge.h b/src/experimental/filament/filament/scene_bridge.h index e3d4917d..e6fdd765 100644 --- a/src/experimental/filament/filament/scene_bridge.h +++ b/src/experimental/filament/filament/scene_bridge.h @@ -24,11 +24,11 @@ #include #include #include -#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 model_objects_; std::vector> lights_; - std::vector> drawables_; + std::vector> renderables_; filament::math::mat4 clip_from_world_; int default_shadow_map_size_ = 2048; float default_vsm_blur_width_ = 0.0f; diff --git a/src/experimental/filament/filament/drawable.cc b/src/experimental/filament/filament/scene_geom_util.cc similarity index 72% rename from src/experimental/filament/filament/drawable.cc rename to src/experimental/filament/filament/scene_geom_util.cc index a2bff095..468519f0 100644 --- a/src/experimental/filament/filament/drawable.cc +++ b/src/experimental/filament/filament/scene_geom_util.cc @@ -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 #include +#include #include #include @@ -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 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(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 diff --git a/src/experimental/filament/filament/scene_geom_util.h b/src/experimental/filament/filament/scene_geom_util.h new file mode 100644 index 00000000..20311cc2 --- /dev/null +++ b/src/experimental/filament/filament/scene_geom_util.h @@ -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 + +#include +#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 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_ diff --git a/src/experimental/filament/filament/scene_view.cc b/src/experimental/filament/filament/scene_view.cc index 9ea46dcb..e8c20c30 100644 --- a/src/experimental/filament/filament/scene_view.cc +++ b/src/experimental/filament/filament/scene_view.cc @@ -40,7 +40,6 @@ #include #include #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(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( 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); diff --git a/src/experimental/filament/filament/scene_view.h b/src/experimental/filament/filament/scene_view.h index a7d7c3aa..fff29dd7 100644 --- a/src/experimental/filament/filament/scene_view.h +++ b/src/experimental/filament/filament/scene_view.h @@ -27,9 +27,9 @@ #include #include #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 lights_; - std::unordered_set drawables_; + std::unordered_set 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 reflectives_; + // The list of reflective renderables and their corresponding render targets. + std::vector reflectives_; std::vector> reflect_targets_; }; } // namespace mujoco