14 #pragma warning(disable : 4068 4305)
17 #include <filament/Fence.h>
18 #include <filament/RenderableManager.h>
19 #include <filament/Scene.h>
20 #include <filament/TextureSampler.h>
21 #include <filament/TransformManager.h>
22 #include <utils/EntityManager.h>
49 using namespace filament::math;
51 using namespace utils;
54 namespace visualization {
58 std::vector<char>
bytes;
59 std::string error_str;
61 std::cout <<
"[ERROR] Could not read " <<
path <<
": " << error_str
66 return Material::Builder()
76 filament::Material* material_template) {
78 template_ = material_template;
84 for (
auto* o : pool_) {
92 void reset() { next_index_ = 0; }
95 filament::MaterialInstance*
pull() {
96 if (next_index_ >= pool_.size()) {
97 pool_.push_back(template_->createInstance());
99 return pool_[next_index_++];
103 filament::Engine* engine_ =
nullptr;
104 filament::Material* template_ =
nullptr;
105 std::vector<filament::MaterialInstance*> pool_;
106 size_t next_index_ = 0;
114 filament::Material* uiblit_material_ =
nullptr;
115 filament::Material* image_material_ =
nullptr;
124 filament::Texture* font_texture_ =
nullptr;
125 bool has_synced_ =
false;
133 ImguiFilamentBridge::ImguiFilamentBridge(
135 const Size& window_size)
137 impl_->renderer_ = renderer;
141 resource_path +
"/ui_blit.filamat",
144 resource_path +
"/img_blit.filamat",
148 impl_->uiblit_pool_ =
MaterialPool(&engine, impl_->uiblit_material_);
149 impl_->image_pool_ =
MaterialPool(&engine, impl_->image_material_);
157 scene->GetView(view_id));
159 auto native_view = impl_->view_->GetNativeView();
160 native_view->setPostProcessingEnabled(
false);
161 native_view->setShadowingEnabled(
false);
163 EntityManager& em = utils::EntityManager::get();
164 impl_->renderable_ = em.create();
165 scene->GetNativeScene()->addEntity(impl_->renderable_);
174 engine.destroy(impl_->font_texture_);
177 Texture::PixelBufferDescriptor pb(pixels,
size, Texture::Format::R,
178 Texture::Type::UBYTE);
179 impl_->font_texture_ = Texture::Builder()
180 .width((uint32_t)
width)
183 .format(Texture::InternalFormat::R8)
184 .sampler(Texture::Sampler::SAMPLER_2D)
186 impl_->font_texture_->setImage(engine, 0, std::move(pb));
188 TextureSampler sampler(TextureSampler::MinFilter::LINEAR,
189 TextureSampler::MagFilter::LINEAR);
191 impl_->font_texture_, sampler);
197 engine.destroy(impl_->renderable_);
198 impl_->uiblit_pool_.drain();
199 impl_->image_pool_.drain();
200 engine.destroy(impl_->uiblit_material_);
201 engine.destroy(impl_->image_material_);
202 engine.destroy(impl_->font_texture_);
203 for (
auto&
vb : impl_->vertex_buffers_) {
206 for (
auto&
ib : impl_->index_buffers_) {
216 left_ = (uint16_t)clip_rect.x;
217 bottom_ = (uint16_t)(fb_height - clip_rect.w);
218 width_ = (uint16_t)(clip_rect.z - clip_rect.x);
219 height_ = (uint16_t)(clip_rect.w - clip_rect.y);
255 impl_->has_synced_ =
false;
259 auto& rcm = engine.getRenderableManager();
262 ImGuiIO& io = ImGui::GetIO();
263 int fbwidth = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
264 int fbheight = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
265 if (fbwidth == 0 || fbheight == 0)
return;
266 imgui_data->ScaleClipRects(io.DisplayFramebufferScale);
269 CreateBuffers(imgui_data->CmdListsCount);
273 size_t num_prims = 0;
274 std::map<ScissorRectKey, filament::MaterialInstance*> scissor_rects;
275 for (
int idx = 0; idx < imgui_data->CmdListsCount; idx++) {
276 const ImDrawList* cmds = imgui_data->CmdLists[idx];
277 num_prims += cmds->CmdBuffer.size();
278 for (
const auto& pcmd : cmds->CmdBuffer) {
280 pcmd.TextureId)] =
nullptr;
283 auto rbuilder = RenderableManager::Builder(num_prims);
284 rbuilder.boundingBox({{0, 0, 0}, {10000, 10000, 10000}}).culling(
false);
287 impl_->uiblit_pool_.reset();
288 impl_->image_pool_.reset();
289 TextureSampler sampler(TextureSampler::MinFilter::LINEAR,
290 TextureSampler::MagFilter::LINEAR);
291 for (
auto& pair : scissor_rects) {
292 if (pair.first.id_ == 0) {
293 pair.second = impl_->uiblit_pool_.pull();
297 pair.second = impl_->image_pool_.pull();
298 auto tex_id_long =
reinterpret_cast<uintptr_t
>(pair.first.id_);
299 auto tex_id = std::uint16_t(tex_id_long);
304 auto tex_sh_ptr = tex.lock();
308 pair.second->setScissor(pair.first.left_, pair.first.bottom_,
309 pair.first.width_, pair.first.height_);
313 rcm.destroy(impl_->renderable_);
314 int buffer_index = 0;
316 for (
int cmd_idx = 0; cmd_idx < imgui_data->CmdListsCount; cmd_idx++) {
317 const ImDrawList* cmds = imgui_data->CmdLists[cmd_idx];
318 size_t indexOffset = 0;
320 buffer_index, cmds->VtxBuffer.Size *
sizeof(ImDrawVert),
321 cmds->VtxBuffer.Data, cmds->IdxBuffer.Size *
sizeof(ImDrawIdx),
322 cmds->IdxBuffer.Data);
323 for (
const auto& pcmd : cmds->CmdBuffer) {
324 if (pcmd.UserCallback) {
325 pcmd.UserCallback(cmds, &pcmd);
329 auto miter = scissor_rects.find(skey);
330 if (miter != scissor_rects.end()) {
333 RenderableManager::PrimitiveType::TRIANGLES,
334 impl_->vertex_buffers_[buffer_index],
335 impl_->index_buffers_[buffer_index],
336 indexOffset, pcmd.ElemCount)
337 .blendOrder(prim_index, prim_index)
338 .material(prim_index, miter->second);
344 indexOffset += pcmd.ElemCount;
348 if (imgui_data->CmdListsCount > 0) {
349 rbuilder.build(engine, impl_->renderable_);
355 impl_->view_->SetViewport(0, 0,
size.width,
size.height);
357 auto camera = impl_->view_->GetCamera();
359 0.0,
size.width,
size.height, 0.0, 0.0, 1.0);
362 void ImguiFilamentBridge::CreateVertexBuffer(
size_t buffer_index,
368 engine.destroy(impl_->vertex_buffers_[buffer_index]);
369 impl_->vertex_buffers_[buffer_index] =
370 VertexBuffer::Builder()
371 .vertexCount(std::uint32_t(capacity))
373 .attribute(VertexAttribute::POSITION, 0,
374 VertexBuffer::AttributeType::FLOAT2, 0,
376 .attribute(VertexAttribute::UV0, 0,
377 VertexBuffer::AttributeType::FLOAT2,
378 sizeof(filament::math::float2),
380 .attribute(VertexAttribute::COLOR, 0,
381 VertexBuffer::AttributeType::UBYTE4,
382 2 *
sizeof(filament::math::float2),
384 .normalized(VertexAttribute::COLOR)
388 void ImguiFilamentBridge::CreateIndexBuffer(
size_t buffer_index,
394 engine.destroy(impl_->index_buffers_[buffer_index]);
395 impl_->index_buffers_[buffer_index] =
396 IndexBuffer::Builder()
397 .indexCount(std::uint32_t(capacity))
398 .bufferType(IndexBuffer::IndexType::USHORT)
402 void ImguiFilamentBridge::CreateBuffers(
size_t num_required_buffers) {
403 if (num_required_buffers > impl_->vertex_buffers_.size()) {
404 size_t previous_size = impl_->vertex_buffers_.size();
405 impl_->vertex_buffers_.resize(num_required_buffers,
nullptr);
406 for (
size_t i = previous_size; i < impl_->vertex_buffers_.size(); i++) {
408 CreateVertexBuffer(i, 1000);
411 if (num_required_buffers > impl_->index_buffers_.size()) {
412 size_t previous_size = impl_->index_buffers_.size();
413 impl_->index_buffers_.resize(num_required_buffers,
nullptr);
414 for (
size_t i = previous_size; i < impl_->index_buffers_.size(); i++) {
416 CreateIndexBuffer(i, 5000);
421 void ImguiFilamentBridge::PopulateVertexData(
size_t buffer_index,
422 size_t vb_size_in_bytes,
424 size_t ib_size_in_bytes,
425 void* ib_imgui_data) {
431 size_t required_vert_count = vb_size_in_bytes /
sizeof(ImDrawVert);
432 size_t capacity_vert_count =
433 impl_->vertex_buffers_[buffer_index]->getVertexCount();
434 if (required_vert_count > capacity_vert_count) {
435 CreateVertexBuffer(buffer_index, required_vert_count);
437 size_t num_vb_bytes = required_vert_count *
sizeof(ImDrawVert);
438 void* vb_filament_data = malloc(num_vb_bytes);
439 memcpy(vb_filament_data, vb_imgui_data, num_vb_bytes);
440 impl_->vertex_buffers_[buffer_index]->setBufferAt(
442 VertexBuffer::BufferDescriptor(
443 vb_filament_data, num_vb_bytes,
444 [](
void* buffer,
size_t size,
void* user) { free(buffer); },
450 size_t required_index_count = ib_size_in_bytes / 2;
451 size_t capacity_index_count =
452 impl_->index_buffers_[buffer_index]->getIndexCount();
453 if (required_index_count > capacity_index_count) {
454 CreateIndexBuffer(buffer_index, required_index_count);
456 size_t num_ib_bytes = required_index_count * 2;
457 void* ib_filament_data = malloc(num_ib_bytes);
458 memcpy(ib_filament_data, ib_imgui_data, num_ib_bytes);
459 impl_->index_buffers_[buffer_index]->setBuffer(
461 IndexBuffer::BufferDescriptor(
462 ib_filament_data, num_ib_bytes,
463 [](
void* buffer,
size_t size,
void* user) { free(buffer); },
467 void ImguiFilamentBridge::SyncThreads() {
468 #if UTILS_HAS_THREADING
469 if (!impl_->has_synced_) {
474 Fence::waitAndDestroy(engine.createFence());
475 impl_->has_synced_ =
true;
std::vector< UVAtlasVertex > vb
std::vector< uint8_t > ib
static Application & GetInstance()
const char * GetResourcePath() const
void Update(ImDrawData *imguiData)
void OnWindowResized(const Window &window)
void CreateAtlasTextureAlpha8(unsigned char *pixels, int width, int height, int bytes_per_px)
MaterialPool(filament::Engine *engine, filament::Material *material_template)
filament::MaterialInstance * pull()
ScissorRectKey(int fb_height, const ImVec4 &clip_rect, ImTextureID tex_id)
bool operator!=(const ScissorRectKey &other) const
bool operator==(const ScissorRectKey &other) const
bool operator<(const ScissorRectKey &other) const
static filament::Engine & GetInstance()
static FilamentResourceManager & GetResourceManager()
void ConvertToGuiScene(const SceneHandle &id)
SceneHandle CreateScene() override
FilamentScene * GetGuiScene() const
std::weak_ptr< filament::Texture > GetTexture(const TextureHandle &id)
ViewHandle AddView(std::int32_t x, std::int32_t y, std::uint32_t w, std::uint32_t h) override
QTextStream & endl(QTextStream &stream)
static const std::string path
bool FReadToBuffer(const std::string &path, std::vector< char > &bytes, std::string *errorStr)
static Material * LoadMaterialTemplate(const std::string &path, Engine &engine)
static const char * kImageTexParamName
static const char * kUiBlitTexParamName
REHandle< EntityType::Texture > TextureHandle
Generic file read and write utility for python interface.
std::vector< filament::IndexBuffer * > index_buffers_
std::vector< filament::VertexBuffer * > vertex_buffers_
MaterialPool uiblit_pool_
utils::Entity renderable_