|
| 1 | +#include <Rcpp.h> |
| 2 | + |
| 3 | +#include <SDL2/SDL.h> |
| 4 | + |
| 5 | +#include <GL/gl.h> |
| 6 | +#include <GL/glu.h> |
| 7 | + |
| 8 | +#include <thread> |
| 9 | +#include <atomic> |
| 10 | + |
1 | 11 | #include "drawer.h"
|
2 | 12 |
|
3 | 13 | const float zNear = 1;
|
4 | 14 | const float zFar = 100000;
|
5 | 15 | const Uint32 time_per_frame = 1000 / 30;
|
| 16 | +bool running = false; |
| 17 | + |
| 18 | +std::thread sdl_thread; |
| 19 | + |
| 20 | +void sdl_loop(DataFrame df) |
| 21 | +{ |
| 22 | + SDL_Event event; |
| 23 | + |
| 24 | + unsigned int width = 600; |
| 25 | + unsigned int height = 600; |
| 26 | + bool run = true; |
| 27 | + |
| 28 | + Uint32 last_time, current_time, elapsed_time; |
| 29 | + |
| 30 | + if (SDL_Init(SDL_INIT_VIDEO) != 0) |
| 31 | + { |
| 32 | + Rcpp::stop("Unable to initialize SDL: %s", SDL_GetError()); |
| 33 | + } |
| 34 | + |
| 35 | + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
| 36 | + SDL_Window *window = SDL_CreateWindow("lidRviewer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); |
| 37 | + |
| 38 | + if (window == nullptr) |
| 39 | + { |
| 40 | + SDL_Quit(); |
| 41 | + Rcpp::stop("Unable to create SDL window: %s", SDL_GetError()); |
| 42 | + } |
| 43 | + |
| 44 | + SDL_GLContext glContext = SDL_GL_CreateContext(window); |
| 45 | + SDL_GL_SetSwapInterval(1); // Enable VSync |
| 46 | + |
| 47 | + glMatrixMode(GL_PROJECTION); |
| 48 | + glLoadIdentity(); |
| 49 | + gluPerspective(70, (double)width / height, zNear, zFar); |
| 50 | + |
| 51 | + glEnable(GL_DEPTH_TEST); |
| 52 | + glDepthFunc(GL_LEQUAL); |
| 53 | + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); |
| 54 | + |
| 55 | + glEnable(GL_POINT_SMOOTH); |
| 56 | + glEnable(GL_LINE_SMOOTH); |
| 57 | + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 58 | + |
| 59 | + Drawer *drawer = new Drawer(window, df); |
| 60 | + drawer->camera.setRotateSensivity(0.1); |
| 61 | + drawer->camera.setZoomSensivity(10); |
| 62 | + drawer->camera.setPanSensivity(1); |
| 63 | + drawer->setPointSize(4); |
| 64 | + |
| 65 | + last_time = SDL_GetTicks(); |
| 66 | + |
| 67 | + while (run) |
| 68 | + { |
| 69 | + while (SDL_PollEvent(&event)) |
| 70 | + { |
| 71 | + switch (event.type) |
| 72 | + { |
| 73 | + case SDL_QUIT: |
| 74 | + run = false; |
| 75 | + break; |
| 76 | + |
| 77 | + case SDL_KEYDOWN: |
| 78 | + switch (event.key.keysym.sym) |
| 79 | + { |
| 80 | + case SDLK_ESCAPE: |
| 81 | + run = false; |
| 82 | + break; |
| 83 | + case SDLK_z: |
| 84 | + drawer->setAttribute(Attribute::Z); |
| 85 | + break; |
| 86 | + case SDLK_i: |
| 87 | + drawer->setAttribute(Attribute::I); |
| 88 | + break; |
| 89 | + case SDLK_c: |
| 90 | + drawer->setAttribute(Attribute::CLASS); |
| 91 | + break; |
| 92 | + case SDLK_r: |
| 93 | + case SDLK_g: |
| 94 | + case SDLK_b: |
| 95 | + drawer->setAttribute(Attribute::RGB); |
| 96 | + break; |
| 97 | + case SDLK_q: |
| 98 | + drawer->display_hide_spatial_index(); |
| 99 | + break; |
| 100 | + case SDLK_l: |
| 101 | + drawer->display_hide_edl(); |
| 102 | + break; |
| 103 | + case SDLK_PLUS: |
| 104 | + case SDLK_KP_PLUS: |
| 105 | + drawer->point_size_plus(); |
| 106 | + break; |
| 107 | + case SDLK_MINUS: |
| 108 | + case SDLK_KP_MINUS: |
| 109 | + drawer->point_size_minus(); |
| 110 | + break; |
| 111 | + default: |
| 112 | + drawer->camera.OnKeyboard(event.key); |
| 113 | + break; |
| 114 | + } |
| 115 | + break; |
| 116 | + |
| 117 | + case SDL_MOUSEMOTION: |
| 118 | + drawer->camera.OnMouseMotion(event.motion); |
| 119 | + break; |
| 120 | + |
| 121 | + case SDL_MOUSEBUTTONUP: |
| 122 | + case SDL_MOUSEBUTTONDOWN: |
| 123 | + drawer->camera.OnMouseEvent(event.button, SDL_MouseWheelEvent{}); // Pass an empty SDL_MouseWheelEvent |
| 124 | + break; |
| 125 | + |
| 126 | + case SDL_MOUSEWHEEL: |
| 127 | + drawer->camera.OnMouseEvent(SDL_MouseButtonEvent{}, event.wheel); // Pass an empty SDL_MouseButtonEvent |
| 128 | + break; |
| 129 | + |
| 130 | + case SDL_WINDOWEVENT: |
| 131 | + if (event.window.event == SDL_WINDOWEVENT_RESIZED) |
| 132 | + { |
| 133 | + width = event.window.data1; |
| 134 | + height = event.window.data2; |
| 135 | + glViewport(0, 0, width, height); |
| 136 | + glMatrixMode(GL_PROJECTION); |
| 137 | + glLoadIdentity(); |
| 138 | + gluPerspective(70, (double)width / height, zNear, zFar); |
| 139 | + drawer->camera.changed = true; |
| 140 | + } |
| 141 | + break; |
| 142 | + } |
| 143 | + } |
| 144 | + |
| 145 | + current_time = SDL_GetTicks(); |
| 146 | + elapsed_time = current_time - last_time; |
| 147 | + |
| 148 | + if (elapsed_time > time_per_frame) |
| 149 | + { |
| 150 | + drawer->draw(); |
| 151 | + last_time = current_time; |
| 152 | + } |
| 153 | + else |
| 154 | + { |
| 155 | + SDL_Delay(time_per_frame - elapsed_time); |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + current_time = SDL_GetTicks(); |
| 160 | + elapsed_time = current_time - last_time; |
| 161 | + |
| 162 | + if (elapsed_time > time_per_frame) |
| 163 | + { |
| 164 | + drawer->draw(); |
| 165 | + last_time = current_time; |
| 166 | + } |
| 167 | + else |
| 168 | + { |
| 169 | + SDL_Delay(time_per_frame - elapsed_time); |
| 170 | + } |
| 171 | + |
| 172 | + delete drawer; |
| 173 | + SDL_GL_DeleteContext(glContext); |
| 174 | + SDL_DestroyWindow(window); |
| 175 | + SDL_Quit(); |
| 176 | + running = false; |
| 177 | +} |
6 | 178 |
|
7 | 179 | // [[Rcpp::export]]
|
8 | 180 | void viewer(DataFrame df)
|
| 181 | +{ |
| 182 | + if (running) Rcpp::stop("lidRviewer is limited to one rendering point cloud"); |
| 183 | + |
| 184 | + sdl_thread = std::thread(sdl_loop, df); |
| 185 | + sdl_thread.detach(); // Detach the thread to allow it to run independently |
| 186 | + |
| 187 | + running = true; |
| 188 | +} |
| 189 | + |
| 190 | + |
| 191 | +/*void viewer(DataFrame df) |
9 | 192 | {
|
10 | 193 | bool run = true;
|
11 | 194 |
|
@@ -148,4 +331,4 @@ void viewer(DataFrame df)
|
148 | 331 | SDL_DestroyWindow(window); // Correctly destroy window
|
149 | 332 | SDL_Quit();
|
150 | 333 | return;
|
151 |
| -} |
| 334 | +}*/ |
0 commit comments