implement export cube faces
This commit is contained in:
@@ -232,7 +232,7 @@ public:
|
|||||||
void dialog_export(std::string ext);
|
void dialog_export(std::string ext);
|
||||||
void dialog_export_layers();
|
void dialog_export_layers();
|
||||||
void dialog_export_depth();
|
void dialog_export_depth();
|
||||||
void dialog_export_cubes();
|
void dialog_export_cube_faces();
|
||||||
void dialog_layer_rename();
|
void dialog_layer_rename();
|
||||||
void dialog_resize();
|
void dialog_resize();
|
||||||
|
|
||||||
|
|||||||
@@ -508,11 +508,19 @@ void App::dialog_resize()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::dialog_export_cubes()
|
void App::dialog_export_cube_faces()
|
||||||
{
|
{
|
||||||
if (canvas)
|
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
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -636,6 +636,13 @@ void App::init_menu_file()
|
|||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
};
|
};
|
||||||
|
subpopup->find<NodeButtonCustom>("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<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export_depth();
|
dialog_export_depth();
|
||||||
subpopup->mouse_release();
|
subpopup->mouse_release();
|
||||||
@@ -655,12 +662,6 @@ void App::init_menu_file()
|
|||||||
dialog_resize();
|
dialog_resize();
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-export-cubes"))
|
|
||||||
b->on_click = [this, popup](Node*) {
|
|
||||||
dialog_export_cubes();
|
|
||||||
popup->mouse_release();
|
|
||||||
popup->destroy();
|
|
||||||
};
|
};
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
|
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
|
||||||
b->on_click = [this, popup](Node*) {
|
b->on_click = [this, popup](Node*) {
|
||||||
|
|||||||
@@ -1921,7 +1921,6 @@ void Canvas::export_layers(std::string file_name, std::function<void()> on_compl
|
|||||||
|
|
||||||
void Canvas::export_layers_thread(std::string file_name)
|
void Canvas::export_layers_thread(std::string file_name)
|
||||||
{
|
{
|
||||||
static std::array<const char*, 6> plane_names { "front", "right", "back", "left", "top", "bottom" };
|
|
||||||
auto pb = App::I->show_progress("Export Layers", m_layers.size());
|
auto pb = App::I->show_progress("Export Layers", m_layers.size());
|
||||||
for (int i = 0; i < m_layers.size(); i++)
|
for (int i = 0; i < m_layers.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -1933,67 +1932,51 @@ void Canvas::export_layers_thread(std::string file_name)
|
|||||||
pb->destroy();
|
pb->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::export_cubes()
|
void Canvas::export_cube_faces(std::string file_name, std::function<void()> 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__
|
#ifdef __OBJC__
|
||||||
NSMutableArray* files = [NSMutableArray array];
|
NSMutableArray* files = [NSMutableArray array];
|
||||||
#endif
|
#endif
|
||||||
std::array<std::string, 6> names {
|
static std::array<const char*, 6> plane_names{ "front", "right", "back", "left", "top", "bottom" };
|
||||||
"pz", "px", "nz", "nx",
|
|
||||||
"py", "ny"
|
|
||||||
};
|
|
||||||
const int stride = m_width * 4;
|
|
||||||
auto buffer = std::make_unique<uint8_t[]>(m_width * m_height * 4);
|
|
||||||
auto flipped = std::make_unique<uint8_t[]>(m_width * m_height * 4);
|
|
||||||
for (int layer = 0; layer < m_layers.size(); layer++)
|
|
||||||
{
|
|
||||||
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)
|
auto pb = App::I->show_progress("Export Cube Faces", 7);
|
||||||
{
|
|
||||||
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];
|
App::I->render_task([this] {
|
||||||
sprintf(name, "%s-%02d-%d.png", App::I->work_path.c_str(), layer, plane);
|
draw_merge(false);
|
||||||
int ret = stbi_write_png(name, m_width, m_height, 4, buffer.get(), 0);
|
});
|
||||||
|
pb->increment();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
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__
|
#ifdef __IOS__
|
||||||
save_image_library(name);
|
save_image_library(name);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
[files addObject:[NSString stringWithUTF8String : name]];
|
[files addObject : [NSString stringWithUTF8String:path.c_str()] ];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pb->destroy();
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
static char name[128];
|
static char name[128];
|
||||||
sprintf(name, "%s.zip", App::I->work_path.c_str());
|
sprintf(name, "%s.zip", App::I->work_path.c_str());
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ public:
|
|||||||
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<void()> on_complete = nullptr);
|
void export_depth(std::string file_name, std::function<void()> on_complete = nullptr);
|
||||||
void export_depth_thread(std::string file_name);
|
void export_depth_thread(std::string file_name);
|
||||||
void export_cubes();
|
void export_cube_faces(std::string file_name, std::function<void()> on_complete);
|
||||||
|
void export_cube_faces_thread(std::string file_name);
|
||||||
void project_save(std::function<void(bool)> on_complete = nullptr);
|
void project_save(std::function<void(bool)> on_complete = nullptr);
|
||||||
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
||||||
bool project_save_thread(std::string file_path, bool show_progress);
|
bool project_save_thread(std::string file_path, bool show_progress);
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
void Node::app_redraw()
|
void Node::app_redraw()
|
||||||
{
|
{
|
||||||
App::I->redraw = true;
|
App::I->redraw = true;
|
||||||
App::I->ui_cv.notify_all();
|
|
||||||
App::I->render_cv.notify_all();
|
App::I->render_cv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
src/rtt.cpp
16
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]);
|
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<glm::u8vec4[]>(reinterpret_cast<glm::u8vec4*>(readTextureData()));
|
auto data = std::unique_ptr<glm::u8vec4[]>(reinterpret_cast<glm::u8vec4*>(readTextureData()));
|
||||||
glm::ivec2 bbmin(w, h);
|
glm::ivec2 bbmin(w, h);
|
||||||
@@ -293,7 +293,7 @@ glm::ivec4 RTT::calc_bounds()
|
|||||||
return { bbmin, bbmax };
|
return { bbmin, bbmax };
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* RTT::readTextureData(uint8_t* buffer)
|
uint8_t* RTT::readTextureData(uint8_t* buffer) const noexcept
|
||||||
{
|
{
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
buffer = createBuffer();
|
buffer = createBuffer();
|
||||||
@@ -308,7 +308,7 @@ uint8_t* RTT::readTextureData(uint8_t* buffer)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
float* RTT::readTextureDataFloat(float* buffer)
|
float* RTT::readTextureDataFloat(float* buffer) const noexcept
|
||||||
{
|
{
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
buffer = createBufferFloat();
|
buffer = createBufferFloat();
|
||||||
@@ -323,12 +323,12 @@ float* RTT::readTextureDataFloat(float* buffer)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* RTT::createBuffer()
|
uint8_t* RTT::createBuffer() const noexcept
|
||||||
{
|
{
|
||||||
return new uint8_t[w * h * 4];
|
return new uint8_t[w * h * 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
float * RTT::createBufferFloat()
|
float * RTT::createBufferFloat() const noexcept
|
||||||
{
|
{
|
||||||
return new float[w * h * 4];
|
return new float[w * h * 4];
|
||||||
}
|
}
|
||||||
@@ -345,4 +345,10 @@ void RTT::unbindTexture()
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image RTT::get_image() const noexcept
|
||||||
|
{
|
||||||
|
Image ret;
|
||||||
|
ret.create(w, h, readTextureData());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
26
src/rtt.h
26
src/rtt.h
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
class RTT
|
class RTT
|
||||||
{
|
{
|
||||||
@@ -28,20 +29,21 @@ public:
|
|||||||
bool recreate() { return create(w, h); }
|
bool recreate() { return create(w, h); }
|
||||||
void clear(glm::vec4 color = glm::vec4(0));
|
void clear(glm::vec4 color = glm::vec4(0));
|
||||||
void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0));
|
void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0));
|
||||||
glm::ivec4 calc_bounds();
|
glm::ivec4 calc_bounds() const noexcept;
|
||||||
uint8_t* readTextureData(uint8_t* buffer = nullptr);
|
uint8_t* readTextureData(uint8_t* buffer = nullptr) const noexcept;
|
||||||
float* readTextureDataFloat(float* buffer = nullptr);
|
float* readTextureDataFloat(float* buffer = nullptr) const noexcept;
|
||||||
uint8_t* createBuffer();
|
uint8_t* createBuffer() const noexcept;
|
||||||
float* createBufferFloat();
|
float* createBufferFloat() const noexcept;
|
||||||
void bindFramebuffer();
|
void bindFramebuffer();
|
||||||
void unbindFramebuffer();
|
void unbindFramebuffer();
|
||||||
void bindTexture();
|
void bindTexture();
|
||||||
void unbindTexture();
|
void unbindTexture();
|
||||||
GLuint getTextureID() const { return texID; }
|
GLuint getTextureID() const noexcept { return texID; }
|
||||||
int getWidth() const { return w; }
|
int getWidth() const noexcept { return w; }
|
||||||
int getHeight() const { return h; }
|
int getHeight() const noexcept { return h; }
|
||||||
glm::ivec2 getSize() const { return { w, h }; }
|
glm::ivec2 getSize() const noexcept { return { w, h }; }
|
||||||
int bytes() const { return w * h * 4; }
|
int bytes() const noexcept { return w * h * 4; }
|
||||||
int stride() const { return w * 4; }
|
int stride() const noexcept { return w * 4; }
|
||||||
GLuint getFBO() const { return fboID; }
|
GLuint getFBO() const noexcept { return fboID; }
|
||||||
|
Image get_image() const noexcept;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user