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_bridge.h
|
||||||
compat/scene_geom_util.cc
|
compat/scene_geom_util.cc
|
||||||
compat/scene_geom_util.h
|
compat/scene_geom_util.h
|
||||||
|
compat/scene_objects.cc
|
||||||
|
compat/scene_objects.h
|
||||||
)
|
)
|
||||||
if(MUJOCO_USE_FILAMENT_MJR_COMPAT)
|
if(MUJOCO_USE_FILAMENT_MJR_COMPAT)
|
||||||
target_sources(${MUJOCO_FILAMENT_EXPERIMENTAL_TARGET_NAME}
|
target_sources(${MUJOCO_FILAMENT_EXPERIMENTAL_TARGET_NAME}
|
||||||
|
|||||||
@@ -16,11 +16,9 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <span>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#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,
|
static void UpdateMeshData(mjrfMeshData* data, const mjModel* model, int id,
|
||||||
MeshType mesh_type) {
|
MeshType mesh_type) {
|
||||||
if (!IsValidIndex(model, id, 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;
|
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)
|
ModelObjects::ModelObjects(const mjModel* model, mjrfContext* ctx)
|
||||||
: model_(model), ctx_(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));
|
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 {
|
const mjrfMesh* ModelObjects::GetMesh(int data_id) const {
|
||||||
// As defined by mjv_updateScene:
|
// As defined by mjv_updateScene:
|
||||||
// original mesh: mesh_id * 2
|
// original mesh: mesh_id * 2
|
||||||
@@ -630,22 +512,6 @@ const mjrfMesh* ModelObjects::GetHeightField(int hfield_id) const {
|
|||||||
return nullptr;
|
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 {
|
const mjrfTexture* ModelObjects::GetTexture(int tex_id) const {
|
||||||
if (auto it = textures_.find(tex_id); it != textures_.end()) {
|
if (auto it = textures_.find(tex_id); it != textures_.end()) {
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
|
|||||||
@@ -24,33 +24,46 @@
|
|||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
|
|
||||||
// Creates and owns various filament objects based on the mjModel.
|
// Creates and owns meshes and textures read from an mjModel.
|
||||||
class ModelObjects {
|
class ModelObjects {
|
||||||
public:
|
public:
|
||||||
ModelObjects(const mjModel* model, mjrfContext* ctx);
|
ModelObjects(const mjModel* model, mjrfContext* ctx);
|
||||||
|
|
||||||
|
// Uploads a new mesh from the model with the given id.
|
||||||
void UploadMesh(const mjModel* model, int 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);
|
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 UploadHeightField(const mjModel* model, int id);
|
||||||
|
|
||||||
void CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom);
|
// Returns the mjModel mesh with the given data_id. The data_id is the
|
||||||
|
// mesh_id * 2 of the mesh in the mjModel.
|
||||||
// Returns the cached instance of a filament object created from the mjModel.
|
|
||||||
const mjrfMesh* GetMesh(int data_id) const;
|
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* 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;
|
const mjrfTexture* GetTexture(int tex_id) const;
|
||||||
|
|
||||||
|
// Returns the skybox texture in the mjModel.
|
||||||
const mjrfTexture* GetSkyboxTexture() const;
|
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 GetSpecularMultiplier() const { return specular_multiplier_; }
|
||||||
float GetShininessMultiplier() const { return shininess_multiplier_; }
|
float GetShininessMultiplier() const { return shininess_multiplier_; }
|
||||||
float GetEmissiveMultiplier() const { return emissive_multiplier_; }
|
float GetEmissiveMultiplier() const { return emissive_multiplier_; }
|
||||||
|
|
||||||
const mjModel* GetModel() const { return model_; }
|
|
||||||
|
|
||||||
ModelObjects(const ModelObjects&) = delete;
|
ModelObjects(const ModelObjects&) = delete;
|
||||||
ModelObjects& operator=(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>> meshes_;
|
||||||
std::unordered_map<int, UniquePtr<mjrfMesh>> convex_hulls_;
|
std::unordered_map<int, UniquePtr<mjrfMesh>> convex_hulls_;
|
||||||
std::unordered_map<int, UniquePtr<mjrfMesh>> height_fields_;
|
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_;
|
std::unordered_map<int, UniquePtr<mjrfTexture>> textures_;
|
||||||
float specular_multiplier_ = 0.2f;
|
float specular_multiplier_ = 0.2f;
|
||||||
float shininess_multiplier_ = 0.1f;
|
float shininess_multiplier_ = 0.1f;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "experimental/filament/compat/light_manager.h"
|
#include "experimental/filament/compat/light_manager.h"
|
||||||
#include "experimental/filament/compat/model_objects.h"
|
#include "experimental/filament/compat/model_objects.h"
|
||||||
#include "experimental/filament/compat/scene_geom_util.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.h"
|
||||||
#include "render/filament/mjrfilament_cpp.h"
|
#include "render/filament/mjrfilament_cpp.h"
|
||||||
#include "render/filament/support/filament_util.h"
|
#include "render/filament/support/filament_util.h"
|
||||||
@@ -45,6 +46,7 @@ SceneBridge::SceneBridge(mjrfContext* ctx, const mjModel* model)
|
|||||||
mjrf_defaultSceneParams(¶ms);
|
mjrf_defaultSceneParams(¶ms);
|
||||||
scene_ = CreateScene(ctx_, params);
|
scene_ = CreateScene(ctx_, params);
|
||||||
model_objects_ = std::make_unique<ModelObjects>(model, ctx_);
|
model_objects_ = std::make_unique<ModelObjects>(model, ctx_);
|
||||||
|
scene_objects_ = std::make_unique<SceneObjects>(ctx_);
|
||||||
|
|
||||||
mjrf_configureSceneFromModel(scene_.get(), model);
|
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) {
|
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 =
|
UniquePtr<mjrfRenderable> renderable = CreateGeomRenderable(
|
||||||
CreateGeomRenderable(*geom, ctx_, model_objects_.get(), scene->flags);
|
*geom, ctx_, model_objects_.get(), scene_objects_.get(), scene->flags);
|
||||||
|
|
||||||
mjrf_addRenderableToScene(scene_.get(), renderable.get());
|
mjrf_addRenderableToScene(scene_.get(), renderable.get());
|
||||||
renderables_.push_back(std::move(renderable));
|
renderables_.push_back(std::move(renderable));
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
#include "experimental/filament/compat/light_manager.h"
|
#include "experimental/filament/compat/light_manager.h"
|
||||||
#include "experimental/filament/compat/model_objects.h"
|
#include "experimental/filament/compat/model_objects.h"
|
||||||
|
#include "experimental/filament/compat/scene_objects.h"
|
||||||
#include "render/filament/mjrfilament.h"
|
#include "render/filament/mjrfilament.h"
|
||||||
#include "render/filament/mjrfilament_cpp.h"
|
#include "render/filament/mjrfilament_cpp.h"
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ class SceneBridge {
|
|||||||
|
|
||||||
mjrfContext* ctx_ = nullptr;
|
mjrfContext* ctx_ = nullptr;
|
||||||
std::unique_ptr<ModelObjects> model_objects_;
|
std::unique_ptr<ModelObjects> model_objects_;
|
||||||
|
std::unique_ptr<SceneObjects> scene_objects_;
|
||||||
std::unique_ptr<LightManager> light_manager_;
|
std::unique_ptr<LightManager> light_manager_;
|
||||||
mjrCamera camera_;
|
mjrCamera camera_;
|
||||||
DrawTextAtFn draw_text_callback_;
|
DrawTextAtFn draw_text_callback_;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <mujoco/mjvisualize.h>
|
#include <mujoco/mjvisualize.h>
|
||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
#include "experimental/filament/compat/model_objects.h"
|
#include "experimental/filament/compat/model_objects.h"
|
||||||
|
#include "experimental/filament/compat/scene_objects.h"
|
||||||
#include "render/filament/mjrfilament.h"
|
#include "render/filament/mjrfilament.h"
|
||||||
#include "render/filament/mjrfilament_cpp.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,
|
static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
||||||
ModelObjects* model_objs) {
|
ModelObjects* model_objs,
|
||||||
|
SceneObjects* scene_objs) {
|
||||||
const mjModel* model = model_objs->GetModel();
|
const mjModel* model = model_objs->GetModel();
|
||||||
const int nstack = model->vis.quality.numstacks;
|
const int nstack = model->vis.quality.numstacks;
|
||||||
const int nslice = model->vis.quality.numslices;
|
const int nslice = model->vis.quality.numslices;
|
||||||
@@ -113,7 +115,7 @@ static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
|||||||
mjrf_setRenderableSize(renderable, geom.size);
|
mjrf_setRenderableSize(renderable, geom.size);
|
||||||
break;
|
break;
|
||||||
case mjGEOM_FLEX:
|
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.
|
// Flexes are defined in global space.
|
||||||
std::memset(position, 0, sizeof(position));
|
std::memset(position, 0, sizeof(position));
|
||||||
std::memset(rotation, 0, sizeof(rotation));
|
std::memset(rotation, 0, sizeof(rotation));
|
||||||
@@ -122,7 +124,7 @@ static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom,
|
|||||||
rotation[8] = 1.f;
|
rotation[8] = 1.f;
|
||||||
break;
|
break;
|
||||||
case mjGEOM_SKIN:
|
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.
|
// Skins are defined in global space.
|
||||||
std::memset(position, 0, sizeof(position));
|
std::memset(position, 0, sizeof(position));
|
||||||
std::memset(rotation, 0, sizeof(rotation));
|
std::memset(rotation, 0, sizeof(rotation));
|
||||||
@@ -271,11 +273,11 @@ static void UpdateGeomMaterial(mjrfRenderable* renderable, const mjvGeom& geom,
|
|||||||
|
|
||||||
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
||||||
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
||||||
const mjtByte render_flags[mjNRNDFLAG]) {
|
SceneObjects* scene_objs, const mjtByte render_flags[mjNRNDFLAG]) {
|
||||||
mjrfRenderableParams params;
|
mjrfRenderableParams params;
|
||||||
mjrf_defaultRenderableParams(¶ms);
|
mjrf_defaultRenderableParams(¶ms);
|
||||||
auto renderable = CreateRenderable(ctx, params);
|
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);
|
UpdateGeomMaterial(renderable.get(), geom, model_objs, render_flags);
|
||||||
return renderable;
|
return renderable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <mujoco/mjvisualize.h>
|
#include <mujoco/mjvisualize.h>
|
||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
#include "experimental/filament/compat/model_objects.h"
|
#include "experimental/filament/compat/model_objects.h"
|
||||||
|
#include "experimental/filament/compat/scene_objects.h"
|
||||||
#include "render/filament/mjrfilament.h"
|
#include "render/filament/mjrfilament.h"
|
||||||
#include "render/filament/mjrfilament_cpp.h"
|
#include "render/filament/mjrfilament_cpp.h"
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ namespace mujoco {
|
|||||||
// Creates a Renderable from the given mjvGeom.
|
// Creates a Renderable from the given mjvGeom.
|
||||||
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
UniquePtr<mjrfRenderable> CreateGeomRenderable(
|
||||||
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
const mjvGeom& geom, mjrfContext* ctx, ModelObjects* model_objs,
|
||||||
const mjtByte render_flags[mjNRNDFLAG]);
|
SceneObjects* scene_objs, const mjtByte render_flags[mjNRNDFLAG]);
|
||||||
|
|
||||||
} // namespace mujoco
|
} // 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