29#include <easy3d/core/point_cloud.h>
30#include <easy3d/renderer/opengl.h>
31#include <easy3d/renderer/drawable_points.h>
32#include <easy3d/renderer/drawable_lines.h>
33#include <easy3d/renderer/camera.h>
34#include <easy3d/renderer/manipulated_camera_frame.h>
35#include <easy3d/renderer/texture_manager.h>
36#include <easy3d/renderer/shape.h>
37#include <easy3d/renderer/renderer.h>
38#include <easy3d/renderer/shader_program.h>
39#include <easy3d/renderer/shader_manager.h>
40#include <easy3d/renderer/transform.h>
41#include <easy3d/util/string.h>
42#include <easy3d/util/file_system.h>
43#include <easy3d/util/resource.h>
49const float scale = 0.3f;
51RealCamera::RealCamera(
const std::string& title,
52 const std::string& bundler_file,
53 const std::string& cloud_file)
54 :
Viewer(title, 4, 3, 2, false, false)
57 , cameras_drawable_(nullptr)
58 , ray_drawable_(nullptr)
59 , cross_drawable_(nullptr)
63 auto drawable = current_model()->renderer()->get_points_drawable(
"vertices");
64 drawable->set_point_size(5.0f);
67 if (read_bundler_file(bundler_file))
68 update_cameras_drawable(
true);
70 LOG(ERROR) <<
"failed to load bundler file";
72 camera()->setUpVector(
vec3(0, 1, 0));
73 camera()->setViewDirection(
vec3(0, 0, -1));
74 camera_->showEntireScene();
77 LOG(ERROR) <<
"failed to load point cloud";
80 "---------------- Real Camera usage ------------------ \n"
81 "Press 'Space' to switch views \n"
82 "Press 'H' to show/hide the cameras \n"
83 "Move cursor on image to show corresponding 3D ray \n"
84 "Move cursor on scene to show corresponding image point\n"
85 "----------------------------------------------------- \n";
89bool RealCamera::key_press_event(
int key,
int modifiers) {
91 ray_drawable_->set_visible(
false);
93 cross_drawable_->set_visible(
false);
95 if (key == KEY_SPACE) {
96 if (!views_.empty()) {
97 current_view_ = (current_view_ + 1) %
static_cast<int>(views_.size());
98 const bool ground_truth =
true;
99 if (KRT_to_camera(current_view_, camera(), ground_truth)) {
100 update_cameras_drawable(ground_truth);
101 std::cout <<
"----- view " << current_view_ <<
": " << (ground_truth ?
"ground truth view" :
"calibration view") << std::endl;
102 set_title(
"RealCamera: View_" + std::to_string(current_view_));
103 const CameraPara &c = views_[current_view_];
105 resize(
static_cast<int>(
static_cast<float>(c.w) * scale),
static_cast<int>(
static_cast<float>(c.h) * scale));
110 else if (key == KEY_1) {
111 if (!views_.empty()) {
112 const bool ground_truth =
false;
113 if (KRT_to_camera(current_view_, camera(), ground_truth)) {
114 update_cameras_drawable(ground_truth);
115 std::cout <<
"----- view " << current_view_ <<
": " << (ground_truth ?
"ground truth view" :
"calibration view") << std::endl;
116 set_title(
"RealCamera: View_" + std::to_string(current_view_));
117 const CameraPara &c = views_[current_view_];
119 resize(
static_cast<int>(
static_cast<float>(c.w) * scale),
static_cast<int>(
static_cast<float>(c.h) * scale));
124 else if (key == KEY_2) {
125 if (!views_.empty()) {
126 const bool ground_truth =
true;
127 if (KRT_to_camera(current_view_, camera(), ground_truth)) {
128 update_cameras_drawable(ground_truth);
129 std::cout <<
"----- view " << current_view_ <<
": " << (ground_truth ?
"ground truth view" :
"calibration view") << std::endl;
130 set_title(
"RealCamera: View_" + std::to_string(current_view_));
131 const CameraPara &c = views_[current_view_];
133 resize(
static_cast<int>(
static_cast<float>(c.w) * scale),
static_cast<int>(
static_cast<float>(c.h) * scale));
138 else if (key == KEY_H) {
139 if (cameras_drawable_) {
140 cameras_drawable_->set_visible(!cameras_drawable_->is_visible());
146 return Viewer::key_press_event(key, modifiers);
150void RealCamera::load_image() {
151 const std::string image_file = resource::directory() +
"/data/fountain/images/" + string::to_string(current_view_, 4,
'0') +
".jpg";
152 if (file_system::is_file(image_file)) {
153 texture_ = TextureManager::request(image_file);
159bool RealCamera::KRT_to_camera(
int view_index,
Camera* c,
bool ground_truth) {
160 if (view_index < 0 || view_index >= views_.size()) {
161 std::cerr <<
"Error: invalid view index (" << view_index <<
")" << std::endl;
165 const CameraPara& cam = views_[view_index];
172 const float proj11 = 2.0f * cam.fy /
static_cast<float>(cam.h);
173 const float fov = 2.0f * std::atan(1.0f / proj11);
178 cam.fx, cam.fy, 0.0f,
189void RealCamera::update_cameras_drawable(
bool ground_truth)
191 if (!cameras_drawable_) {
193 add_drawable(cameras_drawable_);
194 cameras_drawable_->set_uniform_coloring(
vec4(0, 0, 1, 1.0f));
195 cameras_drawable_->set_line_width(2.0f);
198 std::vector<vec3> vertices;
199 for (std::size_t i = 0; i < views_.size(); ++i) {
201 KRT_to_camera(
static_cast<int>(i), &c, ground_truth);
202 std::vector<vec3> points;
203 shape::create_camera(points, c.
sceneRadius() * 0.03f, c.
fieldOfView(),
static_cast<float>(views_[i].h)/
static_cast<float>(views_[i].w));
205 for (
auto& p : points)
206 vertices.push_back(m * p);
209 cameras_drawable_->update_vertex_buffer(vertices);
213Rect RealCamera::calculate_image_rect()
const {
214 if (texture_ ==
nullptr) {
215 LOG_N_TIMES(3, ERROR) <<
"image not shown";
219 int tex_w = texture_->
width();
220 int tex_h = texture_->height();
221 const float image_as =
static_cast<float>(tex_w) /
static_cast<float>(tex_h);
222 const float viewer_as =
static_cast<float>(width()) /
static_cast<float>(height());
223 if (image_as < viewer_as) {
224 tex_h =
static_cast<int>(
static_cast<float>(height()) * scale);
225 tex_w =
static_cast<int>(
static_cast<float>(tex_h) * image_as);
228 tex_w =
static_cast<int>(
static_cast<float>(width()) * scale);
229 tex_h =
static_cast<int>(
static_cast<float>(tex_w) / image_as);
232 return Rect(
static_cast<float>(20),
static_cast<float>(20 + tex_w), 40.0f,
static_cast<float>(40 + tex_h));
236void RealCamera::post_draw() {
239 if (texture_ ==
nullptr)
242 const Rect image_rect = calculate_image_rect();
243 const Rect quad(image_rect.
x_min() * dpi_scaling(), image_rect.
x_max() * dpi_scaling(),
244 image_rect.
y_min() * dpi_scaling(), image_rect.
y_max() * dpi_scaling());
246 const int w =
static_cast<int>(
static_cast<float>(width()) * dpi_scaling());
247 const int h =
static_cast<int>(
static_cast<float>(height()) * dpi_scaling());
248 shape::draw_quad_filled(quad, texture_->id(), w, h, -0.9f);
249 shape::draw_quad_wire(quad,
vec4(1.0f, 0.0f, 0.0f, 1.0f), w, h, -0.99f);
253 if (cross_drawable_ && cross_drawable_->is_visible()) {
254 ShaderProgram *program = ShaderManager::get_program(
"lines/lines_plain_color");
256 std::vector<ShaderProgram::Attribute> attributes;
257 attributes.emplace_back(ShaderProgram::Attribute(ShaderProgram::POSITION,
"vtx_position"));
258 attributes.emplace_back(ShaderProgram::Attribute(ShaderProgram::COLOR,
"vtx_color"));
259 program = ShaderManager::create_program_from_files(
"lines/lines_plain_color", attributes);
264 const mat4 &proj = transform::ortho(0.0f,
static_cast<float>(width()),
static_cast<float>(height()), 0.0f,
266 glDisable(GL_DEPTH_TEST);
268 program->
set_uniform(
"MVP", proj);
269 program->set_uniform(
"per_vertex_color",
false);
270 program->set_uniform(
"default_color",
vec4(0.0f, 1.0f, 0.0f, 1.0f));
271 cross_drawable_->gl_draw();
273 glEnable(GL_DEPTH_TEST);
278bool RealCamera::mouse_free_move_event(
int x,
int y,
int dx,
int dy,
int modifiers) {
283 if (current_view_ < 0 || current_view_ >= views_.size()) {
284 std::cerr <<
"Error: invalid view index (" << current_view_ <<
")" << std::endl;
288 const CameraPara &cam = views_[current_view_];
289 const Rect image_rect = calculate_image_rect();
291 if (
static_cast<float>(x) >= image_rect.x_min() &&
static_cast<float>(x) <= image_rect.x_max() &&
static_cast<float>(y) >= image_rect.y_min() &&
static_cast<float>(y) <= image_rect.y_max()) {
292 const float image_x = (
static_cast<float>(x) - image_rect.x_min()) / image_rect.
width() *
static_cast<float>(cam.w);
293 const float image_y = (
static_cast<float>(y) - image_rect.y_min()) / image_rect.
height() *
static_cast<float>(cam.h);
294 if (!ray_drawable_) {
296 add_drawable(ray_drawable_);
297 ray_drawable_->set_uniform_coloring(
vec4(0, 1, 0, 1.0f));
298 ray_drawable_->set_line_width(3.0f);
299 ray_drawable_->set_impostor_type(easy3d::LinesDrawable::CYLINDER);
301 const vec3 pos = camera_pos(cam.R, cam.t);
302 const vec3 dir = pixel_to_ray(
static_cast<int>(image_x),
static_cast<int>(image_y), cam.fx, cam.fy, 0, cam.cx, cam.cy, cam.R, cam.t,
true);
303 const std::vector<vec3> points = {pos, pos + dir};
304 ray_drawable_->update_vertex_buffer(points);
305 ray_drawable_->set_visible(
true);
309 ray_drawable_->set_visible(
false);
312 const vec3 p = point_under_pixel(x, y, found);
314 const vec2 q = point_to_pixel(p, cam.fx, cam.fy, 0, cam.cx, cam.cy, cam.R, cam.t);
317 if (q.x >= 0 && q.x <=
static_cast<float>(cam.w) && q.y >= 0 && q.y <=
static_cast<float>(cam.h)) {
318 const float screen_x = q.x /
static_cast<float>(cam.w) * image_rect.
width() + image_rect.x_min();
319 const float screen_y = q.y /
static_cast<float>(cam.h) * image_rect.
height() + image_rect.y_min();
320 if (!cross_drawable_) {
322 add_drawable(cross_drawable_);
323 cross_drawable_->set_line_width(3.0f);
326#if defined(__APPLE__)
327 const float size = 10;
329 const float size =
static_cast<float>(10 * dpi_scaling());
331 const std::vector<vec3> points = {
332 vec3(screen_x - size, screen_y, 0.5f),
vec3(screen_x + size, screen_y, 0.5f),
333 vec3(screen_x, screen_y - size, 0.5f),
vec3(screen_x, screen_y + size, 0.5f)
335 cross_drawable_->update_vertex_buffer(points);
336 cross_drawable_->set_visible(
true);
340 cross_drawable_->set_visible(
false);
350vec3 RealCamera::camera_pos(
const mat3 &R,
const vec3 &t) {
355vec3 RealCamera::pixel_to_ray(
int image_x,
int image_y,
float fx,
float fy,
float skew,
float cx,
float cy,
356 const mat3& R,
const vec3& t,
bool convert) {
362 vec3 P =
inverse(K) *
vec3(
static_cast<float>(image_x),
static_cast<float>(image_y), 1);
373 return P - camera_pos(R, t);
378 float fx,
float fy,
float skew,
float cx,
float cy,
401 return vec2(q.x, q.y);
void setOrientation(const quat &q) const
Definition: camera.cpp:869
float sceneRadius() const
Returns the radius of the scene observed by the Camera.
Definition: camera.h:408
void setFieldOfView(float fov)
Definition: camera.cpp:257
void set_from_calibration(float fx, float fy, float skew, float cx, float cy, const mat3 &R, const vec3 &t, bool convert=true)
Defines the position(), orientation() and fieldOfView() of the camera from calibrated camera intrinsi...
Definition: camera.cpp:995
float fieldOfView() const
Returns the vertical field of view of the Camera (in radians).
Definition: camera.h:278
void setPosition(const vec3 &pos) const
Definition: camera.cpp:950
ManipulatedCameraFrame * frame() const
Returns the ManipulatedFrame attached to the Camera.
Definition: camera.h:438
mat4 worldMatrix() const
Definition: frame.cpp:201
FT height() const
Returns the height of the rectangle.
Definition: rect.h:80
FT width() const
Returns the width of the rectangle.
Definition: rect.h:78
Base class for matrix types.
Definition: mat.h:66
Vec< N, T > col(size_t c) const
Return col c as a vector.
Definition: mat.h:509
void set_col(size_t c, const Vec< vN, T > &v)
Set col c from vector v. This copies the first N components from v, so vN must be >= N....
Definition: mat.h:532
OpenGL Shader Compilation.
Definition: shader_program.h:78
void bind() const
Starts using the program.
Definition: shader_program.cpp:678
void release() const
Ends using the program.
Definition: shader_program.cpp:689
virtual Model * add_model(const std::string &file_name, bool create_default_drawables=true)
Add a model from a file to the viewer to be visualized. On success, the viewer will be in charge of t...
Definition: viewer.cpp:1204
Mat< M, N, T > transpose(const Mat< N, M, T > &m)
Transpose m.
Definition: mat.h:907
Mat< N, N, T > inverse(const Mat< N, N, T > &m)
Return the inverse of N x N (square) matrix m.
Definition: mat.h:977