Skip to content

Commit 2d22eff

Browse files
committed
Non blocking
1 parent 9fec781 commit 2d22eff

File tree

2 files changed

+185
-2
lines changed

2 files changed

+185
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ While `rgl` is a powerful package, it has some limitations when it comes to hand
1717

1818
### Drawbacks:
1919

20-
* Blocks the R session: while the viewer window is open, you cannot use R for other tasks. You must close the viewer window to resume normal R usage.
2120
* Limited functionality: only displays point clouds and does not offer additional features. It is not intended to replace `rgl` for other visualization needs and custom rendering.
21+
* Limited to only one windows and thus one rendering.
2222

2323
## Installation
2424

src/lidRviewer.cpp

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,194 @@
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+
111
#include "drawer.h"
212

313
const float zNear = 1;
414
const float zFar = 100000;
515
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+
}
6178

7179
// [[Rcpp::export]]
8180
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)
9192
{
10193
bool run = true;
11194
@@ -148,4 +331,4 @@ void viewer(DataFrame df)
148331
SDL_DestroyWindow(window); // Correctly destroy window
149332
SDL_Quit();
150333
return;
151-
}
334+
}*/

0 commit comments

Comments
 (0)