Split SceneObjects out from ModelObjects.
PiperOrigin-RevId: 930960334 Change-Id: I7958a8240a90e2eb7fb87e58e5bea561459a7695
This commit is contained in:
committed by
Copybara-Service
parent
8d42473ed0
commit
a37389ccfb
@@ -29,6 +29,8 @@ target_sources(${MUJOCO_FILAMENT_EXPERIMENTAL_TARGET_NAME}
|
||||
compat/scene_bridge.h
|
||||
compat/scene_geom_util.cc
|
||||
compat/scene_geom_util.h
|
||||
compat/scene_objects.cc
|
||||
compat/scene_objects.h
|
||||
)
|
||||
if(MUJOCO_USE_FILAMENT_MJR_COMPAT)
|
||||
target_sources(${MUJOCO_FILAMENT_EXPERIMENTAL_TARGET_NAME}
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -331,77 +329,6 @@ static int GetNumVertices(const mjModel* model, int id, MeshType mesh_type) {
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetPositions(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexface + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinvert + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetNormals(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexnormal + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinnormal + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetUvs(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
if (geom.texcoord && geom.matid >= 0) {
|
||||
const int num = 6 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flextexcoord + (6 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
} else {
|
||||
if (model->skin_texcoordadr[geom.objid] >= 0) {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = model->skin_texcoordadr[geom.objid];
|
||||
const float* ptr = model->skin_texcoord + (2 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const int> GetIndices(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
} else {
|
||||
const int num = 3 * model->skin_facenum[geom.objid];
|
||||
const int* ptr = model->skin_face + 3 * model->skin_faceadr[geom.objid];
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateMeshData(mjrfMeshData* data, const mjModel* model, int id,
|
||||
MeshType mesh_type) {
|
||||
if (!IsValidIndex(model, id, mesh_type)) {
|
||||
@@ -457,38 +384,6 @@ static void UpdateMeshData(mjrfMeshData* data, const mjModel* model, int id,
|
||||
data->bounds_max[2] = builder->bounds_max.z;
|
||||
}
|
||||
|
||||
void UpdateSkinFlexMeshData(mjrfMeshData* data, 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);
|
||||
auto indices = GetIndices(model, scene, geom);
|
||||
|
||||
int num_indices = indices.size();
|
||||
if (num_indices == 0 && geom.type == mjGEOM_FLEX) {
|
||||
num_indices = 3 * scene->flexfaceused[geom.objid];
|
||||
}
|
||||
|
||||
data->nattributes = uvs.data() ? 3 : 2;
|
||||
data->attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
|
||||
data->attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[0].bytes = positions.data();
|
||||
data->attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
|
||||
data->attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[1].bytes = normals.data();
|
||||
data->attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
|
||||
data->attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
|
||||
data->attributes[2].bytes = uvs.data();
|
||||
data->nvertices = positions.size() / 3;
|
||||
data->nindices = num_indices;
|
||||
data->indices = indices.data();
|
||||
data->index_type = mjINDEX_TYPE_U32;
|
||||
data->primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
|
||||
data->compute_bounds = true;
|
||||
data->release = nullptr;
|
||||
data->user_data = nullptr;
|
||||
}
|
||||
|
||||
ModelObjects::ModelObjects(const mjModel* model, mjrfContext* ctx)
|
||||
: model_(model), ctx_(ctx) {
|
||||
|
||||
@@ -595,19 +490,6 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) {
|
||||
height_fields_.insert_or_assign(id, CreateMesh(ctx_, data));
|
||||
}
|
||||
|
||||
void ModelObjects::CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom) {
|
||||
mjrfMeshData data;
|
||||
mjrf_defaultMeshData(&data);
|
||||
UpdateSkinFlexMeshData(&data, model_, scene, geom);
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
flexes_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
|
||||
} else if (geom.type == mjGEOM_SKIN) {
|
||||
skins_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
|
||||
} else {
|
||||
mju_error("Unsupported dynamic mesh type: %d", geom.type);
|
||||
}
|
||||
}
|
||||
|
||||
const mjrfMesh* ModelObjects::GetMesh(int data_id) const {
|
||||
// As defined by mjv_updateScene:
|
||||
// original mesh: mesh_id * 2
|
||||
@@ -630,22 +512,6 @@ const mjrfMesh* ModelObjects::GetHeightField(int hfield_id) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const mjrfMesh* ModelObjects::GetFlexMesh(int geom_id) const {
|
||||
if (auto it = flexes_.find(geom_id); it != flexes_.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
mju_error("Unknown flex mesh %d", geom_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const mjrfMesh* ModelObjects::GetSkinMesh(int geom_id) const {
|
||||
if (auto it = skins_.find(geom_id); it != skins_.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
mju_error("Unknown skin mesh %d", geom_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const mjrfTexture* ModelObjects::GetTexture(int tex_id) const {
|
||||
if (auto it = textures_.find(tex_id); it != textures_.end()) {
|
||||
return it->second.get();
|
||||
|
||||
@@ -24,33 +24,46 @@
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Creates and owns various filament objects based on the mjModel.
|
||||
// Creates and owns meshes and textures read from an mjModel.
|
||||
class ModelObjects {
|
||||
public:
|
||||
ModelObjects(const mjModel* model, mjrfContext* ctx);
|
||||
|
||||
// Uploads a new mesh from the model with the given id.
|
||||
void UploadMesh(const mjModel* model, int id);
|
||||
|
||||
// Uploads a new texture from the model with the given id.
|
||||
void UploadTexture(const mjModel* model, int id);
|
||||
|
||||
// Uploads a new height field from the model with the given id.
|
||||
void UploadHeightField(const mjModel* model, int id);
|
||||
|
||||
void CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom);
|
||||
|
||||
// Returns the cached instance of a filament object created from the mjModel.
|
||||
// Returns the mjModel mesh with the given data_id. The data_id is the
|
||||
// mesh_id * 2 of the mesh in the mjModel.
|
||||
const mjrfMesh* GetMesh(int data_id) const;
|
||||
|
||||
// Returns the mjModel convex hulll mesh with the given data_id. The data_id
|
||||
// is the (mesh_id * 2) + 1 of the mesh in the mjModel.
|
||||
const mjrfMesh* GetConvexHull(int data_id) const;
|
||||
|
||||
// Returns the mjModel height field mesh with the given id.
|
||||
const mjrfMesh* GetHeightField(int hfield_id) const;
|
||||
const mjrfMesh* GetSkinMesh(int geom_id) const;
|
||||
const mjrfMesh* GetFlexMesh(int geom_id) const;
|
||||
|
||||
// Returns the mjModel texture with the given id.
|
||||
const mjrfTexture* GetTexture(int tex_id) const;
|
||||
|
||||
// Returns the skybox texture in the mjModel.
|
||||
const mjrfTexture* GetSkyboxTexture() const;
|
||||
|
||||
// Returns the mjModel from which the Model Objects are created.
|
||||
const mjModel* GetModel() const { return model_; }
|
||||
|
||||
// Returns the multipliers used for mapping legacy material properties to
|
||||
// filament material properties.
|
||||
float GetSpecularMultiplier() const { return specular_multiplier_; }
|
||||
float GetShininessMultiplier() const { return shininess_multiplier_; }
|
||||
float GetEmissiveMultiplier() const { return emissive_multiplier_; }
|
||||
|
||||
const mjModel* GetModel() const { return model_; }
|
||||
|
||||
ModelObjects(const ModelObjects&) = delete;
|
||||
ModelObjects& operator=(const ModelObjects&) = delete;
|
||||
|
||||
@@ -60,8 +73,6 @@ class ModelObjects {
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> meshes_;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> convex_hulls_;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> height_fields_;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> skins_;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> flexes_;
|
||||
std::unordered_map<int, UniquePtr<mjrfTexture>> textures_;
|
||||
float specular_multiplier_ = 0.2f;
|
||||
float shininess_multiplier_ = 0.1f;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "experimental/filament/compat/light_manager.h"
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/compat/scene_geom_util.h"
|
||||
#include "experimental/filament/compat/scene_objects.h"
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
#include "render/filament/support/filament_util.h"
|
||||
@@ -45,6 +46,7 @@ SceneBridge::SceneBridge(mjrfContext* ctx, const mjModel* model)
|
||||
mjrf_defaultSceneParams(¶ms);
|
||||
scene_ = CreateScene(ctx_, params);
|
||||
model_objects_ = std::make_unique<ModelObjects>(model, ctx_);
|
||||
scene_objects_ = std::make_unique<SceneObjects>(ctx_);
|
||||
|
||||
mjrf_configureSceneFromModel(scene_.get(), model);
|
||||
|
||||
@@ -124,11 +126,12 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
}
|
||||
|
||||
if (geom->type == mjGEOM_FLEX || geom->type == mjGEOM_SKIN) {
|
||||
model_objects_->CreateSkinFlexMesh(scene, *geom);
|
||||
scene_objects_->CreateSkinFlexMesh(scene, model_objects_->GetModel(),
|
||||
*geom);
|
||||
}
|
||||
|
||||
UniquePtr<mjrfRenderable> renderable =
|
||||
CreateGeomRenderable(*geom, ctx_, model_objects_.get(), scene->flags);
|
||||
UniquePtr<mjrfRenderable> renderable = CreateGeomRenderable(
|
||||
*geom, ctx_, model_objects_.get(), scene_objects_.get(), scene->flags);
|
||||
|
||||
mjrf_addRenderableToScene(scene_.get(), renderable.get());
|
||||
renderables_.push_back(std::move(renderable));
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/compat/light_manager.h"
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/compat/scene_objects.h"
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
|
||||
@@ -64,6 +65,7 @@ class SceneBridge {
|
||||
|
||||
mjrfContext* ctx_ = nullptr;
|
||||
std::unique_ptr<ModelObjects> model_objects_;
|
||||
std::unique_ptr<SceneObjects> scene_objects_;
|
||||
std::unique_ptr<LightManager> light_manager_;
|
||||
mjrCamera camera_;
|
||||
DrawTextAtFn draw_text_callback_;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/compat/scene_objects.h"
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
|
||||
@@ -41,7 +42,8 @@ static float GetPlaneTileSize(const mjModel* model, int matid,
|
||||
}
|
||||
|
||||
static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
||||
ModelObjects* model_objs) {
|
||||
ModelObjects* model_objs,
|
||||
SceneObjects* scene_objs) {
|
||||
const mjModel* model = model_objs->GetModel();
|
||||
const int nstack = model->vis.quality.numstacks;
|
||||
const int nslice = model->vis.quality.numslices;
|
||||
@@ -113,7 +115,7 @@ static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
||||
mjrf_setRenderableSize(renderable, geom.size);
|
||||
break;
|
||||
case mjGEOM_FLEX:
|
||||
mjrf_setRenderableMesh(renderable, model_objs->GetFlexMesh(geom.objid), 0, 0);
|
||||
mjrf_setRenderableMesh(renderable, scene_objs->GetFlexMesh(geom.objid), 0, 0);
|
||||
// Flexes are defined in global space.
|
||||
std::memset(position, 0, sizeof(position));
|
||||
std::memset(rotation, 0, sizeof(rotation));
|
||||
@@ -122,7 +124,7 @@ static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
||||
rotation[8] = 1.f;
|
||||
break;
|
||||
case mjGEOM_SKIN:
|
||||
mjrf_setRenderableMesh(renderable, model_objs->GetSkinMesh(geom.objid), 0, 0);
|
||||
mjrf_setRenderableMesh(renderable, scene_objs->GetSkinMesh(geom.objid), 0, 0);
|
||||
// Skins are defined in global space.
|
||||
std::memset(position, 0, sizeof(position));
|
||||
std::memset(rotation, 0, sizeof(rotation));
|
||||
@@ -271,11 +273,11 @@ static void UpdateGeomMaterial(mjrfRenderable* renderable, const mjvGeom& geom,
|
||||
|
||||
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
||||
const mjtByte render_flags[mjNRNDFLAG]) {
|
||||
SceneObjects* scene_objs, const mjtByte render_flags[mjNRNDFLAG]) {
|
||||
mjrfRenderableParams params;
|
||||
mjrf_defaultRenderableParams(¶ms);
|
||||
auto renderable = CreateRenderable(ctx, params);
|
||||
PrepareGeomMeshes(renderable.get(), geom, model_objs);
|
||||
PrepareGeomMeshes(renderable.get(), geom, model_objs, scene_objs);
|
||||
UpdateGeomMaterial(renderable.get(), geom, model_objs, render_flags);
|
||||
return renderable;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/compat/scene_objects.h"
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
|
||||
@@ -26,7 +27,7 @@ namespace mujoco {
|
||||
// Creates a Renderable from the given mjvGeom.
|
||||
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
||||
const mjtByte render_flags[mjNRNDFLAG]);
|
||||
SceneObjects* scene_objs, const mjtByte render_flags[mjNRNDFLAG]);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright 2026 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.
|
||||
|
||||
#include "experimental/filament/compat/scene_objects.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
using filament::math::float2;
|
||||
using filament::math::float3;
|
||||
using filament::math::float4;
|
||||
|
||||
static std::span<const float> GetPositions(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexface + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinvert + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetNormals(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexnormal + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinnormal + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetUvs(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
if (geom.texcoord && geom.matid >= 0) {
|
||||
const int num = 6 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flextexcoord + (6 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
} else {
|
||||
if (model->skin_texcoordadr[geom.objid] >= 0) {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = model->skin_texcoordadr[geom.objid];
|
||||
const float* ptr = model->skin_texcoord + (2 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const int> GetIndices(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
} else {
|
||||
const int num = 3 * model->skin_facenum[geom.objid];
|
||||
const int* ptr = model->skin_face + 3 * model->skin_faceadr[geom.objid];
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateSkinFlexMeshData(mjrfMeshData* data, 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);
|
||||
auto indices = GetIndices(model, scene, geom);
|
||||
|
||||
int num_indices = indices.size();
|
||||
if (num_indices == 0 && geom.type == mjGEOM_FLEX) {
|
||||
num_indices = 3 * scene->flexfaceused[geom.objid];
|
||||
}
|
||||
|
||||
data->nattributes = uvs.data() ? 3 : 2;
|
||||
data->attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
|
||||
data->attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[0].bytes = positions.data();
|
||||
data->attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
|
||||
data->attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[1].bytes = normals.data();
|
||||
data->attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
|
||||
data->attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
|
||||
data->attributes[2].bytes = uvs.data();
|
||||
data->nvertices = positions.size() / 3;
|
||||
data->nindices = num_indices;
|
||||
data->indices = indices.data();
|
||||
data->index_type = mjINDEX_TYPE_U32;
|
||||
data->primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
|
||||
data->compute_bounds = true;
|
||||
data->release = nullptr;
|
||||
data->user_data = nullptr;
|
||||
}
|
||||
|
||||
SceneObjects::SceneObjects(mjrfContext* ctx) : ctx_(ctx) {}
|
||||
|
||||
void SceneObjects::CreateSkinFlexMesh(const mjvScene* scene,
|
||||
const mjModel* model,
|
||||
const mjvGeom& geom) {
|
||||
mjrfMeshData data;
|
||||
mjrf_defaultMeshData(&data);
|
||||
UpdateSkinFlexMeshData(&data, model, scene, geom);
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
flexes_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
|
||||
} else if (geom.type == mjGEOM_SKIN) {
|
||||
skins_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
|
||||
} else {
|
||||
mju_error("Unsupported dynamic mesh type: %d", geom.type);
|
||||
}
|
||||
}
|
||||
|
||||
const mjrfMesh* SceneObjects::GetFlexMesh(int geom_id) const {
|
||||
if (auto it = flexes_.find(geom_id); it != flexes_.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
mju_error("Unknown flex mesh %d", geom_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const mjrfMesh* SceneObjects::GetSkinMesh(int geom_id) const {
|
||||
if (auto it = skins_.find(geom_id); it != skins_.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
mju_error("Unknown skin mesh %d", geom_id);
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace mujoco
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2026 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_COMPAT_SCENE_OBJECTS_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_SCENE_OBJECTS_H_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "render/filament/mjrfilament.h"
|
||||
#include "render/filament/mjrfilament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Creates and owns meshes read from an mjvScene.
|
||||
class SceneObjects {
|
||||
public:
|
||||
explicit SceneObjects(mjrfContext* ctx);
|
||||
|
||||
// Creates a skin or flex mesh from the given geom in the mjvScene.
|
||||
void CreateSkinFlexMesh(const mjvScene* scene, const mjModel* model,
|
||||
const mjvGeom& geom);
|
||||
|
||||
// Returns the mesh for the given geom id, as created by CreateSkinFlexMesh.
|
||||
const mjrfMesh* GetSkinMesh(int geom_id) const;
|
||||
const mjrfMesh* GetFlexMesh(int geom_id) const;
|
||||
|
||||
SceneObjects(const SceneObjects&) = delete;
|
||||
SceneObjects& operator=(const SceneObjects&) = delete;
|
||||
|
||||
private:
|
||||
mjrfContext* ctx_ = nullptr;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> skins_;
|
||||
std::unordered_map<int, UniquePtr<mjrfMesh>> flexes_;
|
||||
};
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
#endif // MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_SCENE_OBJECTS_H_
|
||||
Reference in New Issue
Block a user