Update compat library to use public functions.
There are still a few places where the compat library is downcasting to the internal types due to limitations in the public APIs. PiperOrigin-RevId: 910646480 Change-Id: I1ccb6714db08a2010d9535f59338e5eba06d1d35
This commit is contained in:
committed by
Copybara-Service
parent
b9c1877ecb
commit
24ce1eff10
@@ -18,31 +18,28 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/vec3.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/renderable.h"
|
||||
#include "experimental/filament/filament/scene_view.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
using filament::math::float3;
|
||||
using filament::math::mat3f;
|
||||
|
||||
ImguiBridge::ImguiBridge(FilamentContext* ctx) : ctx_(ctx) {
|
||||
ImguiBridge::ImguiBridge(mjrfContext* ctx) : ctx_(ctx) {
|
||||
mjrSceneParams params;
|
||||
mjr_defaultSceneParams(¶ms);
|
||||
params.enable_post_processing = false;
|
||||
params.enable_reflections = false;
|
||||
params.enable_shadows = false;
|
||||
scene_view_ = std::make_unique<SceneView>(ctx_, params);
|
||||
scene_ = CreateScene(ctx_, params);
|
||||
}
|
||||
|
||||
ImguiBridge::~ImguiBridge() {
|
||||
@@ -77,12 +74,12 @@ uintptr_t ImguiBridge::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
|
||||
tex_id = next_tex_id_++;
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture>& texture = textures_[tex_id];
|
||||
mjrTexture* texture = GetTexture(tex_id);
|
||||
|
||||
// If the texture does not exist or the dimensions have changed, we create a
|
||||
// new texture.
|
||||
if (texture == nullptr || texture->GetWidth() != width ||
|
||||
texture->GetHeight() != height) {
|
||||
if (texture == nullptr || mjrf_getTextureWidth(texture) != width ||
|
||||
mjrf_getTextureHeight(texture) != height) {
|
||||
mjrTextureConfig config;
|
||||
mjr_defaultTextureConfig(&config);
|
||||
config.width = width;
|
||||
@@ -90,7 +87,9 @@ uintptr_t ImguiBridge::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
|
||||
config.target = mjTEXTURE_2D;
|
||||
config.format = bpp == 4 ? mjPIXEL_FORMAT_RGBA8 : mjPIXEL_FORMAT_RGB8;
|
||||
config.color_space = mjCOLORSPACE_LINEAR;
|
||||
texture = std::make_unique<Texture>(ctx_, config);
|
||||
UniquePtr<mjrTexture> new_texture = ::mujoco::CreateTexture(ctx_, config);
|
||||
texture = new_texture.get();
|
||||
textures_.insert_or_assign(tex_id, std::move(new_texture));
|
||||
}
|
||||
|
||||
// Create a copy of the image to pass it to filament as we don't know the
|
||||
@@ -108,7 +107,7 @@ uintptr_t ImguiBridge::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
|
||||
texture_data.release_callback = callback;
|
||||
|
||||
std::memcpy(bytes, pixels, num_bytes);
|
||||
texture->Upload(texture_data);
|
||||
mjrf_setTextureData(texture, &texture_data);
|
||||
return tex_id;
|
||||
}
|
||||
|
||||
@@ -126,7 +125,7 @@ void ImguiBridge::CreateTexture(ImTextureData* data) {
|
||||
config.color_space = mjCOLORSPACE_LINEAR;
|
||||
|
||||
const uintptr_t tex_id = next_tex_id_++;
|
||||
textures_[tex_id] = std::make_unique<Texture>(ctx_, config);
|
||||
textures_.insert_or_assign(tex_id, ::mujoco::CreateTexture(ctx_, config));
|
||||
data->SetTexID((ImTextureID)tex_id);
|
||||
UpdateTexture(data);
|
||||
}
|
||||
@@ -143,7 +142,7 @@ void ImguiBridge::UpdateTexture(ImTextureData* data) {
|
||||
texture_data.nbytes = data->Width * data->Height * 4;
|
||||
texture_data.user_data = nullptr;
|
||||
texture_data.release_callback = nullptr;
|
||||
iter->second->Upload(texture_data);
|
||||
mjrf_setTextureData(iter->second.get(), &texture_data);
|
||||
data->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
|
||||
@@ -156,6 +155,14 @@ void ImguiBridge::DestroyTexture(ImTextureData* data) {
|
||||
}
|
||||
}
|
||||
|
||||
mjrTexture* ImguiBridge::GetTexture(uintptr_t tex_id) const {
|
||||
auto iter = textures_.find(tex_id);
|
||||
if (iter == textures_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second.get();
|
||||
}
|
||||
|
||||
void ImguiBridge::Update() {
|
||||
if (!ImGui::GetCurrentContext()) {
|
||||
PrepareRenderables(0);
|
||||
@@ -233,21 +240,22 @@ void ImguiBridge::Update() {
|
||||
data.indices = cmds->IdxBuffer.Data;
|
||||
data.index_type = mjINDEX_TYPE_U16;
|
||||
data.primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
|
||||
meshes_.push_back(std::make_unique<Mesh>(ctx_, data));
|
||||
meshes_.push_back(CreateMesh(ctx_, data));
|
||||
|
||||
const Mesh* mesh = meshes_.back().get();
|
||||
const mjrMesh* mesh = meshes_.back().get();
|
||||
|
||||
int index_offset = 0;
|
||||
for (const ImDrawCmd& command : cmds->CmdBuffer) {
|
||||
const int width = size.x * scale.x;
|
||||
const int height = size.y * scale.y;
|
||||
|
||||
auto& renderable = renderables_[renderable_index];
|
||||
renderable->SetMesh(mesh, index_offset, command.ElemCount);
|
||||
UniquePtr<mjrRenderable>& renderable = renderables_[renderable_index];
|
||||
mjrf_setRenderableMesh(renderable.get(), mesh, index_offset,
|
||||
command.ElemCount);
|
||||
|
||||
mjrMaterialTextures textures;
|
||||
mjr_defaultMaterialTextures(&textures);
|
||||
textures.color = textures_[command.GetTexID()].get();
|
||||
textures.color = GetTexture(command.GetTexID());
|
||||
|
||||
mjrMaterialParams properties;
|
||||
mjr_defaultMaterialParams(&properties);
|
||||
@@ -264,9 +272,12 @@ void ImguiBridge::Update() {
|
||||
properties.scissor[2] = width;
|
||||
properties.scissor[3] = height;
|
||||
}
|
||||
renderable->UpdateMaterial(properties, textures);
|
||||
renderable->SetTransform(
|
||||
{float3{0, 0, 0}, mat3f(), float3(scale.x, scale.y, 1.0f)});
|
||||
mjrf_setRenderableMaterial(renderable.get(), &properties, &textures);
|
||||
|
||||
const float position[] = {0, 0, 0};
|
||||
const float rotation[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||
const float size[] = {scale.x, scale.y, 1.0f};
|
||||
mjrf_setRenderableTransform(renderable.get(), position, rotation, size);
|
||||
|
||||
index_offset += command.ElemCount;
|
||||
++renderable_index;
|
||||
@@ -279,15 +290,14 @@ void ImguiBridge::PrepareRenderables(int count) {
|
||||
mjrRenderableParams params;
|
||||
mjr_defaultRenderableParams(¶ms);
|
||||
params.shading_model = mjSHADING_MODEL_UX;
|
||||
auto& r =
|
||||
renderables_.emplace_back(std::make_unique<Renderable>(ctx_, params));
|
||||
r->SetCastShadows(false);
|
||||
r->SetReceiveShadows(false);
|
||||
r->SetBlendOrder(static_cast<std::uint16_t>(renderables_.size()));
|
||||
scene_view_->AddToScene(r.get());
|
||||
params.cast_shadows = false;
|
||||
params.receive_shadows = false;
|
||||
params.blend_order = static_cast<std::uint16_t>(renderables_.size() + 1);
|
||||
auto& renderable = renderables_.emplace_back(CreateRenderable(ctx_, params));
|
||||
mjrf_addRenderableToScene(scene_.get(), renderable.get());
|
||||
}
|
||||
while (renderables_.size() > count) {
|
||||
scene_view_->RemoveFromScene(renderables_.back().get());
|
||||
mjrf_removeRenderableFromScene(scene_.get(), renderables_.back().get());
|
||||
renderables_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,23 +16,19 @@
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_IMGUI_BRIDGE_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/renderable.h"
|
||||
#include "experimental/filament/filament/scene_view.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Creates and manages a SceneView using data read from ImGui.
|
||||
class ImguiBridge {
|
||||
public:
|
||||
explicit ImguiBridge(FilamentContext* ctx);
|
||||
explicit ImguiBridge(mjrfContext* ctx);
|
||||
~ImguiBridge();
|
||||
|
||||
// Prepares the Renderables using data from the current ImGui state. This
|
||||
@@ -41,7 +37,7 @@ class ImguiBridge {
|
||||
void Update();
|
||||
|
||||
// Returns the managed UX scene.
|
||||
SceneView* GetSceneView() const { return scene_view_.get(); }
|
||||
mjrScene* GetScene() const { return scene_.get(); }
|
||||
|
||||
// Uploads texture to be used with ImGui's Image and ImageButton functions.
|
||||
uintptr_t UploadImage(uintptr_t tex_id, const uint8_t* pixels, int width,
|
||||
@@ -58,12 +54,13 @@ class ImguiBridge {
|
||||
void CreateTexture(ImTextureData* data);
|
||||
void UpdateTexture(ImTextureData* data);
|
||||
void DestroyTexture(ImTextureData* data);
|
||||
mjrTexture* GetTexture(uintptr_t tex_id) const;
|
||||
|
||||
FilamentContext* ctx_ = nullptr;
|
||||
std::unique_ptr<SceneView> scene_view_;
|
||||
std::vector<std::unique_ptr<Renderable>> renderables_;
|
||||
std::vector<std::unique_ptr<Mesh>> meshes_;
|
||||
std::unordered_map<uintptr_t, std::unique_ptr<Texture>> textures_;
|
||||
mjrfContext* ctx_ = nullptr;
|
||||
UniquePtr<mjrScene> scene_{nullptr, nullptr};
|
||||
std::vector<UniquePtr<mjrRenderable>> renderables_;
|
||||
std::vector<UniquePtr<mjrMesh>> meshes_;
|
||||
std::unordered_map<uintptr_t, UniquePtr<mjrTexture>> textures_;
|
||||
uintptr_t next_tex_id_ = 1;
|
||||
};
|
||||
|
||||
|
||||
@@ -651,7 +651,7 @@ void DrawLightGui(filament::LightManager& lm,
|
||||
}
|
||||
|
||||
void DrawGui(SceneBridge* scene_bridge) {
|
||||
SceneView* scene_view = scene_bridge->GetSceneView();
|
||||
SceneView* scene_view = SceneView::downcast(scene_bridge->GetScene());
|
||||
filament::View* view = scene_view->GetDefaultRenderView();
|
||||
filament::Engine* engine = scene_view->GetEngine();
|
||||
filament::LightManager& lm = engine->getLightManager();
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
#include "experimental/filament/compat/scene_bridge.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/model_util.h"
|
||||
#include "experimental/filament/filament/render_target.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -43,10 +43,10 @@ void MjrFilamentRenderer::Init(const mjModel* model) {
|
||||
mjr_defaultRenderRequest(&render_requests_[0]);
|
||||
mjr_defaultRenderRequest(&render_requests_[1]);
|
||||
|
||||
render_requests_[0].scene = scene_bridge_->GetSceneView();
|
||||
render_requests_[0].scene = scene_bridge_->GetScene();
|
||||
render_requests_[0].draw_mode = mjDRAW_MODE_COLOR;
|
||||
|
||||
render_requests_[1].scene = imgui_bridge_->GetSceneView();
|
||||
render_requests_[1].scene = imgui_bridge_->GetScene();
|
||||
render_requests_[1].draw_mode = mjDRAW_MODE_COLOR;
|
||||
|
||||
// The UX camera is a fixed orthographic camera. We only need to change the
|
||||
@@ -135,8 +135,7 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb,
|
||||
config.height = viewport.height;
|
||||
config.color_format = mjPIXEL_FORMAT_RGB8;
|
||||
config.depth_format = mjPIXEL_FORMAT_DEPTH32F;
|
||||
auto target =
|
||||
std::make_unique<RenderTarget>(filament_context_.get(), config);
|
||||
auto target = CreateRenderTarget(filament_context_.get(), config);
|
||||
render_requests_[0].target = target.get();
|
||||
render_requests_[1].target = target.get();
|
||||
|
||||
@@ -158,11 +157,11 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb,
|
||||
if (depth) {
|
||||
mjrRenderTargetConfig config;
|
||||
mjr_defaultRenderTargetConfig(&config);
|
||||
config.width = viewport.width;
|
||||
config.height = viewport.height;
|
||||
config.color_format = mjPIXEL_FORMAT_R32F;
|
||||
config.depth_format = mjPIXEL_FORMAT_DEPTH32F;
|
||||
auto target =
|
||||
std::make_unique<RenderTarget>(filament_context_.get(), config);
|
||||
target->Prepare(viewport.width, viewport.height);
|
||||
auto target = CreateRenderTarget(filament_context_.get(), config);
|
||||
render_requests_[0].target = target.get();
|
||||
render_requests_[1].target = target.get();
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
@@ -25,18 +24,16 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <math/TVecHelpers.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/builtins.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/math_util.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/model_util.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -407,7 +404,7 @@ static std::span<const int> GetIndices(const mjModel* model,
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatemjrMeshData(mjrMeshData* data, const mjModel* model, int id,
|
||||
static void UpdateMeshData(mjrMeshData* data, const mjModel* model, int id,
|
||||
MeshType mesh_type) {
|
||||
if (!IsValidIndex(model, id, mesh_type)) {
|
||||
mju_error("Invalid index %d for type %d", id, mesh_type);
|
||||
@@ -462,7 +459,7 @@ static void UpdatemjrMeshData(mjrMeshData* data, const mjModel* model, int id,
|
||||
data->bounds_max[2] = builder->bounds_max.z;
|
||||
}
|
||||
|
||||
void UpdateSkinFlexmjrMeshData(mjrMeshData* data, const mjModel* model,
|
||||
void UpdateSkinFlexMeshData(mjrMeshData* data, const mjModel* model,
|
||||
const mjvScene* scene, const mjvGeom& geom) {
|
||||
auto positions = GetPositions(model, scene, geom);
|
||||
auto normals = GetNormals(model, scene, geom);
|
||||
@@ -494,21 +491,21 @@ void UpdateSkinFlexmjrMeshData(mjrMeshData* data, const mjModel* model,
|
||||
data->user_data = nullptr;
|
||||
}
|
||||
|
||||
ModelObjects::ModelObjects(const mjModel* model, FilamentContext* ctx)
|
||||
ModelObjects::ModelObjects(const mjModel* model, mjrfContext* ctx)
|
||||
: model_(model), ctx_(ctx) {
|
||||
const int nstack = model->vis.quality.numstacks;
|
||||
const int nslice = model->vis.quality.numslices;
|
||||
const int nquad = model->vis.quality.numquads;
|
||||
shapes_[kLine] = CreateLine(ctx_);
|
||||
shapes_[kBox] = CreateBox(ctx_, nquad);
|
||||
shapes_[kLineBox] = CreateLineBox(ctx_);
|
||||
shapes_[kCone] = CreateCone(ctx_, nstack, nslice);
|
||||
shapes_[kDisk] = CreateDisk(ctx_, nslice);
|
||||
shapes_[kDome] = CreateDome(ctx_, nstack / 2, nslice);
|
||||
shapes_[kTube] = CreateTube(ctx_, nstack, nslice);
|
||||
shapes_[kPlane] = CreatePlane(ctx_, nquad);
|
||||
shapes_[kSphere] = CreateSphere(ctx_, nstack, nslice);
|
||||
shapes_[kTriangle] = CreateTriangle(ctx_);
|
||||
shapes_.insert({kLine, CreateLine(ctx_)});
|
||||
shapes_.insert({kBox, CreateBox(ctx_, nquad)});
|
||||
shapes_.insert({kLineBox, CreateLineBox(ctx_)});
|
||||
shapes_.insert({kCone, CreateCone(ctx_, nstack, nslice)});
|
||||
shapes_.insert({kDisk, CreateDisk(ctx_, nslice)});
|
||||
shapes_.insert({kDome, CreateDome(ctx_, nstack / 2, nslice)});
|
||||
shapes_.insert({kTube, CreateTube(ctx_, nstack, nslice)});
|
||||
shapes_.insert({kPlane, CreatePlane(ctx_, nquad)});
|
||||
shapes_.insert({kSphere, CreateSphere(ctx_, nstack, nslice)});
|
||||
shapes_.insert({kTriangle, CreateTriangle(ctx_)});
|
||||
|
||||
for (int i = 0; i < model_->ntex; ++i) {
|
||||
UploadTexture(model_, i);
|
||||
@@ -545,14 +542,14 @@ void ModelObjects::UploadMesh(const mjModel* model, int id) {
|
||||
|
||||
mjrMeshData data;
|
||||
mjr_defaultMeshData(&data);
|
||||
UpdatemjrMeshData(&data, model, id, MeshType::kNormal);
|
||||
meshes_[id] = std::make_unique<Mesh>(ctx_, data);
|
||||
UpdateMeshData(&data, model, id, MeshType::kNormal);
|
||||
meshes_.insert_or_assign(id, CreateMesh(ctx_, data));
|
||||
|
||||
if (model->mesh_graphadr[id] >= 0) {
|
||||
mjrMeshData convex_hull_data;
|
||||
mjr_defaultMeshData(&convex_hull_data);
|
||||
UpdatemjrMeshData(&convex_hull_data, model, id, MeshType::kConvexHull);
|
||||
convex_hulls_[id] = std::make_unique<Mesh>(ctx_, convex_hull_data);
|
||||
UpdateMeshData(&convex_hull_data, model, id, MeshType::kConvexHull);
|
||||
convex_hulls_.insert_or_assign(id, CreateMesh(ctx_, convex_hull_data));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,9 +594,9 @@ void ModelObjects::UploadTexture(const mjModel* model, int id) {
|
||||
payload.user_data = nullptr;
|
||||
payload.release_callback = nullptr;
|
||||
|
||||
auto texture = std::make_unique<Texture>(ctx_, config);
|
||||
texture->Upload(payload);
|
||||
textures_[id] = std::move(texture);
|
||||
auto texture = CreateTexture(ctx_, config);
|
||||
mjrf_setTextureData(texture.get(), &payload);
|
||||
textures_.insert_or_assign(id, std::move(texture));
|
||||
}
|
||||
|
||||
void ModelObjects::UploadHeightField(const mjModel* model, int id) {
|
||||
@@ -614,18 +611,18 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) {
|
||||
|
||||
mjrMeshData data;
|
||||
mjr_defaultMeshData(&data);
|
||||
UpdatemjrMeshData(&data, model, id, MeshType::kHeightField);
|
||||
height_fields_[id] = std::make_unique<Mesh>(ctx_, data);
|
||||
UpdateMeshData(&data, model, id, MeshType::kHeightField);
|
||||
height_fields_.insert_or_assign(id, CreateMesh(ctx_, data));
|
||||
}
|
||||
|
||||
void ModelObjects::CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom) {
|
||||
mjrMeshData data;
|
||||
mjr_defaultMeshData(&data);
|
||||
UpdateSkinFlexmjrMeshData(&data, model_, scene, geom);
|
||||
dynamic_meshes_[geom.objid] = std::make_unique<Mesh>(ctx_, data);
|
||||
UpdateSkinFlexMeshData(&data, model_, scene, geom);
|
||||
dynamic_meshes_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
|
||||
}
|
||||
|
||||
const Mesh* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
const mjrMesh* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
// As defined by mjv_updateScene:
|
||||
// original mesh: mesh_id * 2
|
||||
// convex hull: (mesh_id * 2) + 1
|
||||
@@ -639,29 +636,27 @@ const Mesh* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
}
|
||||
}
|
||||
|
||||
const Mesh* ModelObjects::GetHeightFieldBuffer(int hfield_id) const {
|
||||
const mjrMesh* ModelObjects::GetHeightFieldBuffer(int hfield_id) const {
|
||||
auto it = height_fields_.find(hfield_id);
|
||||
return it != height_fields_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
const Mesh* ModelObjects::GetShapeBuffer(ShapeType shape) const {
|
||||
if (shape < 0 || shape >= kNumShapes) {
|
||||
mju_error("Invalid shape type: %d", shape);
|
||||
}
|
||||
return shapes_[shape].get();
|
||||
const mjrMesh* ModelObjects::GetShapeBuffer(ShapeType shape) const {
|
||||
auto it = shapes_.find(shape);
|
||||
return it != shapes_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
const Mesh* ModelObjects::GetFlexSkinGeomMesh(int geom_id) const {
|
||||
const mjrMesh* ModelObjects::GetFlexSkinGeomMesh(int geom_id) const {
|
||||
auto it = dynamic_meshes_.find(geom_id);
|
||||
return it != dynamic_meshes_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
const Texture* ModelObjects::GetTexture(int tex_id) const {
|
||||
const mjrTexture* ModelObjects::GetTexture(int tex_id) const {
|
||||
auto it = textures_.find(tex_id);
|
||||
return it != textures_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
const Texture* ModelObjects::GetTexture(int mat_id, int role) const {
|
||||
const mjrTexture* ModelObjects::GetTexture(int mat_id, int role) const {
|
||||
if (mat_id < 0 || mat_id >= model_->nmat || role < 0 || role >= mjNTEXROLE) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -669,7 +664,7 @@ const Texture* ModelObjects::GetTexture(int mat_id, int role) const {
|
||||
return GetTexture(tex_id);
|
||||
}
|
||||
|
||||
const Texture* ModelObjects::GetSkyboxTexture() const {
|
||||
const mjrTexture* ModelObjects::GetSkyboxTexture() const {
|
||||
for (auto& iter : textures_) {
|
||||
if (model_->tex_type[iter.first] == mjTEXTURE_SKYBOX) {
|
||||
return iter.second.get();
|
||||
|
||||
@@ -15,22 +15,19 @@
|
||||
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_MODEL_OBJECTS_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_MODEL_OBJECTS_H_
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Creates and owns various filament objects based on the mjModel.
|
||||
class ModelObjects {
|
||||
public:
|
||||
ModelObjects(const mjModel* model, FilamentContext* ctx);
|
||||
ModelObjects(const mjModel* model, mjrfContext* ctx);
|
||||
~ModelObjects();
|
||||
|
||||
enum ShapeType {
|
||||
@@ -56,13 +53,13 @@ class ModelObjects {
|
||||
void CreateSkinFlexMesh(const mjvScene* scene, const mjvGeom& geom);
|
||||
|
||||
// Returns the cached instance of a filament object created from the mjModel.
|
||||
const Mesh* GetShapeBuffer(ShapeType shape) const;
|
||||
const Mesh* GetMeshBuffer(int data_id) const;
|
||||
const Mesh* GetHeightFieldBuffer(int hfield_id) const;
|
||||
const Mesh* GetFlexSkinGeomMesh(int geom_id) const;
|
||||
const Texture* GetTexture(int tex_id) const;
|
||||
const Texture* GetTexture(int mat_id, int role) const;
|
||||
const Texture* GetSkyboxTexture() const;
|
||||
const mjrMesh* GetShapeBuffer(ShapeType shape) const;
|
||||
const mjrMesh* GetMeshBuffer(int data_id) const;
|
||||
const mjrMesh* GetHeightFieldBuffer(int hfield_id) const;
|
||||
const mjrMesh* GetFlexSkinGeomMesh(int geom_id) const;
|
||||
const mjrTexture* GetTexture(int tex_id) const;
|
||||
const mjrTexture* GetTexture(int mat_id, int role) const;
|
||||
const mjrTexture* GetSkyboxTexture() const;
|
||||
|
||||
float GetSpecularMultiplier() const { return specular_multiplier_; }
|
||||
float GetShininessMultiplier() const { return shininess_multiplier_; }
|
||||
@@ -75,13 +72,13 @@ class ModelObjects {
|
||||
|
||||
private:
|
||||
const mjModel* model_ = nullptr;
|
||||
FilamentContext* ctx_ = nullptr;
|
||||
std::array<std::unique_ptr<Mesh>, kNumShapes> shapes_;
|
||||
std::unordered_map<int, std::unique_ptr<Mesh>> meshes_;
|
||||
std::unordered_map<int, std::unique_ptr<Mesh>> convex_hulls_;
|
||||
std::unordered_map<int, std::unique_ptr<Mesh>> height_fields_;
|
||||
std::unordered_map<int, std::unique_ptr<Mesh>> dynamic_meshes_;
|
||||
std::unordered_map<int, std::unique_ptr<Texture>> textures_;
|
||||
mjrfContext* ctx_ = nullptr;
|
||||
std::unordered_map<ShapeType, UniquePtr<mjrMesh>> shapes_;
|
||||
std::unordered_map<int, UniquePtr<mjrMesh>> meshes_;
|
||||
std::unordered_map<int, UniquePtr<mjrMesh>> convex_hulls_;
|
||||
std::unordered_map<int, UniquePtr<mjrMesh>> height_fields_;
|
||||
std::unordered_map<int, UniquePtr<mjrMesh>> dynamic_meshes_;
|
||||
std::unordered_map<int, UniquePtr<mjrTexture>> textures_;
|
||||
float specular_multiplier_ = 0.2f;
|
||||
float shininess_multiplier_ = 0.1f;
|
||||
float emissive_multiplier_ = 0.3f;
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <filament/Options.h>
|
||||
#include <filament/View.h>
|
||||
#include <math/TMatHelpers.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/mathfwd.h>
|
||||
@@ -31,16 +29,13 @@
|
||||
#include "experimental/filament/compat/imgui_bridge.h"
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/compat/scene_geom_util.h"
|
||||
#include "experimental/filament/filament/color_grading_options.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/light.h"
|
||||
#include "experimental/filament/filament/object_manager.h"
|
||||
#include "experimental/filament/filament/math_util.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_view.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -49,14 +44,14 @@ using filament::math::float4;
|
||||
using filament::math::mat3;
|
||||
using filament::math::mat4;
|
||||
|
||||
static std::unique_ptr<Texture> CreateFallbackIndirectLightTexture(
|
||||
FilamentContext* ctx, std::string_view filename = "") {
|
||||
static UniquePtr<mjrTexture> CreateFallbackIndirectLightTexture(
|
||||
mjrfContext* ctx, std::string_view filename = "") {
|
||||
if (filename.empty()) {
|
||||
filename = ObjectManager::kDefaultEnvironmentLight;
|
||||
}
|
||||
|
||||
std::unique_ptr<ObjectManager::Asset> asset =
|
||||
ctx->GetObjectManager()->LoadAsset(filename);
|
||||
FilamentContext::downcast(ctx)->GetObjectManager()->LoadAsset(filename);
|
||||
|
||||
mjrTextureConfig config;
|
||||
mjr_defaultTextureConfig(&config);
|
||||
@@ -66,7 +61,7 @@ static std::unique_ptr<Texture> CreateFallbackIndirectLightTexture(
|
||||
config.format = mjPIXEL_FORMAT_KTX;
|
||||
config.color_space = mjCOLORSPACE_AUTO;
|
||||
|
||||
auto texture = std::make_unique<Texture>(ctx, config);
|
||||
auto texture = CreateTexture(ctx, config);
|
||||
|
||||
mjrTextureData payload;
|
||||
mjr_defaultTextureData(&payload);
|
||||
@@ -77,20 +72,20 @@ static std::unique_ptr<Texture> CreateFallbackIndirectLightTexture(
|
||||
};
|
||||
payload.user_data = asset.release();
|
||||
|
||||
texture->Upload(payload);
|
||||
mjrf_setTextureData(texture.get(), &payload);
|
||||
return texture;
|
||||
}
|
||||
|
||||
SceneBridge::SceneBridge(FilamentContext* ctx, const mjModel* model)
|
||||
SceneBridge::SceneBridge(mjrfContext* ctx, const mjModel* model)
|
||||
: ctx_(ctx) {
|
||||
mjrSceneParams params;
|
||||
mjr_defaultSceneParams(¶ms);
|
||||
params.layer_mask = mjCAT_ALL;
|
||||
params.reflection_layer_mask = mjCAT_DYNAMIC | mjCAT_STATIC;
|
||||
scene_view_ = std::make_unique<SceneView>(ctx_, params);
|
||||
scene_ = CreateScene(ctx_, params);
|
||||
model_objects_ = std::make_unique<ModelObjects>(model, ctx_);
|
||||
|
||||
scene_view_->Configure(model);
|
||||
mjrf_configureSceneFromModel(scene_.get(), model);
|
||||
|
||||
default_shadow_map_size_ = ReadElement(
|
||||
model, "filament.shadows.map_size", default_shadow_map_size_);
|
||||
@@ -111,15 +106,15 @@ SceneBridge::SceneBridge(FilamentContext* ctx, const mjModel* model)
|
||||
|
||||
SceneBridge::~SceneBridge() {
|
||||
for (auto& iter : lights_) {
|
||||
scene_view_->RemoveFromScene(iter.get());
|
||||
mjrf_removeLightFromScene(scene_.get(), iter.get());
|
||||
}
|
||||
lights_.clear();
|
||||
if (fallback_ibl_) {
|
||||
scene_view_->RemoveFromScene(fallback_ibl_.get());
|
||||
mjrf_removeLightFromScene(scene_.get(), fallback_ibl_.get());
|
||||
}
|
||||
fallback_ibl_.reset();
|
||||
for (auto& iter : renderables_) {
|
||||
scene_view_->RemoveFromScene(iter.get());
|
||||
mjrf_removeRenderableFromScene(scene_.get(), iter.get());
|
||||
}
|
||||
renderables_.clear();
|
||||
}
|
||||
@@ -127,14 +122,14 @@ SceneBridge::~SceneBridge() {
|
||||
void SceneBridge::SetEnvironmentLight(std::string_view filename,
|
||||
float intensity) {
|
||||
for (auto& light : lights_) {
|
||||
if (light->GetType() == mjLIGHT_IMAGE) {
|
||||
scene_view_->RemoveFromScene(light.get());
|
||||
if (mjrf_getLightType(light.get()) == mjLIGHT_IMAGE) {
|
||||
mjrf_removeLightFromScene(scene_.get(), light.get());
|
||||
light.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fallback_ibl_) {
|
||||
scene_view_->RemoveFromScene(fallback_ibl_.get());
|
||||
mjrf_removeLightFromScene(scene_.get(), fallback_ibl_.get());
|
||||
fallback_ibl_.reset();
|
||||
}
|
||||
|
||||
@@ -145,8 +140,8 @@ void SceneBridge::SetEnvironmentLight(std::string_view filename,
|
||||
params.type = mjLIGHT_IMAGE;
|
||||
params.texture = fallback_ibl_texture_.get();
|
||||
params.intensity = intensity;
|
||||
fallback_ibl_ = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(fallback_ibl_.get());
|
||||
fallback_ibl_ = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), fallback_ibl_.get());
|
||||
}
|
||||
|
||||
std::optional<float3> SceneBridge::ClipFromWorld(const float3& pos) const{
|
||||
@@ -171,8 +166,8 @@ void SceneBridge::PrepareLights() {
|
||||
params.type = mjLIGHT_IMAGE;
|
||||
params.texture = model_objects_->GetTexture(model->light_texid[i]);
|
||||
params.intensity = model->light_intensity[i];
|
||||
auto light_obj = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(light_obj.get());
|
||||
auto light_obj = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), light_obj.get());
|
||||
lights_.emplace_back(std::move(light_obj));
|
||||
has_image_based_light = true;
|
||||
} else {
|
||||
@@ -192,8 +187,8 @@ void SceneBridge::PrepareLights() {
|
||||
params.spot_cone_angle = model->light_cutoff[i];
|
||||
}
|
||||
|
||||
auto light_obj = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(light_obj.get());
|
||||
auto light_obj = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), light_obj.get());
|
||||
lights_.emplace_back(std::move(light_obj));
|
||||
}
|
||||
}
|
||||
@@ -212,8 +207,8 @@ void SceneBridge::PrepareLights() {
|
||||
params.cast_shadows = 0;
|
||||
params.intensity = 0.0f;
|
||||
params.spot_cone_angle = 90.0f;
|
||||
auto light_obj = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(light_obj.get());
|
||||
auto light_obj = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), light_obj.get());
|
||||
lights_.emplace_back(std::move(light_obj));
|
||||
}
|
||||
|
||||
@@ -224,8 +219,8 @@ void SceneBridge::PrepareLights() {
|
||||
mjr_defaultLightParams(¶ms);
|
||||
params.type = mjLIGHT_IMAGE;
|
||||
params.intensity = 10.0f;
|
||||
fallback_ibl_ = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(fallback_ibl_.get());
|
||||
fallback_ibl_ = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), fallback_ibl_.get());
|
||||
}
|
||||
|
||||
// There are no "physical" lights in the scene which means we're likely
|
||||
@@ -240,21 +235,22 @@ void SceneBridge::PrepareLights() {
|
||||
params.type = mjLIGHT_IMAGE;
|
||||
params.texture = fallback_ibl_texture_.get();
|
||||
params.intensity = fallback_environment_light_intensity_;
|
||||
fallback_ibl_ = std::make_unique<Light>(ctx_, params);
|
||||
scene_view_->AddToScene(fallback_ibl_.get());
|
||||
fallback_ibl_ = CreateLight(ctx_, params);
|
||||
mjrf_addLightToScene(scene_.get(), fallback_ibl_.get());
|
||||
|
||||
// Distribute the fallback scene light intensity among the lights.
|
||||
const float intensity = fallback_scene_light_intensity_ / lights_.size();
|
||||
for (auto& light : lights_) {
|
||||
if (light) {
|
||||
const bool is_headlight = (light == lights_.back());
|
||||
light->SetIntensity(is_headlight ? fallback_head_light_intensity_
|
||||
: intensity);
|
||||
mjrf_setLightIntensity(light.get(),
|
||||
is_headlight ? fallback_head_light_intensity_
|
||||
: intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scene_view_->SetSkybox(model_objects_->GetSkyboxTexture());
|
||||
mjrf_setSceneSkybox(scene_.get(), model_objects_->GetSkyboxTexture());
|
||||
}
|
||||
|
||||
mat4 CalculateClipFromWorld(const mjrRect& viewport, const mjvGLCamera& cam) {
|
||||
@@ -285,16 +281,8 @@ mat4 CalculateClipFromWorld(const mjrRect& viewport, const mjvGLCamera& cam) {
|
||||
}
|
||||
|
||||
void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
if (scene->flags[mjRND_SHADOW]) {
|
||||
scene_view_->EnableShadows();
|
||||
} else {
|
||||
scene_view_->DisableShadows();
|
||||
}
|
||||
if (scene->flags[mjRND_REFLECTION]) {
|
||||
scene_view_->EnableReflections();
|
||||
} else {
|
||||
scene_view_->DisableReflections();
|
||||
}
|
||||
mjrf_setSceneShadowsEnabled(scene_.get(), scene->flags[mjRND_SHADOW]);
|
||||
mjrf_setSceneReflectionsEnabled(scene_.get(), scene->flags[mjRND_REFLECTION]);
|
||||
|
||||
mjtNum hpos[3], hfwd[3];
|
||||
float headpos[3], gazedir[3];
|
||||
@@ -308,7 +296,7 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
|
||||
// Remove all drawables from previous render and prepare new ones.
|
||||
for (auto& iter : renderables_) {
|
||||
scene_view_->RemoveFromScene(iter.get());
|
||||
mjrf_removeRenderableFromScene(scene_.get(), iter.get());
|
||||
}
|
||||
renderables_.clear();
|
||||
for (int i = 0; i < scene->ngeom; ++i) {
|
||||
@@ -324,10 +312,10 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
model_objects_->CreateSkinFlexMesh(scene, *geom);
|
||||
}
|
||||
|
||||
std::unique_ptr<Renderable> renderable = CreateGeomRenderable(
|
||||
UniquePtr<mjrRenderable> renderable = CreateGeomRenderable(
|
||||
*geom, scene, ctx_, model_objects_.get(), headpos);
|
||||
|
||||
scene_view_->AddToScene(renderable.get());
|
||||
mjrf_addRenderableToScene(scene_.get(), renderable.get());
|
||||
renderables_.push_back(std::move(renderable));
|
||||
}
|
||||
|
||||
@@ -343,16 +331,15 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
headpos[2] -= gazedir[2] * 0.05f;
|
||||
|
||||
// The headlight is always the "back" light.
|
||||
std::unique_ptr<Light>& light = lights_.back();
|
||||
light->SetColor(ReadFloat3(scene_light.diffuse));
|
||||
light->SetTransform(ReadFloat3(headpos), ReadFloat3(gazedir));
|
||||
UniquePtr<mjrLight>& light = lights_.back();
|
||||
mjrf_setLightColor(light.get(), scene_light.diffuse);
|
||||
mjrf_setLightTransform(light.get(), headpos, gazedir);
|
||||
continue;
|
||||
} else if (scene_light.id < lights_.size() - 1) {
|
||||
std::unique_ptr<Light>& light = lights_[scene_light.id];
|
||||
UniquePtr<mjrLight>& light = lights_[scene_light.id];
|
||||
if (light) {
|
||||
light->SetColor(ReadFloat3(scene_light.diffuse));
|
||||
light->SetTransform(ReadFloat3(scene_light.pos),
|
||||
ReadFloat3(scene_light.dir));
|
||||
mjrf_setLightColor(light.get(), scene_light.diffuse);
|
||||
mjrf_setLightTransform(light.get(), scene_light.pos, scene_light.dir);
|
||||
}
|
||||
} else {
|
||||
mju_error("Unexpected light id: %d", scene_light.id);
|
||||
@@ -360,11 +347,7 @@ void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
|
||||
}
|
||||
|
||||
// Enable/disable the headlight based on whether or not it's in the scene.
|
||||
if (headlight_enabled) {
|
||||
lights_.back()->Enable();
|
||||
} else {
|
||||
lights_.back()->Disable();
|
||||
}
|
||||
mjrf_setLightEnabled(lights_.back().get(), headlight_enabled);
|
||||
}
|
||||
|
||||
void SceneBridge::UploadMesh(const mjModel* model, int id) {
|
||||
|
||||
@@ -25,18 +25,15 @@
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/light.h"
|
||||
#include "experimental/filament/filament/renderable.h"
|
||||
#include "experimental/filament/filament/scene_view.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Manages all mjModel data and updates a SceneView using an mjvScene.
|
||||
class SceneBridge {
|
||||
public:
|
||||
SceneBridge(FilamentContext* ctx, const mjModel* model);
|
||||
SceneBridge(mjrfContext* ctx, const mjModel* model);
|
||||
~SceneBridge();
|
||||
|
||||
// Updates the environment light using the KTX image at the given path.
|
||||
@@ -55,7 +52,7 @@ class SceneBridge {
|
||||
void UploadHeightField(const mjModel* model, int id);
|
||||
|
||||
// Returns the managed scene.
|
||||
SceneView* GetSceneView() const { return scene_view_.get(); }
|
||||
mjrScene* GetScene() const { return scene_.get(); }
|
||||
|
||||
SceneBridge(const SceneBridge&) = delete;
|
||||
SceneBridge& operator=(const SceneBridge&) = delete;
|
||||
@@ -68,13 +65,13 @@ class SceneBridge {
|
||||
std::optional<filament::math::float3> ClipFromWorld(
|
||||
const filament::math::float3& pos) const;
|
||||
|
||||
FilamentContext* ctx_ = nullptr;
|
||||
std::unique_ptr<SceneView> scene_view_;
|
||||
mjrfContext* ctx_ = nullptr;
|
||||
std::unique_ptr<ModelObjects> model_objects_;
|
||||
std::unique_ptr<Light> fallback_ibl_;
|
||||
std::unique_ptr<Texture> fallback_ibl_texture_;
|
||||
std::vector<std::unique_ptr<Light>> lights_;
|
||||
std::vector<std::unique_ptr<Renderable>> renderables_;
|
||||
UniquePtr<mjrScene> scene_{nullptr, nullptr};
|
||||
UniquePtr<mjrLight> fallback_ibl_{nullptr, nullptr};
|
||||
UniquePtr<mjrTexture> fallback_ibl_texture_{nullptr, nullptr};
|
||||
std::vector<UniquePtr<mjrLight>> lights_;
|
||||
std::vector<UniquePtr<mjrRenderable>> renderables_;
|
||||
filament::math::mat4 clip_from_world_;
|
||||
int default_shadow_map_size_ = 2048;
|
||||
float default_vsm_blur_width_ = 0.0f;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
#include <vector>
|
||||
@@ -27,12 +28,10 @@
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/math_util.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/renderable.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -64,39 +63,39 @@ static bool IsBehind(const float* headpos, const float* pos, const float* mat) {
|
||||
0.0f);
|
||||
}
|
||||
|
||||
static const Mesh* GetMesh(ModelObjects* model_objs, int data_id) {
|
||||
const Mesh* mesh = model_objs->GetMeshBuffer(data_id);
|
||||
static const mjrMesh* GetMesh(ModelObjects* model_objs, int data_id) {
|
||||
const mjrMesh* mesh = model_objs->GetMeshBuffer(data_id);
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown mesh %d", data_id);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static const Mesh* GetSkinFlexMesh(ModelObjects* model_objs, int objid) {
|
||||
static const mjrMesh* GetSkinFlexMesh(ModelObjects* model_objs, int objid) {
|
||||
return model_objs->GetFlexSkinGeomMesh(objid);
|
||||
}
|
||||
|
||||
static const Mesh* GetHeightField(ModelObjects* model_objs, int hfield_id) {
|
||||
const Mesh* mesh = model_objs->GetHeightFieldBuffer(hfield_id);
|
||||
static const mjrMesh* GetHeightField(ModelObjects* model_objs, int hfield_id) {
|
||||
const mjrMesh* mesh = model_objs->GetHeightFieldBuffer(hfield_id);
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown height field %d", hfield_id);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static const Mesh* GetShape(ModelObjects* model_objs,
|
||||
static const mjrMesh* GetShape(ModelObjects* model_objs,
|
||||
ModelObjects::ShapeType shape_type) {
|
||||
const Mesh* mesh = model_objs->GetShapeBuffer(shape_type);
|
||||
const mjrMesh* mesh = model_objs->GetShapeBuffer(shape_type);
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown shape %d", shape_type);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
|
||||
static void PrepareGeomMeshes(mjrRenderable* renderable, const mjvGeom& geom,
|
||||
const mjvScene* scene,
|
||||
ModelObjects* model_objects) {
|
||||
std::vector<const Mesh*> meshes;
|
||||
std::vector<const mjrMesh*> meshes;
|
||||
Renderable::GetTransformFn get_transforms;
|
||||
|
||||
Trs trs = {
|
||||
@@ -334,11 +333,18 @@ static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
|
||||
break;
|
||||
}
|
||||
|
||||
renderable.SetMeshes(meshes, get_transforms);
|
||||
renderable.SetTransform(trs);
|
||||
Renderable::downcast(renderable)->SetMeshes(meshes, get_transforms);
|
||||
|
||||
float position[3];
|
||||
std::memcpy(position, &trs.translation[0], 3 * sizeof(float));
|
||||
float rotation[9];
|
||||
std::memcpy(rotation, &trs.rotation[0], 9 * sizeof(float));
|
||||
float size[3];
|
||||
std::memcpy(size, &trs.size[0], 3 * sizeof(float));
|
||||
mjrf_setRenderableTransform(renderable, position, rotation, size);
|
||||
}
|
||||
|
||||
static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
|
||||
static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
|
||||
const mjvScene* scene, ModelObjects* model_objs,
|
||||
const float headpos[3]) {
|
||||
const mjModel* model = model_objs->GetModel();
|
||||
@@ -353,19 +359,19 @@ static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
|
||||
if (geom.type == mjGEOM_PLANE) {
|
||||
if (IsBehind(headpos, geom.pos, geom.mat)) {
|
||||
params.color[3] *= 0.3;
|
||||
renderable.SetReceiveShadows(false);
|
||||
mjrf_setRenderableReceiveShadows(renderable, false);
|
||||
params.reflective = false;
|
||||
} else {
|
||||
renderable.SetReceiveShadows(true);
|
||||
mjrf_setRenderableReceiveShadows(renderable, true);
|
||||
params.reflective = geom.reflectance > 0 && params.color[3] == 1.0f;
|
||||
}
|
||||
}
|
||||
renderable.SetLayerMask(geom.category);
|
||||
mjrf_setRenderableLayerMask(renderable, geom.category);
|
||||
if (geom.category == mjCAT_DECOR) {
|
||||
renderable.SetCastShadows(false);
|
||||
renderable.SetReceiveShadows(false);
|
||||
mjrf_setRenderableCastShadows(renderable, false);
|
||||
mjrf_setRenderableReceiveShadows(renderable, false);
|
||||
} else {
|
||||
renderable.SetWireframe(scene->flags[mjRND_WIREFRAME]);
|
||||
mjrf_setRenderableWireframe(renderable, scene->flags[mjRND_WIREFRAME]);
|
||||
}
|
||||
|
||||
mjrMaterialTextures textures;
|
||||
@@ -420,7 +426,7 @@ static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
|
||||
// the programmatic UVs.
|
||||
|
||||
if (textures.color) {
|
||||
if (Texture::downcast(textures.color)->GetTarget() == mjTEXTURE_2D) {
|
||||
if (mjrf_getTextureTarget(textures.color) == mjTEXTURE_2D) {
|
||||
// For 2D textures, `tex_repeat` specifies how many times the texture
|
||||
// image is repeated. The `tex_uniform` flag determines if the repetition
|
||||
// is applied at in object space (false) or in world space (true).
|
||||
@@ -482,11 +488,11 @@ static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
|
||||
params.specular *= model_objs->GetSpecularMultiplier();
|
||||
params.glossiness *= model_objs->GetShininessMultiplier();
|
||||
|
||||
renderable.UpdateMaterial(params, textures);
|
||||
mjrf_setRenderableMaterial(renderable, ¶ms, &textures);
|
||||
}
|
||||
|
||||
std::unique_ptr<Renderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, const mjvScene* scene, FilamentContext* ctx,
|
||||
UniquePtr<mjrRenderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, const mjvScene* scene, mjrfContext* ctx,
|
||||
ModelObjects* model_objs, const float headpos[3]) {
|
||||
mjrShadingModel shading_model = mjSHADING_MODEL_SCENE_OBJECT;
|
||||
if (geom.type == mjGEOM_LINE || geom.type == mjGEOM_LINEBOX) {
|
||||
@@ -498,9 +504,9 @@ std::unique_ptr<Renderable> CreateGeomRenderable(
|
||||
mjrRenderableParams params;
|
||||
mjr_defaultRenderableParams(¶ms);
|
||||
params.shading_model = shading_model;
|
||||
auto renderable = std::make_unique<Renderable>(ctx, params);
|
||||
PrepareGeomMeshes(*renderable, geom, scene, model_objs);
|
||||
UpdateGeomMaterial(*renderable, geom, scene, model_objs, headpos);
|
||||
auto renderable = CreateRenderable(ctx, params);
|
||||
PrepareGeomMeshes(renderable.get(), geom, scene, model_objs);
|
||||
UpdateGeomMaterial(renderable.get(), geom, scene, model_objs, headpos);
|
||||
return renderable;
|
||||
}
|
||||
} // namespace mujoco
|
||||
|
||||
@@ -15,18 +15,16 @@
|
||||
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_SCENE_GEOM_UTIL_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_COMPAT_SCENE_GEOM_UTIL_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include "experimental/filament/compat/model_objects.h"
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/renderable.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Creates a Renderable from the given mjvGeom.
|
||||
std::unique_ptr<Renderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, const mjvScene* scene, FilamentContext* ctx,
|
||||
UniquePtr<mjrRenderable> CreateGeomRenderable(
|
||||
const mjvGeom& geom, const mjvScene* scene, mjrfContext* ctx,
|
||||
ModelObjects* model_objs, const float headpos[3]);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "experimental/filament/filament/math_util.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -64,15 +65,14 @@ class BuiltinBuilder : public mjrMeshData {
|
||||
virtual ~BuiltinBuilder() = default;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static std::unique_ptr<Mesh> Create(FilamentContext* ctx,
|
||||
Args&&... args) {
|
||||
static UniquePtr<mjrMesh> Create(mjrfContext* ctx, Args&&... args) {
|
||||
auto builder = new T(std::forward<Args>(args)...);
|
||||
mjrMeshData* mesh_data = builder->PrepareMeshData();
|
||||
mesh_data->release_callback = +[](void* user_data) {
|
||||
delete static_cast<BuiltinBuilder*>(user_data);
|
||||
};
|
||||
mesh_data->user_data = builder;
|
||||
return std::make_unique<Mesh>(ctx, *mesh_data);
|
||||
return CreateMesh(ctx, *mesh_data);
|
||||
}
|
||||
|
||||
mjrMeshData* PrepareMeshData() {
|
||||
@@ -617,43 +617,43 @@ class DomeBuilder : public BuiltinBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Mesh> CreateLine(FilamentContext* ctx) {
|
||||
UniquePtr<mjrMesh> CreateLine(mjrfContext* ctx) {
|
||||
return BuiltinBuilder::Create<LineBuilder>(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreatePlane(FilamentContext* ctx, int nquad) {
|
||||
UniquePtr<mjrMesh> CreatePlane(mjrfContext* ctx, int nquad) {
|
||||
return BuiltinBuilder::Create<PlaneBuilder>(ctx, nquad);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateTriangle(FilamentContext* ctx) {
|
||||
UniquePtr<mjrMesh> CreateTriangle(mjrfContext* ctx) {
|
||||
return BuiltinBuilder::Create<TriangleBuilder>(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateBox(FilamentContext* ctx, int nquad) {
|
||||
UniquePtr<mjrMesh> CreateBox(mjrfContext* ctx, int nquad) {
|
||||
return BuiltinBuilder::Create<BoxBuilder>(ctx, nquad);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateLineBox(FilamentContext* ctx) {
|
||||
UniquePtr<mjrMesh> CreateLineBox(mjrfContext* ctx) {
|
||||
return BuiltinBuilder::Create<LineBoxBuilder>(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateSphere(FilamentContext* ctx, int nstack, int nslice) {
|
||||
UniquePtr<mjrMesh> CreateSphere(mjrfContext* ctx, int nstack, int nslice) {
|
||||
return BuiltinBuilder::Create<SphereBuilder>(ctx, nstack, nslice);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateTube(FilamentContext* ctx, int nstack, int nslice) {
|
||||
UniquePtr<mjrMesh> CreateTube(mjrfContext* ctx, int nstack, int nslice) {
|
||||
return BuiltinBuilder::Create<TubeBuilder>(ctx, nstack, nslice);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateDisk(FilamentContext* ctx, int nslice) {
|
||||
UniquePtr<mjrMesh> CreateDisk(mjrfContext* ctx, int nslice) {
|
||||
return BuiltinBuilder::Create<DiskBuilder>(ctx, nslice);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateDome(FilamentContext* ctx, int nstack, int nslice) {
|
||||
UniquePtr<mjrMesh> CreateDome(mjrfContext* ctx, int nstack, int nslice) {
|
||||
return BuiltinBuilder::Create<DomeBuilder>(ctx, nstack, nslice);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mesh> CreateCone(FilamentContext* ctx, int nstack, int nslice) {
|
||||
UniquePtr<mjrMesh> CreateCone(mjrfContext* ctx, int nstack, int nslice) {
|
||||
return BuiltinBuilder::Create<ConeBuilder>(ctx, nstack, nslice);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,24 +15,22 @@
|
||||
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_BUILTINS_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_BUILTINS_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "experimental/filament/filament/filament_context.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/render_context_filament.h"
|
||||
#include "experimental/filament/render_context_filament_cpp.h"
|
||||
|
||||
// Generates buffers for built-in shapes.
|
||||
namespace mujoco {
|
||||
|
||||
std::unique_ptr<Mesh> CreateLine(FilamentContext* ctx);
|
||||
std::unique_ptr<Mesh> CreatePlane(FilamentContext* ctx, int nquad);
|
||||
std::unique_ptr<Mesh> CreateTriangle(FilamentContext* ctx);
|
||||
std::unique_ptr<Mesh> CreateBox(FilamentContext* ctx, int nquad);
|
||||
std::unique_ptr<Mesh> CreateLineBox(FilamentContext* ctx);
|
||||
std::unique_ptr<Mesh> CreateSphere(FilamentContext* ctx, int nstack, int nslice);
|
||||
std::unique_ptr<Mesh> CreateTube(FilamentContext* ctx, int nstack, int nslice);
|
||||
std::unique_ptr<Mesh> CreateDisk(FilamentContext* ctx, int nslice);
|
||||
std::unique_ptr<Mesh> CreateDome(FilamentContext* ctx, int nstack, int nslice);
|
||||
std::unique_ptr<Mesh> CreateCone(FilamentContext* ctx, int nstack, int nslice);
|
||||
UniquePtr<mjrMesh> CreateLine(mjrfContext* ctx);
|
||||
UniquePtr<mjrMesh> CreatePlane(mjrfContext* ctx, int nquad);
|
||||
UniquePtr<mjrMesh> CreateTriangle(mjrfContext* ctx);
|
||||
UniquePtr<mjrMesh> CreateBox(mjrfContext* ctx, int nquad);
|
||||
UniquePtr<mjrMesh> CreateLineBox(mjrfContext* ctx);
|
||||
UniquePtr<mjrMesh> CreateSphere(mjrfContext* ctx, int nstack, int nslice);
|
||||
UniquePtr<mjrMesh> CreateTube(mjrfContext* ctx, int nstack, int nslice);
|
||||
UniquePtr<mjrMesh> CreateDisk(mjrfContext* ctx, int nslice);
|
||||
UniquePtr<mjrMesh> CreateDome(mjrfContext* ctx, int nstack, int nslice);
|
||||
UniquePtr<mjrMesh> CreateCone(mjrfContext* ctx, int nstack, int nslice);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ const mat4f& Renderable::GetTransform() const {
|
||||
return transform_;
|
||||
}
|
||||
|
||||
void Renderable::SetMeshes(std::span<const Mesh*> meshes,
|
||||
void Renderable::SetMeshes(std::span<const mjrMesh*> meshes,
|
||||
GetTransformFn get_transform_fn) {
|
||||
if (!parts_.empty()) {
|
||||
mju_error("Cannot set meshes for renderable with multiple parts.");
|
||||
@@ -168,7 +168,7 @@ void Renderable::SetMeshes(std::span<const Mesh*> meshes,
|
||||
get_transform_fn_ = get_transform_fn;
|
||||
for (int i = 0; i < meshes.size(); ++i) {
|
||||
Part& part = parts_.emplace_back();
|
||||
part.mesh = meshes[i];
|
||||
part.mesh = Mesh::downcast(meshes[i]);
|
||||
part.elem_offset = 0;
|
||||
part.elem_count = part.mesh->GetFilamentIndexBuffer()->getIndexCount();
|
||||
InitPartEntity(part);
|
||||
|
||||
@@ -70,7 +70,7 @@ class Renderable : public mjrRenderable {
|
||||
// relative to the transform of the renderable itself. This allows users to
|
||||
// construct compound (but rigid) objects from multiple meshes.
|
||||
using GetTransformFn = std::function<filament::math::mat4f(int, const Trs&)>;
|
||||
void SetMeshes(std::span<const Mesh*> meshes,
|
||||
void SetMeshes(std::span<const mjrMesh*> meshes,
|
||||
GetTransformFn get_transform = nullptr);
|
||||
|
||||
// Sets the layer mask for the managed filament Entities. Layer masks can be
|
||||
|
||||
Reference in New Issue
Block a user