Newer
Older
#include "src_window.hpp"
#include <nanogui/imageview.h>
#include <nanogui/combobox.h>
#include <nanogui/label.h>
#include <nanogui/opengl.h>
#include <nanogui/glutil.h>
#include <nanogui/screen.h>
#include <nanogui/layout.h>
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using std::string;
class GLTexture {
public:
GLTexture() {
glGenTextures(1, &glid_);
glBindTexture(GL_TEXTURE_2D, glid_);
cv::Mat m(cv::Size(100,100), CV_8UC3);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m.cols, m.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, m.data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
~GLTexture() {
glDeleteTextures(1, &glid_);
}
void update(cv::Mat &m) {
if (m.rows == 0) return;
glBindTexture(GL_TEXTURE_2D, glid_);
// TODO Allow for other formats
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m.cols, m.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, m.data);
auto err = glGetError();
if (err != 0) LOG(ERROR) << "OpenGL Texture error: " << err;
}
unsigned int texture() const { return glid_; }
private:
unsigned int glid_;
};
template<class T>
Eigen::Matrix<T,4,4> lookAt
(
Eigen::Matrix<T,3,1> const & eye,
Eigen::Matrix<T,3,1> const & center,
Eigen::Matrix<T,3,1> const & up
)
{
typedef Eigen::Matrix<T,4,4> Matrix4;
typedef Eigen::Matrix<T,3,1> Vector3;
Vector3 f = (center - eye).normalized();
Vector3 u = up.normalized();
Vector3 s = f.cross(u).normalized();
u = s.cross(f);
Matrix4 res;
res << s.x(),s.y(),s.z(),-s.dot(eye),
u.x(),u.y(),u.z(),-u.dot(eye),
-f.x(),-f.y(),-f.z(),f.dot(eye),
0,0,0,1;
return res;
}
class VirtualCameraView : public nanogui::ImageView {
public:
VirtualCameraView(nanogui::Widget *parent) : nanogui::ImageView(parent, 0) {
src_ = nullptr;
eye_ = Eigen::Vector3f(0.0f, 0.0f, 0.0f);
centre_ = Eigen::Vector3f(0.0f, 0.0f, -4.0f);
up_ = Eigen::Vector3f(0,1.0f,0);
lookPoint_ = Eigen::Vector3f(0.0f,0.0f,-4.0f);
lerpSpeed_ = 0.4f;
depth_ = false;
}
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
bool mouseButtonEvent(const nanogui::Vector2i &p, int button, bool down, int modifiers) {
//LOG(INFO) << "Mouse move: " << p[0];
if (src_ && down) {
Eigen::Vector4f camPos = src_->point(p[0],p[1]);
camPos *= -1.0f;
Eigen::Vector4f worldPos = src_->getPose() * camPos;
lookPoint_ = Eigen::Vector3f(worldPos[0],worldPos[1],worldPos[2]);
LOG(INFO) << "Depth at click = " << -camPos[2];
}
}
bool keyboardEvent(int key, int scancode, int action, int modifiers) {
LOG(INFO) << "Key press" << key << " - " << action;
if (key == 81 || key == 83) {
// TODO Should rotate around lookAt object, but requires correct depth
Eigen::Quaternion<float> q; q = Eigen::AngleAxis<float>((key == 81) ? 0.01f : -0.01f, up_);
eye_ = (q * (eye_ - centre_)) + centre_;
} else if (key == 84 || key == 82) {
float scalar = (key == 84) ? 0.99f : 1.01f;
eye_ = ((eye_ - centre_) * scalar) + centre_;
}
}
void draw(NVGcontext *ctx) {
//net_->broadcast("grab");
if (src_) {
cv::Mat rgb, depth;
centre_ += (lookPoint_ - centre_) * (lerpSpeed_ * 0.1f);
Eigen::Matrix4f viewPose = lookAt<float>(eye_,centre_,up_).inverse();
src_->setPose(viewPose);
src_->grab();
if (depth_) {
if (depth.rows > 0) {
cv::Mat idepth;
depth.convertTo(idepth, CV_8U, 255.0f / 10.0f); // TODO(nick)
applyColorMap(idepth, idepth, cv::COLORMAP_JET);
texture_.update(idepth);
bindImage(texture_.texture());
}
} else {
if (rgb.rows > 0) {
texture_.update(rgb);
bindImage(texture_.texture());
}
}
screen()->performLayout(ctx);
}
ImageView::draw(ctx);
}
void setDepth(bool d) { depth_ = d; }
private:
GLTexture texture_;
Eigen::Vector3f eye_;
Eigen::Vector3f centre_;
Eigen::Vector3f up_;
Eigen::Vector3f lookPoint_;
float lerpSpeed_;
bool depth_;
};
SourceWindow::SourceWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl)
: nanogui::Window(parent, "Source View"), ctrl_(ctrl) {
setLayout(new nanogui::GroupLayout());
using namespace nanogui;
src_ = ftl::create<Source>(ctrl->getRoot(), "source", ctrl->getNet());
//Widget *tools = new Widget(this);
// tools->setLayout(new BoxLayout(Orientation::Horizontal,
// Alignment::Middle, 0, 6));
available_ = ctrl->getNet()->findAll<string>("list_streams");
select->setCallback([this,select](int ix) {
ctrl->getNet()->onConnect([this,select](ftl::net::Peer *p) {
available_ = ctrl_->getNet()->findAll<string>("list_streams");
select->setItems(available_);
});
depth->setFlags(Button::ToggleButton);
depth->setChangeCallback([this](bool state) {
auto snapshot = new Button(this, "Snapshot");
snapshot->setCallback([this] {
try {
char timestamp[18];
std::time_t t=std::time(NULL);
std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t));
auto writer = ftl::rgbd::SnapshotWriter(std::string(timestamp) + ".tar.gz");
cv::Mat rgb, depth;
if (!writer.addCameraRGBD(
"0", // TODO
rgb,
depth,
this->src_->getPose(),
)) {
LOG(ERROR) << "Snapshot failed";
}
}
catch(std::runtime_error) {
LOG(ERROR) << "Snapshot failed (file error)";
}
});
#endif
//cam.view = imageView;
//imageView->setGridThreshold(20);
//imageView->setSource(src_);
//image_ = imageView;
}
SourceWindow::~SourceWindow() {
}