From a8e9e92d9605cfe275c1aed84036a6fbecf262aa Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 16 Aug 2019 12:23:34 +0200 Subject: [PATCH] implement export cube faces --- src/app.h | 2 +- src/app_dialogs.cpp | 14 ++++++-- src/app_layout.cpp | 15 ++++---- src/canvas.cpp | 87 ++++++++++++++++++--------------------------- src/canvas.h | 5 +-- src/node.cpp | 1 - src/rtt.cpp | 16 ++++++--- src/rtt.h | 26 +++++++------- 8 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/app.h b/src/app.h index 997d282..c8bd09a 100644 --- a/src/app.h +++ b/src/app.h @@ -232,7 +232,7 @@ public: void dialog_export(std::string ext); void dialog_export_layers(); void dialog_export_depth(); - void dialog_export_cubes(); + void dialog_export_cube_faces(); void dialog_layer_rename(); void dialog_resize(); diff --git a/src/app_dialogs.cpp b/src/app_dialogs.cpp index 810dfb8..acb70f9 100644 --- a/src/app_dialogs.cpp +++ b/src/app_dialogs.cpp @@ -508,12 +508,20 @@ void App::dialog_resize() }; } -void App::dialog_export_cubes() +void App::dialog_export_cube_faces() { if (canvas) { - canvas->m_canvas->export_cubes(); - } + canvas->m_canvas->export_cube_faces(doc_name, [this] { +#if defined(__IOS__) + message_box("Export Cube Faces", "Image and depth exported to Files/PanoPainter"); +#elif defined(__OSX__) + message_box("Export Cube Faces", "Image and depth exported to Pictures/PanoPainter folder"); +#elif defined(_WIN32) + message_box("Export Cube Faces", "Image and depth exported to " + work_path); +#endif + }); + } } void App::dialog_layer_rename() diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 4e43ad5..48c5a76 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -636,6 +636,13 @@ void App::init_menu_file() popup->mouse_release(); popup->destroy(); }; + subpopup->find("file-submenu-export-cube")->on_click = [this, subpopup, popup](Node*) { + dialog_export_cube_faces(); + subpopup->mouse_release(); + subpopup->destroy(); + popup->mouse_release(); + popup->destroy(); + }; subpopup->find("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) { dialog_export_depth(); subpopup->mouse_release(); @@ -656,13 +663,7 @@ void App::init_menu_file() popup->mouse_release(); popup->destroy(); }; - if (auto b = popup->find("file-export-cubes")) - b->on_click = [this, popup](Node*) { - dialog_export_cubes(); - popup->mouse_release(); - popup->destroy(); - }; - if (auto b = popup->find("file-cloud-upload")) + if (auto b = popup->find("file-cloud-upload")) b->on_click = [this, popup](Node*) { cloud_upload(); popup->mouse_release(); diff --git a/src/canvas.cpp b/src/canvas.cpp index 962d75f..54435bc 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1921,7 +1921,6 @@ void Canvas::export_layers(std::string file_name, std::function on_compl void Canvas::export_layers_thread(std::string file_name) { - static std::array plane_names { "front", "right", "back", "left", "top", "bottom" }; auto pb = App::I->show_progress("Export Layers", m_layers.size()); for (int i = 0; i < m_layers.size(); i++) { @@ -1933,67 +1932,51 @@ void Canvas::export_layers_thread(std::string file_name) pb->destroy(); } -void Canvas::export_cubes() +void Canvas::export_cube_faces(std::string file_name, std::function on_complete) +{ + if (App::I->check_license()) + { + std::thread t([=] { + BT_SetTerminate(); + export_cube_faces_thread(file_name); + if (on_complete) + on_complete(); + }); + t.detach(); + } +} + +void Canvas::export_cube_faces_thread(std::string file_name) { - if (!App::I->check_license()) - return; #ifdef __OBJC__ NSMutableArray* files = [NSMutableArray array]; #endif - std::array names { - "pz", "px", "nz", "nx", - "py", "ny" - }; - const int stride = m_width * 4; - auto buffer = std::make_unique(m_width * m_height * 4); - auto flipped = std::make_unique(m_width * m_height * 4); - for (int layer = 0; layer < m_layers.size(); layer++) + static std::array plane_names{ "front", "right", "back", "left", "top", "bottom" }; + + auto pb = App::I->show_progress("Export Cube Faces", 7); + + App::I->render_task([this] { + draw_merge(false); + }); + pb->increment(); + + for (int i = 0; i < 6; i++) { - for (int plane = 0; plane < 6; plane++) - { - auto& l = m_layers[layer]; - l->m_rtt[plane].bindFramebuffer(); - glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get()); - l->m_rtt[plane].unbindFramebuffer(); - - if (plane < 4) - { - for (int y = 0; y < m_height; y++) - { - int y_rev = m_height - y - 1; - std::copy_n(buffer.get() + y * stride, stride, flipped.get() + y_rev * stride); - } - std::swap(buffer, flipped); - } - else - { - for (int y = 0; y < m_height; y++) - { - auto src = (glm::u8vec4*)(buffer.get() + y * stride); - auto dst = (glm::u8vec4*)(flipped.get() + y * stride); - for (int x = 0; x < m_width; x++) - { - int x_rev = m_width - x - 1; - dst[x_rev] = src[x]; - } - //std::copy_backward(src + stride, src, dst + stride); - } - std::swap(buffer, flipped); - } - - static char name[128]; - sprintf(name, "%s-%02d-%d.png", App::I->work_path.c_str(), layer, plane); - int ret = stbi_write_png(name, m_width, m_height, 4, buffer.get(), 0); - + Image face = m_layers_merge.m_rtt[i].get_image(); + std::string path = fmt::format("{}/{}-{}.png", App::I->work_path, file_name, plane_names[i]); + face.save_png(path); + pb->increment(); #ifdef __IOS__ - save_image_library(name); + save_image_library(name); #endif #ifdef __OBJC__ - [files addObject:[NSString stringWithUTF8String : name]]; + [files addObject : [NSString stringWithUTF8String:path.c_str()] ]; #endif - } - } + } + + pb->destroy(); + #ifdef __OBJC__ static char name[128]; sprintf(name, "%s.zip", App::I->work_path.c_str()); diff --git a/src/canvas.h b/src/canvas.h index 2fd7ba3..9d54f61 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -204,10 +204,11 @@ public: void export_equirectangular(std::string file_path, std::function on_complete = nullptr); void export_equirectangular_thread(std::string file_path); void export_layers(std::string file_name, std::function on_complete = nullptr); - void export_layers_thread(std::string file_name); + void export_layers_thread(std::string file_name); void export_depth(std::string file_name, std::function on_complete = nullptr); void export_depth_thread(std::string file_name); - void export_cubes(); + void export_cube_faces(std::string file_name, std::function on_complete); + void export_cube_faces_thread(std::string file_name); void project_save(std::function on_complete = nullptr); void project_save(std::string file_path, std::function on_complete = nullptr); bool project_save_thread(std::string file_path, bool show_progress); diff --git a/src/node.cpp b/src/node.cpp index 93e1dc8..e96a6ca 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -40,7 +40,6 @@ void Node::app_redraw() { App::I->redraw = true; - App::I->ui_cv.notify_all(); App::I->render_cv.notify_all(); } diff --git a/src/rtt.cpp b/src/rtt.cpp index d8e7cd7..9da0f1d 100644 --- a/src/rtt.cpp +++ b/src/rtt.cpp @@ -274,7 +274,7 @@ void RTT::clear_mask(glm::bool4 mask, glm::vec4 color) glColorMask(old_mask[0], old_mask[1], old_mask[2], old_mask[3]); } -glm::ivec4 RTT::calc_bounds() +glm::ivec4 RTT::calc_bounds() const noexcept { auto data = std::unique_ptr(reinterpret_cast(readTextureData())); glm::ivec2 bbmin(w, h); @@ -293,7 +293,7 @@ glm::ivec4 RTT::calc_bounds() return { bbmin, bbmax }; } -uint8_t* RTT::readTextureData(uint8_t* buffer) +uint8_t* RTT::readTextureData(uint8_t* buffer) const noexcept { if (!buffer) buffer = createBuffer(); @@ -308,7 +308,7 @@ uint8_t* RTT::readTextureData(uint8_t* buffer) return buffer; } -float* RTT::readTextureDataFloat(float* buffer) +float* RTT::readTextureDataFloat(float* buffer) const noexcept { if (!buffer) buffer = createBufferFloat(); @@ -323,12 +323,12 @@ float* RTT::readTextureDataFloat(float* buffer) return buffer; } -uint8_t* RTT::createBuffer() +uint8_t* RTT::createBuffer() const noexcept { return new uint8_t[w * h * 4]; } -float * RTT::createBufferFloat() +float * RTT::createBufferFloat() const noexcept { return new float[w * h * 4]; } @@ -345,4 +345,10 @@ void RTT::unbindTexture() glBindTexture(GL_TEXTURE_2D, 0); } +Image RTT::get_image() const noexcept +{ + Image ret; + ret.create(w, h, readTextureData()); + return ret; +} diff --git a/src/rtt.h b/src/rtt.h index e17405f..aeaa869 100644 --- a/src/rtt.h +++ b/src/rtt.h @@ -1,4 +1,5 @@ #pragma once +#include "image.h" class RTT { @@ -28,20 +29,21 @@ public: bool recreate() { return create(w, h); } void clear(glm::vec4 color = glm::vec4(0)); void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0)); - glm::ivec4 calc_bounds(); - uint8_t* readTextureData(uint8_t* buffer = nullptr); - float* readTextureDataFloat(float* buffer = nullptr); - uint8_t* createBuffer(); - float* createBufferFloat(); + glm::ivec4 calc_bounds() const noexcept; + uint8_t* readTextureData(uint8_t* buffer = nullptr) const noexcept; + float* readTextureDataFloat(float* buffer = nullptr) const noexcept; + uint8_t* createBuffer() const noexcept; + float* createBufferFloat() const noexcept; void bindFramebuffer(); void unbindFramebuffer(); void bindTexture(); void unbindTexture(); - GLuint getTextureID() const { return texID; } - int getWidth() const { return w; } - int getHeight() const { return h; } - glm::ivec2 getSize() const { return { w, h }; } - int bytes() const { return w * h * 4; } - int stride() const { return w * 4; } - GLuint getFBO() const { return fboID; } + GLuint getTextureID() const noexcept { return texID; } + int getWidth() const noexcept { return w; } + int getHeight() const noexcept { return h; } + glm::ivec2 getSize() const noexcept { return { w, h }; } + int bytes() const noexcept { return w * h * 4; } + int stride() const noexcept { return w * 4; } + GLuint getFBO() const noexcept { return fboID; } + Image get_image() const noexcept; };