Update GuiView to use Texture class.
PiperOrigin-RevId: 892866156 Change-Id: I2a2e9ef51df51472b675d69edcf2d5ba291721ea
This commit is contained in:
committed by
Copybara-Service
parent
9fa9193a62
commit
565e46da42
@@ -17,6 +17,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
#include <mujoco/mjrender.h>
|
#include <mujoco/mjrender.h>
|
||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
#include "experimental/filament/filament/buffer_util.h"
|
#include "experimental/filament/filament/buffer_util.h"
|
||||||
|
#include "experimental/filament/filament/texture_util.h"
|
||||||
#include "experimental/filament/filament/vertex_util.h"
|
#include "experimental/filament/filament/vertex_util.h"
|
||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
@@ -67,9 +69,7 @@ GuiView::~GuiView() {
|
|||||||
for (auto& instance : instances_) {
|
for (auto& instance : instances_) {
|
||||||
engine_->destroy(instance);
|
engine_->destroy(instance);
|
||||||
}
|
}
|
||||||
for (auto& texture : textures_) {
|
textures_.clear();
|
||||||
engine_->destroy(texture.second);
|
|
||||||
}
|
|
||||||
engine_->destroyCameraComponent(camera_->getEntity());
|
engine_->destroyCameraComponent(camera_->getEntity());
|
||||||
engine_->destroy(view_);
|
engine_->destroy(view_);
|
||||||
engine_->destroy(scene_);
|
engine_->destroy(scene_);
|
||||||
@@ -98,62 +98,52 @@ uintptr_t GuiView::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
|
|||||||
mju_error("Unsupported image bpp. Got %d, wanted 3 or 4", bpp);
|
mju_error("Unsupported image bpp. Got %d, wanted 3 or 4", bpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto internal_format =
|
if (pixels == nullptr) {
|
||||||
bpp == 4 ? filament::Texture::InternalFormat::RGBA8
|
// If the pixels are nullptr, we destroy the texture.
|
||||||
: filament::Texture::InternalFormat::RGB8;
|
if (tex_id != 0) {
|
||||||
const auto texture_format = bpp == 4 ? filament::Texture::Format::RGBA
|
|
||||||
: filament::Texture::Format::RGB;
|
|
||||||
|
|
||||||
filament::Texture* texture = nullptr;
|
|
||||||
if (tex_id == 0) {
|
|
||||||
texture = filament::Texture::Builder()
|
|
||||||
.width(width)
|
|
||||||
.height(height)
|
|
||||||
.levels(1)
|
|
||||||
.format(internal_format)
|
|
||||||
.sampler(filament::Texture::Sampler::SAMPLER_2D)
|
|
||||||
.build(*engine_);
|
|
||||||
tex_id = textures_.size() + 1;
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (pixels == nullptr) {
|
|
||||||
// A nullptr implies that the user wants to destroy the texture.
|
|
||||||
engine_->destroy(texture);
|
|
||||||
textures_.erase(tex_id);
|
textures_.erase(tex_id);
|
||||||
return 0;
|
|
||||||
} else if (texture->getWidth() != width || texture->getHeight() != height) {
|
|
||||||
// Recreate the texture if the dimensions have changed.
|
|
||||||
engine_->destroy(texture);
|
|
||||||
texture = filament::Texture::Builder()
|
|
||||||
.width(width)
|
|
||||||
.height(height)
|
|
||||||
.levels(1)
|
|
||||||
.format(internal_format)
|
|
||||||
.sampler(filament::Texture::Sampler::SAMPLER_2D)
|
|
||||||
.build(*engine_);
|
|
||||||
textures_[tex_id] = texture;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign a new texture ID.
|
||||||
|
if (tex_id == 0) {
|
||||||
|
tex_id = textures_.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture>& texture = textures_[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) {
|
||||||
|
TextureConfig config;
|
||||||
|
DefaultTextureConfig(&config);
|
||||||
|
config.width = width;
|
||||||
|
config.height = height;
|
||||||
|
config.target = mjTEXTURE_2D;
|
||||||
|
config.format = bpp == 4 ? mjPIXEL_FORMAT_RGBA8 : mjPIXEL_FORMAT_RGB8;
|
||||||
|
config.color_space = mjCOLORSPACE_LINEAR;
|
||||||
|
texture = std::make_unique<Texture>(engine_, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a copy of the image to pass it to filament as we don't know the
|
// Create a copy of the image to pass it to filament as we don't know the
|
||||||
// lifetime of the data.
|
// lifetime of the data.
|
||||||
const int num_bytes = width * height * bpp;
|
const size_t num_bytes = width * height * bpp;
|
||||||
std::byte* bytes = new std::byte[num_bytes];
|
std::byte* bytes = new std::byte[num_bytes];
|
||||||
std::memcpy(bytes, pixels, num_bytes);
|
const auto callback = +[](void* user) {
|
||||||
const auto callback = [](void* buffer, size_t size, void* user) {
|
delete[] reinterpret_cast<std::byte*>(user);
|
||||||
auto* ptr = reinterpret_cast<std::byte*>(user);
|
|
||||||
delete[] ptr;
|
|
||||||
};
|
};
|
||||||
filament::Texture::PixelBufferDescriptor pb(bytes, num_bytes, texture_format,
|
|
||||||
filament::Texture::Type::UBYTE,
|
TextureData texture_data;
|
||||||
callback);
|
DefaultTextureData(&texture_data);
|
||||||
texture->setImage(*engine_, 0, std::move(pb));
|
texture_data.bytes = bytes;
|
||||||
|
texture_data.nbytes = num_bytes;
|
||||||
|
texture_data.user_data = bytes;
|
||||||
|
texture_data.release_callback = callback;
|
||||||
|
|
||||||
|
std::memcpy(bytes, pixels, num_bytes);
|
||||||
|
texture->Upload(texture_data);
|
||||||
return tex_id;
|
return tex_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,40 +152,39 @@ void GuiView::CreateTexture(ImTextureData* data) {
|
|||||||
mju_error("Unsupported texture format.");
|
mju_error("Unsupported texture format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
filament::Texture* texture =
|
TextureConfig config;
|
||||||
filament::Texture::Builder()
|
DefaultTextureConfig(&config);
|
||||||
.width(data->Width)
|
config.width = data->Width;
|
||||||
.height(data->Height)
|
config.height = data->Height;
|
||||||
.levels(1)
|
config.target = mjTEXTURE_2D;
|
||||||
.format(filament::Texture::InternalFormat::RGBA8)
|
config.format = mjPIXEL_FORMAT_RGBA8;
|
||||||
.sampler(filament::Texture::Sampler::SAMPLER_2D)
|
config.color_space = mjCOLORSPACE_LINEAR;
|
||||||
.build(*engine_);
|
|
||||||
|
|
||||||
const uintptr_t tex_id = textures_.size() + 1;
|
const uintptr_t tex_id = textures_.size() + 1;
|
||||||
textures_[tex_id] = texture;
|
textures_[tex_id] = std::make_unique<Texture>(engine_, config);
|
||||||
data->SetTexID((ImTextureID)tex_id);
|
data->SetTexID((ImTextureID)tex_id);
|
||||||
UpdateTexture(data);
|
UpdateTexture(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiView::UpdateTexture(ImTextureData* data) {
|
void GuiView::UpdateTexture(ImTextureData* data) {
|
||||||
const int size = data->Width * data->Height * 4;
|
|
||||||
filament::Texture::PixelBufferDescriptor pb(data->GetPixels(), size,
|
|
||||||
filament::Texture::Format::RGBA,
|
|
||||||
filament::Texture::Type::UBYTE);
|
|
||||||
auto iter = textures_.find(data->TexID);
|
auto iter = textures_.find(data->TexID);
|
||||||
if (iter == textures_.end()) {
|
if (iter == textures_.end()) {
|
||||||
mju_error("Texture not found: %llu", data->TexID);
|
mju_error("Texture not found: %llu", data->TexID);
|
||||||
}
|
}
|
||||||
|
|
||||||
filament::Texture* texture = iter->second;
|
TextureData texture_data;
|
||||||
texture->setImage(*engine_, 0, std::move(pb));
|
DefaultTextureData(&texture_data);
|
||||||
|
texture_data.bytes = data->GetPixels();
|
||||||
|
texture_data.nbytes = data->Width * data->Height * 4;
|
||||||
|
texture_data.user_data = nullptr;
|
||||||
|
texture_data.release_callback = nullptr;
|
||||||
|
iter->second->Upload(texture_data);
|
||||||
data->SetStatus(ImTextureStatus_OK);
|
data->SetStatus(ImTextureStatus_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiView::DestroyTexture(ImTextureData* data) {
|
void GuiView::DestroyTexture(ImTextureData* data) {
|
||||||
auto iter = textures_.find(data->TexID);
|
auto iter = textures_.find(data->TexID);
|
||||||
if (iter != textures_.end()) {
|
if (iter != textures_.end()) {
|
||||||
engine_->destroy(iter->second);
|
|
||||||
textures_.erase(data->TexID);
|
textures_.erase(data->TexID);
|
||||||
data->SetTexID(ImTextureID_Invalid);
|
data->SetTexID(ImTextureID_Invalid);
|
||||||
data->SetStatus(ImTextureStatus_Destroyed);
|
data->SetStatus(ImTextureStatus_Destroyed);
|
||||||
@@ -361,7 +350,8 @@ filament::MaterialInstance* GuiView::GetMaterialInstance(int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
filament::MaterialInstance* instance = instances_[index];
|
filament::MaterialInstance* instance = instances_[index];
|
||||||
instance->setParameter("glyph", iter->second, filament::TextureSampler());
|
instance->setParameter("glyph", iter->second->GetFilamentTexture(),
|
||||||
|
filament::TextureSampler());
|
||||||
instance->setScissor(rect.left, rect.bottom, rect.width, rect.height);
|
instance->setScissor(rect.left, rect.bottom, rect.width, rect.height);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_GUI_VIEW_H_
|
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_GUI_VIEW_H_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include <filament/View.h>
|
#include <filament/View.h>
|
||||||
#include <mujoco/mjrender.h>
|
#include <mujoco/mjrender.h>
|
||||||
#include "experimental/filament/filament/buffer_util.h"
|
#include "experimental/filament/filament/buffer_util.h"
|
||||||
|
#include "experimental/filament/filament/texture_util.h"
|
||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ class GuiView {
|
|||||||
utils::Entity renderable_;
|
utils::Entity renderable_;
|
||||||
std::vector<FilamentBuffers> buffers_;
|
std::vector<FilamentBuffers> buffers_;
|
||||||
std::vector<filament::MaterialInstance*> instances_;
|
std::vector<filament::MaterialInstance*> instances_;
|
||||||
std::unordered_map<uintptr_t, filament::Texture*> textures_;
|
std::unordered_map<uintptr_t, std::unique_ptr<Texture>> textures_;
|
||||||
int num_elements_ = 0;
|
int num_elements_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user