Skip to content

Commit

Permalink
Non blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Romain committed Aug 25, 2024
1 parent 9fec781 commit 2d22eff
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ While `rgl` is a powerful package, it has some limitations when it comes to hand

### Drawbacks:

* 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.
* 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.
* Limited to only one windows and thus one rendering.

## Installation

Expand Down
185 changes: 184 additions & 1 deletion src/lidRviewer.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,194 @@
#include <Rcpp.h>

#include <SDL2/SDL.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include <thread>
#include <atomic>

#include "drawer.h"

const float zNear = 1;
const float zFar = 100000;
const Uint32 time_per_frame = 1000 / 30;
bool running = false;

std::thread sdl_thread;

void sdl_loop(DataFrame df)
{
SDL_Event event;

unsigned int width = 600;
unsigned int height = 600;
bool run = true;

Uint32 last_time, current_time, elapsed_time;

if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
Rcpp::stop("Unable to initialize SDL: %s", SDL_GetError());
}

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window *window = SDL_CreateWindow("lidRviewer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

if (window == nullptr)
{
SDL_Quit();
Rcpp::stop("Unable to create SDL window: %s", SDL_GetError());
}

SDL_GLContext glContext = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1); // Enable VSync

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, (double)width / height, zNear, zFar);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

Drawer *drawer = new Drawer(window, df);
drawer->camera.setRotateSensivity(0.1);
drawer->camera.setZoomSensivity(10);
drawer->camera.setPanSensivity(1);
drawer->setPointSize(4);

last_time = SDL_GetTicks();

while (run)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
run = false;
break;

case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
run = false;
break;
case SDLK_z:
drawer->setAttribute(Attribute::Z);
break;
case SDLK_i:
drawer->setAttribute(Attribute::I);
break;
case SDLK_c:
drawer->setAttribute(Attribute::CLASS);
break;
case SDLK_r:
case SDLK_g:
case SDLK_b:
drawer->setAttribute(Attribute::RGB);
break;
case SDLK_q:
drawer->display_hide_spatial_index();
break;
case SDLK_l:
drawer->display_hide_edl();
break;
case SDLK_PLUS:
case SDLK_KP_PLUS:
drawer->point_size_plus();
break;
case SDLK_MINUS:
case SDLK_KP_MINUS:
drawer->point_size_minus();
break;
default:
drawer->camera.OnKeyboard(event.key);
break;
}
break;

case SDL_MOUSEMOTION:
drawer->camera.OnMouseMotion(event.motion);
break;

case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
drawer->camera.OnMouseEvent(event.button, SDL_MouseWheelEvent{}); // Pass an empty SDL_MouseWheelEvent
break;

case SDL_MOUSEWHEEL:
drawer->camera.OnMouseEvent(SDL_MouseButtonEvent{}, event.wheel); // Pass an empty SDL_MouseButtonEvent
break;

case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_RESIZED)
{
width = event.window.data1;
height = event.window.data2;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, (double)width / height, zNear, zFar);
drawer->camera.changed = true;
}
break;
}
}

current_time = SDL_GetTicks();
elapsed_time = current_time - last_time;

if (elapsed_time > time_per_frame)
{
drawer->draw();
last_time = current_time;
}
else
{
SDL_Delay(time_per_frame - elapsed_time);
}
}

current_time = SDL_GetTicks();
elapsed_time = current_time - last_time;

if (elapsed_time > time_per_frame)
{
drawer->draw();
last_time = current_time;
}
else
{
SDL_Delay(time_per_frame - elapsed_time);
}

delete drawer;
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
running = false;
}

// [[Rcpp::export]]
void viewer(DataFrame df)
{
if (running) Rcpp::stop("lidRviewer is limited to one rendering point cloud");

sdl_thread = std::thread(sdl_loop, df);
sdl_thread.detach(); // Detach the thread to allow it to run independently

running = true;
}


/*void viewer(DataFrame df)
{
bool run = true;
Expand Down Expand Up @@ -148,4 +331,4 @@ void viewer(DataFrame df)
SDL_DestroyWindow(window); // Correctly destroy window
SDL_Quit();
return;
}
}*/

0 comments on commit 2d22eff

Please sign in to comment.