Skip to content

Commit

Permalink
Move Application to dedicated source file
Browse files Browse the repository at this point in the history
  • Loading branch information
nmellado committed Dec 12, 2023
1 parent 86810e3 commit f0d2af6
Show file tree
Hide file tree
Showing 4 changed files with 304 additions and 282 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ endif()
add_executable( poncaplot
src/myview.h
src/myview.cpp
src/application.h
src/application.cpp
src/drawingPass.h
src/drawingPasses/distanceField.h
src/drawingPasses/poncaFitField.h
src/main.cpp
)
)

# Include settings
target_include_directories(poncaplot PUBLIC
Expand Down
249 changes: 249 additions & 0 deletions src/application.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
#include "application.h"

#include "myview.h"
#include "drawingPass.h"
#include "drawingPasses/distanceField.h"

#include <nanogui/window.h>
#include <nanogui/colorpicker.h>
#include <nanogui/combobox.h>
#include <nanogui/label.h>
#include <nanogui/layout.h>
#include <nanogui/textbox.h>
#include <nanogui/slider.h>
#include <nanogui/textbox.h>

#include <nanogui/opengl.h> // GLFW_KEY_ESCAPE and others

using namespace nanogui;

#define CONFIG_PONCA_FIT_INTERFACE(FitWidget,fit,name) \
{ \
FitWidget = new nanogui::Widget(window); \
FitWidget->set_layout(new GroupLayout()); \
}

const int tex_width = 500;
const int tex_height = 500;

PoncaPlotApplication::PoncaPlotApplication() : Screen(Vector2i(1024, 768), "PoncaPlot"){

passDFWithKdTree = new DistanceFieldWithKdTree();
passPlaneFit = new PlaneFitField();
passSphereFit = new SphereFitField();
passOrientedSphereFit = new OrientedSphereFitField();
passUnorientedSphereFit = new UnorientedSphereFitField();

m_passes[0] = new FillPass( {255,255,255,255});
m_passes[1] = passDFWithKdTree;
m_passes[2] = new DisplayPoint({255,0,0,255});

inc_ref();
auto *window = new Window(this, "Controls");
window->set_position(Vector2i(0, 0));
window->set_layout(new GroupLayout());


new nanogui::Label(window, "Select Fit Type", "sans-bold");
auto combo =new nanogui::ComboBox(window,
{ "Distance Field",
"Plane",
"Sphere",
"Oriented Sphere",
"Unoriented Sphere"});
combo->set_callback([this](int id){
switch (id) {
case 0: m_passes[1] = passDFWithKdTree; break;
case 1: m_passes[1] = passPlaneFit; break;
case 2: m_passes[1] = passSphereFit; break;
case 3: m_passes[1] = passOrientedSphereFit; break;
case 4: m_passes[1] = passUnorientedSphereFit; break;
default: throw std::runtime_error("Unknown Field type!");
}
buildPassInterface(id);
renderPasses();
});


// create pass 1 interface
{
pass1Widget = new nanogui::Widget(window);
pass1Widget->set_layout(new GroupLayout());
new nanogui::Label(pass1Widget, "Background filling", "sans-bold");
new nanogui::Label(pass1Widget, "Color");
// dunno why, but sets colorpicker in range [0-255], but reads in [0-1]
auto cp = new ColorPicker(pass1Widget, (dynamic_cast<FillPass *>(m_passes[0]))->m_fillColor);
cp->set_final_callback([this](const Color &c) {
dynamic_cast<FillPass *>(m_passes[0])->m_fillColor = 255.f * c;
renderPasses();
});
}

// create configurable passes interface
{
distanceFieldWidget = new nanogui::Widget(window);
distanceFieldWidget->set_layout(new GroupLayout());
new nanogui::Label(distanceFieldWidget, "Distance Field", "sans-bold");
new nanogui::Label(distanceFieldWidget, "no parameter available");
}

{
genericFitWidget = new nanogui::Widget(window);
genericFitWidget->set_layout(new GroupLayout());
new nanogui::Label(genericFitWidget, "Local Fitting", "sans-bold");
new nanogui::Label(genericFitWidget, "Scale");
auto slider = new Slider(genericFitWidget);
slider->set_value(passPlaneFit->m_scale); // init with plane, but sync with current.
slider->set_range({5,200});
slider->set_callback([&](float value) {
passPlaneFit->m_scale = value;
passSphereFit->m_scale = value;
passOrientedSphereFit->m_scale = value;
passUnorientedSphereFit->m_scale = value;
renderPasses();
});

new Label(genericFitWidget, "MLS Iterations :", "sans-bold");
auto int_box = new IntBox<int>(genericFitWidget, passPlaneFit->m_iter);
int_box->set_editable(true);
int_box->set_spinnable(true);
int_box->set_min_value(1);
int_box->set_max_value(10);
int_box->set_value_increment(1);
int_box->set_callback([&](int value) {
passPlaneFit->m_iter = value;
passSphereFit->m_iter = value;
passOrientedSphereFit->m_iter = value;
passUnorientedSphereFit->m_iter = value;
renderPasses();
});
}

CONFIG_PONCA_FIT_INTERFACE(planeFitWidget,passPlaneFit,combo->items()[1])
CONFIG_PONCA_FIT_INTERFACE(sphereFitWidget,passSphereFit,combo->items()[2])
CONFIG_PONCA_FIT_INTERFACE(orientedSphereFitWidget,passOrientedSphereFit,combo->items()[3])
CONFIG_PONCA_FIT_INTERFACE(unorientedSphereFitWidget,passUnorientedSphereFit,combo->items()[4])

// create pass 3 interface
{
pass3Widget = new nanogui::Widget(window);
pass3Widget->set_layout(new GroupLayout());
new nanogui::Label(pass3Widget, "Points Display", "sans-bold");
new nanogui::Label(pass3Widget, "Color");
// dunno why, but sets colorpicker in range [0-255], but reads in [0-1]
auto cp = new ColorPicker(pass3Widget, (dynamic_cast<DisplayPoint *>(m_passes[2]))->m_pointColor);
cp->set_final_callback([this](const Color &c) {
dynamic_cast<DisplayPoint *>(m_passes[2])->m_pointColor = 255.f * c;
renderPasses();
});
auto slider = new Slider(pass3Widget);
slider->set_value(dynamic_cast<DisplayPoint *>(m_passes[2])->m_halfSize);
slider->set_range({1,20});
slider->set_callback([&](float value) {
dynamic_cast<DisplayPoint *>(m_passes[2])->m_halfSize = int(value);
m_image_view->setSelectionThreshold(value);
renderPasses();
});
}

window = new Window(this, "Image");
window->set_position(Vector2i(200, 0));
window->set_size(Vector2i(768,768));
window->set_layout(new GroupLayout(3));

m_textureBufferPing = new uint8_t [tex_width * tex_height * 4]; // use UInt8 RGBA textures
m_textureBufferPong = new uint8_t [tex_width * tex_height * 4]; // use UInt8 RGBA textures
m_texture = new Texture(
Texture::PixelFormat::RGBA,
Texture::ComponentFormat::UInt8,
{tex_width,tex_height},
Texture::InterpolationMode::Trilinear,
Texture::InterpolationMode::Nearest,
Texture::WrapMode::ClampToEdge);

m_image_view = new MyView(window);
m_image_view->set_size(Vector2i(768, 768));
m_image_view->set_image(m_texture );
m_image_view->fitImage();
m_image_view->center();
m_image_view->setUpdateFunction([this](){ this->renderPasses();});

renderPasses(); // render twice to fill m_textureBufferPing and m_textureBufferPong
renderPasses();

// call perform_layout
buildPassInterface(0);
}


bool
PoncaPlotApplication::keyboard_event(int key, int scancode, int action, int modifiers) {
if (Screen::keyboard_event(key, scancode, action, modifiers))
return true;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
set_visible(false);
return true;
}
return false;
}

void
PoncaPlotApplication::draw(NVGcontext *ctx) {
// if (m_needUpdate)
Screen::draw(ctx);
}

void
PoncaPlotApplication::draw_contents() {
if (m_needUpdate){
m_texture->upload(m_computeInPing ? m_textureBufferPong : m_textureBufferPing);
m_needUpdate = false;
}
Screen::draw_contents();
}

void
PoncaPlotApplication::buildPassInterface(int id){
distanceFieldWidget->set_visible(false);
genericFitWidget->set_visible(false);
planeFitWidget->set_visible(false);
sphereFitWidget->set_visible(false);
orientedSphereFitWidget->set_visible(false);
unorientedSphereFitWidget->set_visible(false);
switch (id) {
case 0:
distanceFieldWidget->set_visible(true);
break;
case 1:
genericFitWidget->set_visible(true);
planeFitWidget->set_visible(true);
break;
case 2:
genericFitWidget->set_visible(true);
sphereFitWidget->set_visible(true);
break;
case 3:
genericFitWidget->set_visible(true);
orientedSphereFitWidget->set_visible(true);
break;
case 4:
genericFitWidget->set_visible(true);
unorientedSphereFitWidget->set_visible(true);
break;
default: throw std::runtime_error("Unknown Field type!");
}
perform_layout();
}

void
PoncaPlotApplication::renderPasses() {
std::cout << "[Main] Update texture" << std::endl;
const auto& points = m_image_view->getPointCollection();
for (auto* p : m_passes) {
p->render(points, m_computeInPing ? m_textureBufferPing : m_textureBufferPong, tex_width, tex_height);
}

m_computeInPing = ! m_computeInPing;
m_needUpdate = true;
}

50 changes: 50 additions & 0 deletions src/application.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <nanogui/screen.h>

// cannot forward declare aliases
#include "drawingPasses/poncaFitField.h"

// forward declarations
class DrawingPass;
class DistanceFieldWithKdTree;
class MyView;

namespace nanogui{
class Texture;
}



class PoncaPlotApplication : public nanogui::Screen {

public:
PoncaPlotApplication();

bool keyboard_event(int key, int scancode, int action, int modifiers) override;

void draw(NVGcontext *ctx) override;

void draw_contents() override;

private:
void buildPassInterface(int id);

void renderPasses();
private:
uint8_t* m_textureBufferPing {nullptr}, * m_textureBufferPong {nullptr};
bool m_computeInPing{true};
nanogui::Texture* m_texture {nullptr};
std::array<DrawingPass*,3> m_passes{nullptr, nullptr, nullptr};
bool m_needUpdate{false};
MyView *m_image_view {nullptr};
Widget* pass1Widget, *distanceFieldWidget,
*genericFitWidget, //< parameters applicable to all fitting techniques
*planeFitWidget, *sphereFitWidget, *orientedSphereFitWidget, *unorientedSphereFitWidget,
*pass3Widget;
DistanceFieldWithKdTree *passDFWithKdTree;
PlaneFitField *passPlaneFit;
SphereFitField *passSphereFit;
OrientedSphereFitField *passOrientedSphereFit;
UnorientedSphereFitField *passUnorientedSphereFit;
};
Loading

0 comments on commit f0d2af6

Please sign in to comment.