Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
sdlmain.cpp
1 #include "octree.h"
2 #include "synchronized.h"
3 #include "renderer.h"
4 #include "vector.h"
5 #include "exception.h"
6 #include "helpers.h"
7 #include "settings.h"
8 
9 #ifdef _OPENMP
10 #include <omp.h>
11 #endif // _OPENMP
12 
13 #include <SDL/SDL.h>
14 #include <SDL/SDL_ttf.h>
15 
16 #include <iostream>
17 #include <array>
18 #include <memory>
19 #include <cmath>
20 #include <stdexcept>
21 
22 #include <stdlib.h>
23 #include <time.h>
24 #include <sys/time.h>
25 
26 
27 
28 
29 /*==============================================================================
30  Global variables
31 ==============================================================================*/
32 
33 
34 double g_fps = 0;
35 double g_rps = 0;
36 
37 
38 
39 
40 /*==============================================================================
41  Redraw function
42 ==============================================================================*/
43 
44 
45 template< int t_ColorFormat, int t_Platform, int t_RendererPlatform >
46 void Redraw(
47  SDL_Surface* pSurface,
48  TTF_Font* pFont,
49  Synchronized::Heap< t_Platform >& heap,
50  Synchronized::TextureHeap< t_ColorFormat, t_Platform >& textureHeap,
51  typename Synchronized::Heap< t_Platform >::template Pointer< Octree::Node< t_ColorFormat, t_Platform > > const& pRoot,
52  Renderer::State< t_RendererPlatform > const& renderer,
53  Renderer::Camera const& camera
54 )
55 {
56  if ( SDL_FillRect( pSurface, NULL, SDL_MapRGB( pSurface->format, 0, 0, 0 ) ) != 0 )
57  THROW_EXCEPTION_MESSAGE( "SDL_FillRect failed!", SDL_GetError() );
58 
59  if ( SDL_LockSurface( pSurface ) != 0 )
60  THROW_EXCEPTION_MESSAGE( "SDL_LockSurface failed!", SDL_GetError() );
61  try { // **TODO: RAII?
62 
63  Vector< unsigned int, 2 > const dimensions = { { pSurface->w, pSurface->h } };
64 
65 #if 0
66  typename Synchronized::Heap< t_Platform >::template Pointer< Octree::Node< t_ColorFormat, t_Platform > > const pSubtractedRoot = Octree::Subtract(
67  heap,
68  textureHeap,
69  pRoot,
70  g_coordinates,
71  0.1,
72  2
73  );
74  heap.Synchronize();
75  textureHeap.Synchronize();
76 #else // 0/1
77  typename Synchronized::Heap< t_Platform >::template Pointer< Octree::Node< t_ColorFormat, t_Platform > > const& pSubtractedRoot = pRoot;
78 #endif // 0/1
79 
80  renderer.TraceScreen(
81  static_cast< uint8_t* >( pSurface->pixels ),
82  dimensions,
83  pSurface->pitch,
84  heap,
85  textureHeap,
86  pSubtractedRoot,
87  camera
88  );
89  }
90  catch( ... ) {
91 
92  SDL_UnlockSurface( pSurface );
93  throw;
94  }
95  SDL_UnlockSurface( pSurface );
96 
97  { char strings[ 4 ][ 128 ];
98 
99 #ifdef _OPENMP
100  unsigned int const threads = omp_get_max_threads();
101 #else // _OPENMP
102  unsigned int const threads = 1;
103 #endif // _OPENMP
104  snprintf( strings[ 0 ], ARRAYLENGTH( strings[ 0 ] ), "threads = %u, resolution = %dx%d", threads, pSurface->w, pSurface->h );
105  snprintf( strings[ 1 ], ARRAYLENGTH( strings[ 1 ] ), "%.2f Mrays / frame", pSurface->w * pSurface->h / 1000000.0 );
106  snprintf( strings[ 2 ], ARRAYLENGTH( strings[ 2 ] ), "%.2f frames / sec", g_fps );
107  snprintf( strings[ 3 ], ARRAYLENGTH( strings[ 3 ] ), "%.2f Mrays / sec", g_rps / 1000000 );
108 
109  SDL_Color const textColor = { 0xff, 0xff, 0xff };
110 
111  Sint16 xx = 8;
112  Sint16 yy = 8;
113  for ( unsigned int ii = 0; ii < ARRAYLENGTH( strings ); ++ii ) {
114 
115  strings[ ii ][ ARRAYLENGTH( strings[ ii ] ) - 1 ] = '\0';
116 
117  std::unique_ptr< SDL_Surface, void (*)( SDL_Surface* ) > pTextSurface( TTF_RenderText_Blended( pFont, strings[ ii ], textColor ), SDL_FreeSurface );
118  if ( pTextSurface.get() == NULL )
119  THROW_EXCEPTION_MESSAGE( "TTF_RenderText_Blended failed!", TTF_GetError() );
120 
121  SDL_Rect destinationRect = { xx, yy, static_cast< Uint16 >( pTextSurface->w ), static_cast< Uint16 >( pTextSurface->h ) };
122  if ( SDL_BlitSurface( pTextSurface.get(), NULL, pSurface, &destinationRect ) != 0 )
123  THROW_EXCEPTION_MESSAGE( "SDL_BlitSurface failed!", SDL_GetError() );
124  yy += pTextSurface->h;
125  }
126  }
127 }
128 
129 
130 
131 
132 /*==============================================================================
133  main function
134 ==============================================================================*/
135 
136 
137 int main( int argc, char* argv[] ) {
138 
139  int result = EXIT_SUCCESS;
140 
141  try {
142 
143  // ==== initialize voxel and keyboard data ====
144 
145  //enum { COLOR_FORMAT = COLOR_FORMAT_RGB_565 };
146  enum { COLOR_FORMAT = COLOR_FORMAT_RGBA_8888 };
147 #if ( SETTING_OPENCL != 0 )
148  std::shared_ptr< OpenCL::State > pState( new OpenCL::State() );
149  Synchronized::Heap< PLATFORM_OPENCL > heap( pState, ( 1u << 25 ) );
150  Synchronized::TextureHeap< COLOR_FORMAT, PLATFORM_OPENCL > textureHeap( pState, 27 );
151  Synchronized::Heap< PLATFORM_OPENCL >::Pointer< Octree::Node< COLOR_FORMAT, PLATFORM_OPENCL > > pRoot = Octree::Create( heap, textureHeap );
152  Renderer::State< PLATFORM_OPENCL > renderer( pState );
153 #else // SETTING_OPENCL
155  Synchronized::TextureHeap< COLOR_FORMAT, PLATFORM_HOST > textureHeap;
156  Synchronized::Heap< PLATFORM_HOST >::Pointer< Octree::Node< COLOR_FORMAT, PLATFORM_HOST > > pRoot = Octree::Create( heap, textureHeap );
158 #endif // SETTING_OPENCL
159  heap.Synchronize();
160  textureHeap.Synchronize();
161 
162  Vector< double, 3 > const initialX = { { 1, 0, 0 } };
163  Vector< double, 3 > const initialY = { { 0, 1, 0 } };
164  Vector< double, 3 > const initialZ = { { 0, 0, 1 } };
165  Vector< double, 3 > const initialPosition = { { 0.5, 0.5, 1.5 } };
166  Renderer::Camera camera( initialX, initialY, initialZ, initialPosition );
167 
168  enum MovementKeys {
169 
170  MOVEMENT_KEY_MOVE_FORWARD = 0,
171  MOVEMENT_KEY_MOVE_BACK,
172  MOVEMENT_KEY_MOVE_DOWN,
173  MOVEMENT_KEY_MOVE_UP,
174  MOVEMENT_KEY_MOVE_RIGHT,
175  MOVEMENT_KEY_MOVE_LEFT,
176  MOVEMENT_KEY_TURN_COUNTERCLOCKWISE,
177  MOVEMENT_KEY_TURN_CLOCKWISE,
178  MOVEMENT_KEY_TURN_RIGHT,
179  MOVEMENT_KEY_TURN_LEFT,
180  MOVEMENT_KEY_TURN_UP,
181  MOVEMENT_KEY_TURN_DOWN,
182  MOVEMENT_KEY_ZOOM_IN,
183  MOVEMENT_KEY_ZOOM_OUT,
184 
185  MOVEMENT_KEYS_SIZE
186  };
187  bool movementKeys[ MOVEMENT_KEYS_SIZE ];
188  std::fill( movementKeys, movementKeys + ARRAYLENGTH( movementKeys ), false );
189 
190  double const fpsRate = 0.95;
191  double const rateTurn = 0.8;
192  double const rateZoom = 0.4;
193  double const rateMove = 0.2;
194 
195  // ==== initialize SDL ====
196 
197  if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
198  THROW_EXCEPTION_MESSAGE( "SDL_Init failed!", SDL_GetError() );
199  atexit( SDL_Quit );
200 
201  std::unique_ptr< SDL_Surface, void (*)( SDL_Surface* ) > pSurface( SDL_SetVideoMode( 800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF ), SDL_FreeSurface );
202  if ( pSurface.get() == NULL )
203  THROW_EXCEPTION_MESSAGE( "SDL_SetVideoMode failed!", SDL_GetError() );
204 
205  SDL_WM_SetCaption( "Voxel", "Voxel" );
206 
207  // ==== initialize SDL font support ====
208 
209  if ( TTF_Init() != 0 )
210  THROW_EXCEPTION_MESSAGE( "TTF_Init failed!", TTF_GetError() );
211  atexit( TTF_Quit );
212 
213  std::unique_ptr< TTF_Font, void (*)( TTF_Font* ) > pFont( TTF_OpenFont( "verdanab.ttf", 14 ), TTF_CloseFont );
214  if ( pFont.get() == NULL )
215  THROW_EXCEPTION_MESSAGE( "TTF_OpenFont failed!", TTF_GetError() );
216 
217  // ==== message loop ====
218 
219  double frames = 0;
220  double rays = 0;
221  double seconds = 0;
222  double ticks = 0;
223  { struct timeval time;
224  gettimeofday( &time, NULL );
225  ticks = time.tv_sec + static_cast< double >( time.tv_usec ) / 1000000;
226  }
227 
228  SDL_Event event;
229  for ( bool done = false; ! done; ) {
230 
231  // ==== draw frame ====
232 
233  Redraw( pSurface.get(), pFont.get(), heap, textureHeap, pRoot, renderer, camera );
234  SDL_Flip( pSurface.get() );
235 
236  // ==== update counters ====
237 
238  double const ticksOld = ticks;
239  { struct timeval time;
240  gettimeofday( &time, NULL );
241  ticks = time.tv_sec + static_cast< double >( time.tv_usec ) / 1000000;
242  }
243  double const deltaSeconds = ticks - ticksOld;
244 
245  frames = fpsRate * frames + ( 1 - fpsRate );
246  rays = fpsRate * rays + ( 1 - fpsRate ) * pSurface->w * pSurface->h;
247  seconds = fpsRate * seconds + ( 1 - fpsRate ) * deltaSeconds;
248 
249  g_fps = frames / seconds;
250  g_rps = rays / seconds;
251 
252  // ==== process messages ====
253 
254  while ( SDL_PollEvent( &event ) ) {
255 
256  switch( event.type ) {
257 
258  case SDL_KEYUP: {
259 
260  switch( event.key.keysym.sym ) {
261  case SDLK_w: { movementKeys[ MOVEMENT_KEY_MOVE_FORWARD ] = false; break; }
262  case SDLK_s: { movementKeys[ MOVEMENT_KEY_MOVE_BACK ] = false; break; }
263  case SDLK_PAGEDOWN: { movementKeys[ MOVEMENT_KEY_MOVE_DOWN ] = false; break; }
264  case SDLK_PAGEUP: { movementKeys[ MOVEMENT_KEY_MOVE_UP ] = false; break; }
265  case SDLK_d: { movementKeys[ MOVEMENT_KEY_MOVE_RIGHT ] = false; break; }
266  case SDLK_a: { movementKeys[ MOVEMENT_KEY_MOVE_LEFT ] = false; break; }
267  case SDLK_q: { movementKeys[ MOVEMENT_KEY_TURN_COUNTERCLOCKWISE ] = false; break; }
268  case SDLK_e: { movementKeys[ MOVEMENT_KEY_TURN_CLOCKWISE ] = false; break; }
269  case SDLK_RIGHT: { movementKeys[ MOVEMENT_KEY_TURN_RIGHT ] = false; break; }
270  case SDLK_LEFT: { movementKeys[ MOVEMENT_KEY_TURN_LEFT ] = false; break; }
271  case SDLK_UP: { movementKeys[ MOVEMENT_KEY_TURN_UP ] = false; break; }
272  case SDLK_DOWN: { movementKeys[ MOVEMENT_KEY_TURN_DOWN ] = false; break; }
273  case SDLK_HOME: { movementKeys[ MOVEMENT_KEY_ZOOM_OUT ] = false; break; }
274  case SDLK_END: { movementKeys[ MOVEMENT_KEY_ZOOM_IN ] = false; break; }
275  case SDLK_ESCAPE: { done = true; break; }
276  default: break;
277  }
278  break;
279  }
280 
281  case SDL_KEYDOWN: {
282 
283  switch( event.key.keysym.sym ) {
284  case SDLK_w: { movementKeys[ MOVEMENT_KEY_MOVE_FORWARD ] = true; break; }
285  case SDLK_s: { movementKeys[ MOVEMENT_KEY_MOVE_BACK ] = true; break; }
286  case SDLK_PAGEDOWN: { movementKeys[ MOVEMENT_KEY_MOVE_DOWN ] = true; break; }
287  case SDLK_PAGEUP: { movementKeys[ MOVEMENT_KEY_MOVE_UP ] = true; break; }
288  case SDLK_d: { movementKeys[ MOVEMENT_KEY_MOVE_RIGHT ] = true; break; }
289  case SDLK_a: { movementKeys[ MOVEMENT_KEY_MOVE_LEFT ] = true; break; }
290  case SDLK_q: { movementKeys[ MOVEMENT_KEY_TURN_COUNTERCLOCKWISE ] = true; break; }
291  case SDLK_e: { movementKeys[ MOVEMENT_KEY_TURN_CLOCKWISE ] = true; break; }
292  case SDLK_RIGHT: { movementKeys[ MOVEMENT_KEY_TURN_RIGHT ] = true; break; }
293  case SDLK_LEFT: { movementKeys[ MOVEMENT_KEY_TURN_LEFT ] = true; break; }
294  case SDLK_UP: { movementKeys[ MOVEMENT_KEY_TURN_UP ] = true; break; }
295  case SDLK_DOWN: { movementKeys[ MOVEMENT_KEY_TURN_DOWN ] = true; break; }
296  case SDLK_HOME: { movementKeys[ MOVEMENT_KEY_ZOOM_OUT ] = true; break; }
297  case SDLK_END: { movementKeys[ MOVEMENT_KEY_ZOOM_IN ] = true; break; }
298  default: break;
299  }
300  break;
301  }
302 
303  case SDL_QUIT: {
304 
305  done = true;
306  break;
307  }
308  }
309  }
310 
311  // ==== update position ====
312 
313  { double const move = ( movementKeys[ MOVEMENT_KEY_MOVE_FORWARD ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_MOVE_BACK ] ? 1.0 : 0.0 );
314  if ( move != 0 ) {
315 
316  double const rate = move * rateMove * deltaSeconds;
317  camera.MoveForward( rate );
318  }
319  }
320  { double const move = ( movementKeys[ MOVEMENT_KEY_MOVE_DOWN ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_MOVE_UP ] ? 1.0 : 0.0 );
321  if ( move != 0 ) {
322 
323  double const rate = move * rateMove * deltaSeconds;
324  camera.MoveDown( rate );
325  }
326  }
327  { double const move = ( movementKeys[ MOVEMENT_KEY_MOVE_RIGHT ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_MOVE_LEFT ] ? 1.0 : 0.0 );
328  if ( move != 0 ) {
329 
330  double const rate = move * rateMove * deltaSeconds;
331  camera.MoveRight( rate );
332  }
333  }
334  { double const turn = ( movementKeys[ MOVEMENT_KEY_TURN_CLOCKWISE ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_TURN_COUNTERCLOCKWISE ] ? 1.0 : 0.0 );
335  if ( turn != 0 ) {
336 
337  double const rate = turn * rateTurn * deltaSeconds;
338  camera.TurnClockwise( rate );
339  }
340  }
341  { double const turn = ( movementKeys[ MOVEMENT_KEY_TURN_RIGHT ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_TURN_LEFT ] ? 1.0 : 0.0 );
342  if ( turn != 0 ) {
343 
344  double const rate = turn * rateTurn * deltaSeconds;
345  camera.TurnRight( rate );
346  }
347  }
348  { double const turn = ( movementKeys[ MOVEMENT_KEY_TURN_DOWN ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_TURN_UP ] ? 1.0 : 0.0 );
349  if ( turn != 0 ) {
350 
351  double const rate = turn * rateTurn * deltaSeconds;
352  camera.TurnDown( rate );
353  }
354  }
355  { double const zoom = ( movementKeys[ MOVEMENT_KEY_ZOOM_OUT ] ? 1.0 : 0.0 ) - ( movementKeys[ MOVEMENT_KEY_ZOOM_IN ] ? 1.0 : 0.0 );
356  if ( zoom != 0 ) {
357 
358  double const rate = zoom * rateZoom * deltaSeconds;
359  camera.ZoomOut( rate );
360  }
361  }
362  }
363  }
364  catch( std::exception& exception ) {
365 
366  std::cerr << "caught exception: " << exception.what() << std::endl;
367  result = EXIT_FAILURE;
368  }
369  catch( ... ) {
370 
371  std::cerr << "caught exception: <unknown error>" << std::endl;
372  result = EXIT_FAILURE;
373  }
374 
375  return result;
376 }