Allow uploading textures for use with ImGui.

PiperOrigin-RevId: 840669528
Change-Id: I7c5854d966dd024cd492953f86bca961cfaf88b8
This commit is contained in:
Haroon Qureshi
2025-12-05 04:30:40 -08:00
committed by Copybara-Service
parent e93786c161
commit f18c9996e6
6 changed files with 76 additions and 8 deletions
@@ -316,6 +316,15 @@ void FilamentContext::UploadHeightField(const mjModel* model, int id) {
object_manager_->UploadHeightField(model, id);
}
uintptr_t FilamentContext::UploadGuiImage(uintptr_t tex_id,
const uint8_t* pixels, int width,
int height, int bpp) {
if (gui_view_) {
return gui_view_->UploadImage(tex_id, pixels, width, height, bpp);
}
return 0;
}
double FilamentContext::GetFrameRate() const {
utils::FixedCapacityVector<filament::Renderer::FrameInfo> frame_info =
renderer_->getFrameInfoHistory(1);
@@ -51,6 +51,9 @@ class FilamentContext {
void UploadHeightField(const mjModel* model, int id);
uintptr_t UploadGuiImage(uintptr_t tex_id, const uint8_t* pixels, int width,
int height, int bpp);
double GetFrameRate() const;
FilamentContext(const FilamentContext&) = delete;
+49 -8
View File
@@ -83,6 +83,49 @@ void GuiView::ResetRenderable() {
buffers_.clear();
}
uintptr_t GuiView::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
int width, int height, int bpp) {
if (bpp != 4) {
mju_error("Unsupported image bpp. Got %d, wanted 4", bpp);
}
filament::Engine* engine = object_mgr_->GetEngine();
filament::Texture* texture = nullptr;
if (tex_id == 0) {
texture = filament::Texture::Builder()
.width(width)
.height(height)
.levels(1)
.format(filament::Texture::InternalFormat::RGBA8)
.sampler(filament::Texture::Sampler::SAMPLER_2D)
.build(*engine);
tex_id = reinterpret_cast<uintptr_t>(texture);
textures_[tex_id] = texture;
} else {
auto iter = textures_.find(tex_id);
if (iter == textures_.end()) {
mju_error("Texture not found: %lu", tex_id);
}
texture = iter->second;
}
// Create a copy of the image to pass it to filament as we don't know the
// lifetime of the data.
const int num_bytes = width * height * bpp;
std::byte* bytes = new std::byte[num_bytes];
std::memcpy(bytes, pixels, num_bytes);
const auto callback = [](void* buffer, size_t size, void* user) {
auto* ptr = reinterpret_cast<std::byte*>(user);
delete[] ptr;
};
filament::Texture::PixelBufferDescriptor pb(
bytes, num_bytes, filament::Texture::Format::RGBA,
filament::Texture::Type::UBYTE, callback);
texture->setImage(*engine, 0, std::move(pb));
return tex_id;
}
void GuiView::CreateTexture(ImTextureData* data) {
filament::Engine* engine = object_mgr_->GetEngine();
if (data->Format != ImTextureFormat_RGBA32) {
@@ -256,18 +299,16 @@ filament::MaterialInstance* GuiView::GetMaterialInstance(int index,
mjrRect rect,
uintptr_t texture_id) {
while (index >= instances_.size()) {
auto iter = textures_.find(texture_id);
if (iter == textures_.end()) {
mju_error("Texture not found: %lu", texture_id);
}
instances_.push_back(material_->createInstance());
}
filament::TextureSampler sampler;
filament::MaterialInstance* instance = material_->createInstance();
instance->setParameter("glyph", iter->second, sampler);
instances_.push_back(instance);
auto iter = textures_.find(texture_id);
if (iter == textures_.end()) {
mju_error("Texture not found: %lu", texture_id);
}
filament::MaterialInstance* instance = instances_[index];
instance->setParameter("glyph", iter->second, filament::TextureSampler());
instance->setScissor(rect.left, rect.bottom, rect.width, rect.height);
return instance;
}
@@ -47,6 +47,10 @@ class GuiView {
// Returns the filament::View used to render the UX scene.
filament::View* PrepareRenderView();
// 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,
int height, int bpp);
private:
void CreateTexture(ImTextureData* data);
void UpdateTexture(ImTextureData* data);
@@ -137,6 +137,13 @@ void mjr_readPixels(unsigned char* rgb, float* depth, mjrRect viewport,
g_filament_context->ReadPixels(viewport, rgb, depth);
}
uintptr_t mjr_uploadGuiImage(uintptr_t tex_id, const unsigned char* pixels,
int width, int height, int bpp,
const mjrContext* con) {
CheckFilamentContext();
return g_filament_context->UploadGuiImage(tex_id, pixels, width, height, bpp);
}
double mjr_getFrameRate(const mjrContext* con) {
CheckFilamentContext();
return g_filament_context->GetFrameRate();
@@ -81,6 +81,10 @@ MJAPI void mjr_readPixels(unsigned char* rgb, float* depth, mjrRect viewport,
double mjr_getFrameRate(const mjrContext* con);
uintptr_t mjr_uploadGuiImage(uintptr_t tex_id, const unsigned char* pixels,
int width, int height, int bpp,
const mjrContext* con);
#if defined(__cplusplus)
} // extern "C"
#endif