canvas.cc
Go to the documentation of this file.
1 
13 #include "stage.hh"
14 #include "canvas.hh"
15 #include "worldfile.hh"
16 #include "texture_manager.hh"
17 #include "replace.h"
18 
19 #include <string>
20 #include <sstream>
21 #include <png.h>
22 #include <algorithm>
23 #include <functional> // For greater<int>( )
24 
25 #include "region.hh"
26 #include "file_manager.hh"
27 #include "options_dlg.hh"
28 
29 using namespace Stg;
30 
31 static const int checkImageWidth = 2;
32 static const int checkImageHeight = 2;
34 static bool blur = true;
35 
36 static bool init_done = false;
37 static bool texture_load_done = false;
38 
39 //GLuint glowTex;
40 GLuint checkTex;
41 
43 {
44  if( c->world->dirty )
45  {
46  //puts( "timer redraw" );
47  c->redraw();
48  c->world->dirty = false;
49  }
50 
51  Fl::repeat_timeout( c->interval/1000.0,
52  (Fl_Timeout_Handler)Canvas::TimerCallback,
53  c);
54 }
55 
57  int x, int y,
58  int width, int height) :
59  Fl_Gl_Window( x, y, width, height ),
60  colorstack(),
61  models_sorted(),
62  current_camera( NULL ),
63  camera(),
65  dirty_buffer( false ),
66  wf( NULL ),
67  startx( -1 ),
68  starty( -1 ),
70  last_selection( NULL ),
71  interval( 40 ), // msec between redraws
72  // initialize Option objects
73  // showBlinken( "Blinkenlights", "show_blinkenlights", "", true, world ),
74  showBBoxes( "Debug/Bounding boxes", "show_boundingboxes", "^b", false, world ),
75  showBlocks( "Blocks", "show_blocks", "b", true, world ),
76  showBlur( "Trails/Blur", "show_trailblur", "^d", false, world ),
77  showClock( "Clock", "show_clock", "c", true, world ),
78  showData( "Data", "show_data", "d", false, world ),
79  showFlags( "Flags", "show_flags", "l", true, world ),
80  showFollow( "Follow", "show_follow", "f", false, world ),
81  showFootprints( "Footprints", "show_footprints", "o", false, world ),
82  showGrid( "Grid", "show_grid", "g", true, world ),
83  showOccupancy( "Debug/Occupancy", "show_occupancy", "^o", false, world ),
84  showScreenshots( "Save screenshots", "screenshots", "", false, world ),
85  showStatus( "Status", "show_status", "s", true, world ),
86  showTrailArrows( "Trails/Rising Arrows", "show_trailarrows", "^a", false, world ),
87  showTrailRise( "Trails/Rising blocks", "show_trailrise", "^r", false, world ),
88  showTrails( "Trails/Fast", "show_trailfast", "^f", false, world ),
89  showVoxels( "Debug/Voxels", "show_voxels", "^v", false, world ),
90  pCamOn( "Perspective camera", "pcam_on", "r", false, world ),
91  visualizeAll( "Selected only", "vis_all", "v", false, world ),
92  // and the rest
93  graphics( true ),
94  world( world ),
97 {
98  end();
99  //show(); // must do this so that the GL context is created before configuring GL
100  // but that line causes a segfault in Linux/X11! TODO: test in OS X
101 
102  perspective_camera.setPose( 0.0, -4.0, 3.0 );
104  setDirtyBuffer();
105 
106  // enable accumulation buffer
107  //mode( mode() | FL_ACCUM );
108  //assert( can_do( FL_ACCUM ) );
109 }
110 
112 {
113  valid(1);
114  FixViewport(w(), h());
115 
116  // set gl state that won't change every redraw
117  glClearColor ( 0.7, 0.7, 0.8, 1.0);
118  glDisable( GL_LIGHTING );
119  glEnable( GL_DEPTH_TEST );
120  glDepthFunc( GL_LESS );
121  // culling disables text drawing on OS X, so I've disabled it until I understand why
122  //glCullFace( GL_BACK );
123  //glEnable (GL_CULL_FACE);
124  glEnable( GL_BLEND );
125  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
126  glEnable( GL_LINE_SMOOTH );
127  glHint( GL_LINE_SMOOTH_HINT, GL_FASTEST );
128  glDepthMask( GL_TRUE );
129  glEnable( GL_TEXTURE_2D );
130  glEnableClientState( GL_VERTEX_ARRAY );
131  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
132 
133  // install a font
134  gl_font( FL_HELVETICA, 12 );
135 
136  blur = false;
137 
138  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
139 
140  init_done = true;
141 }
142 
143 
145 {
146  // load textures
147  std::string fullpath = FileManager::findFile( "assets/stall.png" );
148  if ( fullpath == "" )
149  {
150  PRINT_DEBUG( "Unable to load stall texture.\n" );
151  }
152 
153  //printf( "stall icon %s\n", fullpath.c_str() );
154 
155  GLuint stall_id = TextureManager::getInstance().loadTexture( fullpath.c_str() );
157 
158  fullpath = FileManager::findFile( "assets/mainspower.png" );
159  if ( fullpath == "" )
160  {
161  PRINT_DEBUG( "Unable to load mains texture.\n" );
162  }
163 
164  // printf( "mains icon %s\n", fullpath.c_str() );
165 
166  GLuint mains_id = TextureManager::getInstance().loadTexture( fullpath.c_str() );
168 
169  // // generate a small glow texture
170  // GLubyte* pixels = new GLubyte[ 4 * 128 * 128 ];
171 
172  // for( int x=0; x<128; x++ )
173  // for( int y=0; y<128; y++ )
174  // {
175  // GLubyte* p = &pixels[ 4 * (128*y + x)];
176  // p[0] = (GLubyte)255; // red
177  // p[1] = (GLubyte)0; // green
178  // p[2] = (GLubyte)0; // blue
179  // p[3] = (GLubyte)128; // alpha
180  // }
181 
182 
183  // glGenTextures(1, &glowTex );
184  // glBindTexture( GL_TEXTURE_2D, glowTex );
185 
186  // glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0,
187  // GL_RGBA, GL_UNSIGNED_BYTE, pixels );
188 
189  // delete[] pixels;
190 
191  // draw a check into a bitmap, then load that into a texture
192  int i, j;
193  for (i = 0; i < checkImageHeight; i++)
194  for (j = 0; j < checkImageWidth; j++)
195  {
196  int even = (i+j)%2;
197  checkImage[i][j][0] = (GLubyte) 255 - 10*even;
198  checkImage[i][j][1] = (GLubyte) 255 - 10*even;
199  checkImage[i][j][2] = (GLubyte) 255;// - 5*even;
200  checkImage[i][j][3] = 255;
201  }
202 
203  glGenTextures(1, &checkTex );
204  glBindTexture(GL_TEXTURE_2D, checkTex);
205 
206  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
207  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
208  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
209  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
210 
211  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight,
212  0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage);
213 
214  texture_load_done = true;
215 }
216 
217 
219 {
220  // nothing to do
221 }
222 
223 Model* Canvas::getModel( int x, int y )
224 {
225  // render all models in a unique color
226  make_current(); // make sure the GL context is current
227  glClearColor( 1,1,1,1 ); // white
228  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
229  glLoadIdentity();
231  current_camera->Draw();
232 
233  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
234  glDisable(GL_DITHER);
235  glDisable(GL_BLEND); // turns off alpha blending, so we read back
236  // exactly what we write to a pixel
237 
238  // render all top-level, draggable models in a color that is their
239  // id
240  FOR_EACH( it, world->World::children )
241  {
242  Model* mod = (*it);
243 
244  if( mod->gui.move )
245  {
246  uint8_t rByte, gByte, bByte, aByte;
247  uint32_t modelId = mod->id;
248  rByte = modelId;
249  gByte = modelId >> 8;
250  bByte = modelId >> 16;
251  aByte = modelId >> 24;
252 
253  //printf("mod->Id(): 0x%X, rByte: 0x%X, gByte: 0x%X, bByte: 0x%X, aByte: 0x%X\n", modelId, rByte, gByte, bByte, aByte);
254 
255  glColor4ub( rByte, gByte, bByte, aByte );
256  mod->DrawPicker();
257  }
258  }
259 
260  glFlush(); // make sure the drawing is done
261 
262  // read the color of the pixel in the back buffer under the mouse
263  // pointer
264  GLint viewport[4];
265  glGetIntegerv(GL_VIEWPORT,viewport);
266 
267  uint8_t rgbaByte[4];
268  uint32_t modelId;
269 
270  glReadPixels( x,viewport[3]-y,1,1,
271  GL_RGBA,GL_UNSIGNED_BYTE,&rgbaByte[0] );
272 
273  modelId = rgbaByte[0];
274  modelId |= rgbaByte[1] << 8;
275  modelId |= rgbaByte[2] << 16;
276  //modelId |= rgbaByte[3] << 24;
277 
278  // printf("Clicked rByte: 0x%X, gByte: 0x%X, bByte: 0x%X, aByte: 0x%X\n", rgbaByte[0], rgbaByte[1], rgbaByte[2], rgbaByte[3]);
279  // printf("-->model Id = 0x%X\n", modelId);
280 
281  Model* mod = Model::LookupId( modelId );
282 
283  //printf("%p %s %d %x\n", mod, mod ? mod->Token() : "(none)", modelId, modelId );
284 
285  // put things back the way we found them
286  glEnable(GL_DITHER);
287  glEnable(GL_BLEND);
288  glClearColor ( 0.7, 0.7, 0.8, 1.0);
289 
290  // useful for debugging the picker
291  //Screenshot();
292 
293  return mod;
294 }
295 
296 bool Canvas::selected( Model* mod )
297 {
298  return( std::find( selected_models.begin(), selected_models.end(), mod ) != selected_models.end() );
299 }
300 
301 void Canvas::select( Model* mod ) {
302  if( mod )
303  {
304  last_selection = mod;
305  selected_models.push_front( mod );
306 
307  // mod->Disable();
308  redraw();
309  }
310 }
311 
312 void Canvas::unSelect( Model* mod )
313 {
314  if( mod )
315  {
316  EraseAll( mod, selected_models );
317  redraw();
318  }
319 }
320 
322 {
323  selected_models.clear();
324 }
325 
326 // convert from 2d window pixel to 3d world coordinates
327 void Canvas::CanvasToWorld( int px, int py,
328  double *wx, double *wy, double* wz )
329 {
330  if( px <= 0 )
331  px = 1;
332  else if( px >= w() )
333  px = w() - 1;
334  if( py <= 0 )
335  py = 1;
336  else if( py >= h() )
337  py = h() - 1;
338 
339  //redraw the screen only if the camera model isn't active.
340  //TODO new selection technique will simply use drawfloor to result in z = 0 always and prevent strange behaviours near walls
341  //TODO refactor, so glReadPixels reads (then caches) the whole screen only when the camera changes.
342  if( true || dirtyBuffer() ) {
343  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
345  current_camera->Draw();
346  DrawFloor(); //call this rather than renderFrame for speed - this won't give correct z values
347  dirty_buffer = false;
348  }
349 
350  int viewport[4];
351  glGetIntegerv(GL_VIEWPORT, viewport);
352 
353  GLdouble modelview[16];
354  glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
355 
356  GLdouble projection[16];
357  glGetDoublev(GL_PROJECTION_MATRIX, projection);
358 
359  GLfloat pz;
360  glReadPixels( px, h()-py, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pz );
361  gluUnProject( px, w()-py, pz, modelview, projection, viewport, wx,wy,wz );
362 }
363 
364 int Canvas::handle(int event)
365 {
366  //printf( "cam %.2f %.2f\n", camera.yaw(), camera.pitch() );
367 
368  switch(event)
369  {
370  case FL_MOUSEWHEEL:
371  if( pCamOn == true ) {
372  perspective_camera.scroll( Fl::event_dy() / 10.0 );
373  }
374  else {
375  camera.scale( Fl::event_dy(), Fl::event_x(), w(), Fl::event_y(), h() );
376  }
377  invalidate();
378  redraw();
379  return 1;
380 
381  case FL_MOVE: // moused moved while no button was pressed
382  if( Fl::event_state( FL_META ) )
383  {
384  puts( "TODO: HANDLE HISTORY" );
385  //world->paused = ! world->paused;
386  return 1;
387  }
388 
389  if ( startx >=0 )
390  {
391  // mouse pointing to valid value
392 
393  if( Fl::event_state( FL_CTRL ) ) // rotate the camera view
394  {
395  int dx = Fl::event_x() - startx;
396  int dy = Fl::event_y() - starty;
397 
398  if( pCamOn == true ) {
399  perspective_camera.addYaw( -dx );
401  }
402  else {
403  camera.addPitch( - 0.5 * static_cast<double>( dy ) );
404  camera.addYaw( - 0.5 * static_cast<double>( dx ) );
405  }
406  invalidate();
407  redraw();
408  }
409  else if( Fl::event_state( FL_ALT ) )
410  {
411  int dx = Fl::event_x() - startx;
412  int dy = Fl::event_y() - starty;
413 
414  if( pCamOn == true ) {
415  perspective_camera.move( -dx, dy, 0.0 );
416  }
417  else {
418  camera.move( -dx, dy );
419  }
420  invalidate();
421  }
422  }
423  startx = Fl::event_x();
424  starty = Fl::event_y();
425  return 1;
426  case FL_PUSH: // button pressed
427  {
428  //else
429  {
430  Model* mod = getModel( startx, starty );
431  startx = Fl::event_x();
432  starty = Fl::event_y();
433  selectedModel = false;
434  switch( Fl::event_button() )
435  {
436  case 1:
437  clicked_empty_space = ( mod == NULL );
440  if( mod ) {
441  // clicked a model
442  if ( Fl::event_state( FL_SHIFT ) ) {
443  // holding shift, toggle selection
444  if ( selected( mod ) )
445  unSelect( mod );
446  else {
447  select( mod );
448  selectedModel = true; // selected a model
449  }
450  }
451  else {
452  if ( !selected( mod ) ) {
453  // clicked on an unselected model while
454  // not holding shift, this is the new
455  // selection
456  unSelectAll();
457  select( mod );
458  }
459  selectedModel = true; // selected a model
460  }
461  }
462 
463  redraw(); // probably required
464  return 1;
465  case 3:
466  {
467  // leave selections alone
468  // rotating handled within FL_DRAG
469  return 1;
470  }
471  default:
472  return 0;
473  }
474  }
475  }
476 
477  case FL_DRAG: // mouse moved while button was pressed
478  {
479  int dx = Fl::event_x() - startx;
480  int dy = Fl::event_y() - starty;
481 
482  if ( Fl::event_state( FL_BUTTON1 ) && Fl::event_state( FL_CTRL ) == false ) {
483  // Left mouse button drag
484  if ( selectedModel ) {
485  // started dragging on a selected model
486 
487  double sx,sy,sz;
489  &sx, &sy, &sz );
490  double x,y,z;
491  CanvasToWorld( Fl::event_x(), Fl::event_y(),
492  &x, &y, &z );
493  // move all selected models to the mouse pointer
495  {
496  Model* mod = *it;
497  mod->AddToPose( x-sx, y-sy, 0, 0 );
498  }
499  }
500  else {
501  // started dragging on empty space or an
502  // unselected model, move the canvas
503  if( pCamOn == true ) {
504  perspective_camera.move( -dx, dy, 0.0 );
505  }
506  else {
507  camera.move( -dx, dy );
508  }
509  invalidate(); // so the projection gets updated
510  }
511  }
512  else if ( Fl::event_state( FL_BUTTON3 ) || ( Fl::event_state( FL_BUTTON1 ) && Fl::event_state( FL_CTRL ) ) ) {
513  // rotate all selected models
514 
515  if( selected_models.size() )
516  {
518  {
519  Model* mod = *it;
520  mod->AddToPose( 0,0,0, 0.05*(dx+dy) );
521  }
522  }
523  else
524  {
525  //printf( "button 2\n" );
526 
527  int dx = Fl::event_x() - startx;
528  int dy = Fl::event_y() - starty;
529 
530  if( pCamOn == true ) {
531  perspective_camera.addYaw( -dx );
533  }
534  else {
535  camera.addPitch( - 0.5 * static_cast<double>( dy ) );
536  camera.addYaw( - 0.5 * static_cast<double>( dx ) );
537  }
538  }
539  invalidate();
540  redraw();
541  }
542 
543  startx = Fl::event_x();
544  starty = Fl::event_y();
545 
546  redraw();
547  return 1;
548  } // end case FL_DRAG
549 
550  case FL_RELEASE: // mouse button released
551  if( empty_space_startx == Fl::event_x() && empty_space_starty == Fl::event_y() && clicked_empty_space == true ) {
552  // clicked on empty space, unselect all
553  unSelectAll();
554  redraw();
555  }
556  return 1;
557 
558  case FL_FOCUS:
559  case FL_UNFOCUS:
560  //.... Return 1 if you want keyboard events, 0 otherwise
561  return 1;
562 
563  case FL_KEYBOARD:
564  switch( Fl::event_key() )
565  {
566  case FL_Left:
567  if( pCamOn == false ) { camera.move( -10, 0 ); }
568  else { perspective_camera.strafe( -0.5 ); } break;
569  case FL_Right:
570  if( pCamOn == false ) {camera.move( 10, 0 ); }
571  else { perspective_camera.strafe( 0.5 ); } break;
572  case FL_Down:
573  if( pCamOn == false ) {camera.move( 0, -10 ); }
574  else { perspective_camera.forward( -0.5 ); } break;
575  case FL_Up:
576  if( pCamOn == false ) {camera.move( 0, 10 ); }
577  else { perspective_camera.forward( 0.5 ); } break;
578  default:
579  redraw(); // we probably set a display config - so need this
580  return 0; // keypress unhandled
581  }
582 
583  invalidate(); // update projection
584  return 1;
585 
586  // case FL_SHORTCUT:
587  // //... shortcut, key is in Fl::event_key(), ascii in Fl::event_text()
588  // //... Return 1 if you understand/use the shortcut event, 0 otherwise...
589  // return 1;
590  default:
591  // pass other events to the base class...
592  //printf( "EVENT %d\n", event );
593  return Fl_Gl_Window::handle(event);
594 
595  } // end switch( event )
596 
597  return 0;
598 }
599 
600 void Canvas::FixViewport(int W,int H)
601 {
602  glLoadIdentity();
603  glViewport(0,0,W,H);
604 }
605 
607 {
608  models_sorted.push_back( mod );
609  redraw();
610 }
611 
613 {
614  printf( "removing model %s from canvas list\n", mod->Token() );
615  EraseAll( mod, models_sorted );
616 }
617 
619 {
620  bounds3d_t bounds = world->GetExtent();
621 
622  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
623 
624  glEnable(GL_POLYGON_OFFSET_FILL);
625  glPolygonOffset(2.0, 2.0);
626  glDisable(GL_BLEND);
627 
628  glEnable(GL_TEXTURE_2D);
629  glBindTexture(GL_TEXTURE_2D, checkTex );
630  glColor3f( 1.0, 1.0, 1.0 );
631 
632  glBegin(GL_QUADS);
633  glTexCoord2f( bounds.x.min/2.0, bounds.y.min/2.0 );
634  glVertex2f( bounds.x.min, bounds.y.min );
635  glTexCoord2f( bounds.x.max/2.0, bounds.y.min/2.0);
636  glVertex2f( bounds.x.max, bounds.y.min );
637  glTexCoord2f( bounds.x.max/2.0, bounds.y.max/2.0 );
638  glVertex2f( bounds.x.max, bounds.y.max );
639  glTexCoord2f( bounds.x.min/2.0, bounds.y.max/2.0 );
640  glVertex2f( bounds.x.min, bounds.y.max );
641  glEnd();
642 
643  glDisable(GL_TEXTURE_2D);
644  glEnable(GL_BLEND);
645 
646  glDisable(GL_POLYGON_OFFSET_FILL );
647 
648 
649  /* printf( "bounds [%.2f %.2f] [%.2f %.2f] [%.2f %.2f]\n",
650  bounds.x.min, bounds.x.max,
651  bounds.y.min, bounds.y.max,
652  bounds.z.min, bounds.z.max );
653 
654  */
655 
656  /* simple scaling of axis labels - could be better */
657  int skip = (int)( 50 / camera.scale());
658  if( skip < 1 ) skip = 1;
659  if( skip > 2 && skip % 2 ) skip += 1;
660 
661  //printf( "scale %.4f\n", camera.scale() );
662 
663  char str[64];
664  PushColor( 0.2, 0.2, 0.2, 1.0 ); // pale gray
665 
666  for( double i=0; i < bounds.x.max; i+=skip)
667  {
668  snprintf( str, 16, "%d", (int)i );
669  Gl::draw_string( i, 0, 0, str );
670  }
671 
672  for( double i=0; i >= bounds.x.min; i-=skip)
673  {
674  snprintf( str, 16, "%d", (int)i );
675  Gl::draw_string( i, 0, 0, str );
676  }
677 
678 
679  for( double i=0; i < bounds.y.max; i+=skip)
680  {
681  snprintf( str, 16, "%d", (int)i );
682  Gl::draw_string( 0, i, 0, str );
683  }
684 
685  for( double i=0; i >= bounds.y.min; i-=skip)
686  {
687  snprintf( str, 16, "%d", (int)i );
688  Gl::draw_string( 0, i, 0, str );
689  }
690 
691 
692  PopColor();
693 
694 }
695 
696 //draw the floor without any grid ( for robot's perspective camera model )
698 {
699  bounds3d_t bounds = world->GetExtent();
700 
701  glEnable(GL_POLYGON_OFFSET_FILL);
702  glPolygonOffset(2.0, 2.0);
703 
704  glColor4f( 1.0, 1.0, 1.0, 1.0 );
705 
706  glBegin(GL_QUADS);
707  glVertex2f( bounds.x.min, bounds.y.min );
708  glVertex2f( bounds.x.max, bounds.y.min );
709  glVertex2f( bounds.x.max, bounds.y.max );
710  glVertex2f( bounds.x.min, bounds.y.max );
711  glEnd();
712 }
713 
715 {
716  FOR_EACH( it, models_sorted )
717  (*it)->DrawBlocksTree();
718 }
719 
721 {
722  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
723  glLineWidth( 2.0 );
724  glPointSize( 5.0 );
725  glDisable (GL_CULL_FACE);
726 
728 
729  glEnable (GL_CULL_FACE);
730  glLineWidth( 1.0 );
731  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
732 }
733 
735 {
736  float max_x = 0, max_y = 0, min_x = 0, min_y = 0;
737 
738  //TODO take orrientation ( `a' ) and geom.pose offset into consideration
739  FOR_EACH( it, world->World::children )
740  {
741  Model* ptr = (*it);
742  Pose pose = ptr->GetPose();
743  Geom geom = ptr->GetGeom();
744 
745  float tmp_min_x = pose.x - geom.size.x / 2.0;
746  float tmp_max_x = pose.x + geom.size.x / 2.0;
747  float tmp_min_y = pose.y - geom.size.y / 2.0;
748  float tmp_max_y = pose.y + geom.size.y / 2.0;
749 
750  if( tmp_min_x < min_x ) min_x = tmp_min_x;
751  if( tmp_max_x > max_x ) max_x = tmp_max_x;
752  if( tmp_min_y < min_y ) min_y = tmp_min_y;
753  if( tmp_max_y > max_y ) max_y = tmp_max_y;
754  }
755 
756  //do a complete reset
757  float x = ( min_x + max_x ) / 2.0;
758  float y = ( min_y + max_y ) / 2.0;
759  camera.setPose( x, y );
760  float scale_x = w() / (max_x - min_x) * 0.9;
761  float scale_y = h() / (max_y - min_y) * 0.9;
762  camera.setScale( scale_x < scale_y ? scale_x : scale_y );
763 
764  //TODO reset perspective cam
765 }
766 
767 
769 {
772  : x(x), y(y) {}
773 
774  bool operator()(const Model* a, const Model* b ) const
775  {
776  const Pose a_pose = a->GetGlobalPose();
777  const Pose b_pose = b->GetGlobalPose();
778 
779  const meters_t a_dist = hypot( y - a_pose.y, x - a_pose.x );
780  const meters_t b_dist = hypot( y - b_pose.y, x - b_pose.x );
781 
782  return ( a_dist < b_dist );
783  }
784 };
785 
786 
788 {
789  //before drawing, order all models based on distance from camera
790  //float x = current_camera->x();
791  //float y = current_camera->y();
792  //float sphi = -dtor( current_camera->yaw() );
793 
794  //estimate point of camera location - hard to do with orthogonal mode
795  // x += -sin( sphi ) * 100;
796  //y += -cos( sphi ) * 100;
797 
798  //double coords[2];
799  //coords[0] = x;
800  //coords[1] = y;
801 
802  // sort the list of models by inverse distance from the camera -
803  // probably doesn't change too much between frames so this is
804  // usually fast
805  // TODO
806  //models_sorted = g_list_sort_with_data( models_sorted, (GCompareDataFunc)compare_distance, coords );
807 
808  // TODO: understand why this doesn't work and fix it - cosmetic but important!
809  //std::sort( models_sorted.begin(), models_sorted.end(), DistFuncObj(x,y) );
810 
811  glEnable( GL_DEPTH_TEST );
812 
813  if( ! showTrails )
814  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
815 
816  if( showOccupancy )
817  ((WorldGui*)world)->DrawOccupancy();
818 
819  if( showVoxels )
820  ((WorldGui*)world)->DrawVoxels();
821 
822 
823  if( ! world->rt_cells.empty() )
824  {
825  glPushMatrix();
826  GLfloat scale = 1.0/world->Resolution();
827  glScalef( scale, scale, 1.0 ); // XX TODO - this seems slightly
828 
829  world->PushColor( Color( 0,0,1,0.5) );
830 
831  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
832 
833  glPointSize( 2 );
834  glBegin( GL_POINTS );
835 
836  for( unsigned int i=0;
837  i < world->rt_cells.size();
838  i++ )
839  {
840  char str[128];
841  snprintf( str, 128, "(%d,%d)",
842  world->rt_cells[i].x,
843  world->rt_cells[i].y );
844 
845  Gl::draw_string( world->rt_cells[i].x+1,
846  world->rt_cells[i].y+1, 0.1, str );
847 
848  //printf( "x: %d y: %d\n", world->rt_regions[i].x, world->rt_regions[i].y );
849  //glRectf( world->rt_cells[i].x+0.3, world->rt_cells[i].y+0.3,
850  // world->rt_cells[i].x+0.7, world->rt_cells[i].y+0.7 );
851 
852  glVertex2f( world->rt_cells[i].x, world->rt_cells[i].y );
853 
854  }
855 
856  glEnd();
857 
858 #if 1
859  world->PushColor( Color( 0,1,0,0.2) );
860  glBegin( GL_LINE_STRIP );
861  for( unsigned int i=0;
862  i < world->rt_cells.size();
863  i++ )
864  {
865  glVertex2f( world->rt_cells[i].x+0.5, world->rt_cells[i].y+0.5 );
866  }
867  glEnd();
868  world->PopColor();
869 #endif
870 
871  glPopMatrix();
872  world->PopColor();
873  }
874 
875  if( ! world->rt_candidate_cells.empty() )
876  {
877  glPushMatrix();
878  GLfloat scale = 1.0/world->Resolution();
879  glScalef( scale, scale, 1.0 ); // XX TODO - this seems slightly
880 
881  world->PushColor( Color( 1,0,0,0.5) );
882 
883  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
884 
885  for( unsigned int i=0;
886  i < world->rt_candidate_cells.size();
887  i++ )
888  {
889  // char str[128];
890  // snprintf( str, 128, "(%d,%d)",
891  // world->rt_candidate_cells[i].x,
892  // world->rt_candidate_cells[i].y );
893 
894  // Gl::draw_string( world->rt_candidate_cells[i].x+1,
895  // world->rt_candidate_cells[i].y+1, 0.1, str );
896 
897  //printf( "x: %d y: %d\n", world->rt_regions[i].x, world->rt_regions[i].y );
898  glRectf( world->rt_candidate_cells[i].x, world->rt_candidate_cells[i].y,
899  world->rt_candidate_cells[i].x+1, world->rt_candidate_cells[i].y+1 );
900  }
901 
902  world->PushColor( Color( 0,1,0,0.2) );
903  glBegin( GL_LINE_STRIP );
904  for( unsigned int i=0;
905  i < world->rt_candidate_cells.size();
906  i++ )
907  {
908  glVertex2f( world->rt_candidate_cells[i].x+0.5, world->rt_candidate_cells[i].y+0.5 );
909  }
910  glEnd();
911  world->PopColor();
912 
913  glPopMatrix();
914  world->PopColor();
915 
916  //world->rt_cells.clear();
917  }
918 
919  if( showGrid )
920  DrawGlobalGrid();
921  else
922  DrawFloor();
923 
924  if( showFootprints )
925  {
926  glDisable( GL_DEPTH_TEST ); // using alpha blending
927 
928  FOR_EACH( it, models_sorted )
929  (*it)->DrawTrailFootprint();
930 
931  glEnable( GL_DEPTH_TEST );
932  }
933 
934  if( showFlags )
935  {
936  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
937  glBegin( GL_TRIANGLES );
938 
939  FOR_EACH( it, models_sorted )
940  (*it)->DrawFlagList();
941 
942  glEnd();
943  }
944 
945  if( showTrailArrows )
946  FOR_EACH( it, models_sorted )
947  (*it)->DrawTrailArrows();
948 
949  if( showTrailRise )
950  FOR_EACH( it, models_sorted )
951  (*it)->DrawTrailBlocks();
952 
953  if( showBlocks )
954  DrawBlocks();
955 
956  if( showBBoxes )
958 
959  // TODO - finish this properly
960  //LISTMETHOD( models_sorted, Model*, DrawWaypoints );
961 
963  (*it)->DrawSelected();
964 
965  // useful debug - puts a point at the origin of each model
966  //for( GList* it = world->World::children; it; it=it->next )
967  // ((Model*)it->data)->DrawOriginTree();
968 
969  // draw the model-specific visualizations
970  if( world->sim_time > 0 )
971  {
972  if( showData ) {
973  if ( ! visualizeAll ) {
974  FOR_EACH( it, world->World::children )
975  (*it)->DataVisualizeTree( current_camera );
976  }
977  else if ( selected_models.size() > 0 ) {
979  (*it)->DataVisualizeTree( current_camera );
980  }
981  else if ( last_selection ) {
983  }
984  }
985  }
986 
987  if( showGrid )
988  FOR_EACH( it, models_sorted )
989  (*it)->DrawGrid();
990 
991  if( showStatus )
992  {
993  glPushMatrix();
994  //ensure two icons can't be in the exact same plane
995  if( camera.pitch() == 0 && !pCamOn )
996  glTranslatef( 0, 0, 0.1 );
997 
998  FOR_EACH( it, models_sorted )
999  (*it)->DrawStatusTree( &camera );
1000 
1001  glPopMatrix();
1002  }
1003 
1004  if( world->ray_list.size() > 0 )
1005  {
1006  glDisable( GL_DEPTH_TEST );
1007  PushColor( 0,0,0,0.5 );
1008  FOR_EACH( it, world->ray_list )
1009  {
1010  float* pts = *it;
1011  glBegin( GL_LINES );
1012  glVertex2f( pts[0], pts[1] );
1013  glVertex2f( pts[2], pts[3] );
1014  glEnd();
1015  }
1016  PopColor();
1017  glEnable( GL_DEPTH_TEST );
1018 
1019  world->ClearRays();
1020  }
1021 
1022  if( showClock )
1023  {
1024  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
1025 
1026  //use orthogonal projeciton without any zoom
1027  glMatrixMode (GL_PROJECTION);
1028  glPushMatrix(); //save old projection
1029  glLoadIdentity ();
1030  glOrtho( 0, w(), 0, h(), -100, 100 );
1031  glMatrixMode (GL_MODELVIEW);
1032 
1033  glPushMatrix();
1034  glLoadIdentity();
1035  glDisable( GL_DEPTH_TEST );
1036 
1037  std::string clockstr = world->ClockString();
1038  if( showFollow == true && last_selection )
1039  clockstr.append( " [FOLLOW MODE]" );
1040 
1041  float txtWidth = gl_width( clockstr.c_str());
1042  if( txtWidth < 200 ) txtWidth = 200;
1043  int txtHeight = gl_height();
1044 
1045  const int margin = 5;
1046  int width, height;
1047  width = txtWidth + 2 * margin;
1048  height = txtHeight + 2 * margin;
1049 
1050  // TIME BOX
1051  colorstack.Push( 0.8,0.8,1.0 ); // pale blue
1052  glRectf( 0, 0, width, height );
1053  colorstack.Push( 0,0,0 ); // black
1054  Gl::draw_string( margin, margin, 0, clockstr.c_str() );
1055  colorstack.Pop();
1056  colorstack.Pop();
1057 
1058  // ENERGY BOX
1059  if( PowerPack::global_capacity > 0 )
1060  {
1061  colorstack.Push( 0.8,1.0,0.8,0.85 ); // pale green
1062  glRectf( 0, height, width, 90 );
1063  colorstack.Push( 0,0,0 ); // black
1064  Gl::draw_string_multiline( margin, height + margin, width, 50,
1065  world->EnergyString().c_str(),
1066  (Fl_Align)( FL_ALIGN_LEFT | FL_ALIGN_BOTTOM) );
1067  colorstack.Pop();
1068  colorstack.Pop();
1069  }
1070 
1071  glEnable( GL_DEPTH_TEST );
1072  glPopMatrix();
1073 
1074  //restore camera projection
1075  glMatrixMode (GL_PROJECTION);
1076  glPopMatrix();
1077  glMatrixMode (GL_MODELVIEW);
1078  }
1079 
1081  Screenshot();
1082 
1084 }
1085 
1086 
1088 {
1089  //use orthogonal projection without any zoom
1090  glMatrixMode (GL_PROJECTION);
1091  glPushMatrix(); //save old projection
1092  glLoadIdentity ();
1093  glOrtho( 0, w(), 0, h(), -100, 100 );
1094  glMatrixMode (GL_MODELVIEW);
1095 
1096  glPushMatrix();
1097  glLoadIdentity();
1098  glDisable( GL_DEPTH_TEST );
1099 }
1100 
1102 {
1103  glEnable( GL_DEPTH_TEST );
1104  glPopMatrix();
1105  glMatrixMode (GL_PROJECTION);
1106  glPopMatrix();
1107  glMatrixMode (GL_MODELVIEW);
1108 }
1109 
1110 
1112 {
1113 
1114  int width = w();
1115  int height = h();
1116  int depth = 4; // RGBA
1117 
1118  // we use RGBA throughout, though we only need RGB, as the 4-byte
1119  // pixels avoid a nasty word-alignment problem when indexing into
1120  // the pixel array.
1121 
1122  // might save a bit of time with a static var as the image size rarely changes
1123  static std::vector<uint8_t> pixels;
1124  pixels.resize( width * height * depth );
1125 
1126  glFlush(); // make sure the drawing is done
1127  // read the pixels from the screen
1128  glReadPixels( 0,0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0] );
1129 
1130  static uint32_t count = 0;
1131  char filename[64];
1132  snprintf( filename, 63, "stage-%06d.png", count++ );
1133 
1134  FILE *fp = fopen( filename, "wb" );
1135  if( fp == NULL )
1136  {
1137  PRINT_ERR1( "Unable to open %s", filename );
1138  }
1139 
1140  // create PNG data
1141  png_structp pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
1142  assert(pp);
1143  png_infop info = png_create_info_struct(pp);
1144  assert(info);
1145 
1146  // setup the output file
1147  png_init_io(pp, fp);
1148 
1149  // need to invert the image as GL and PNG disagree on the row order
1150  png_bytep rowpointers[height];
1151  for( int i=0; i<height; i++ )
1152  rowpointers[i] = &pixels[ (height-1-i) * width * depth ];
1153 
1154  png_set_rows( pp, info, rowpointers );
1155 
1156  png_set_IHDR( pp, info,
1157  width, height, 8,
1158  PNG_COLOR_TYPE_RGBA,
1159  PNG_INTERLACE_NONE,
1160  PNG_COMPRESSION_TYPE_DEFAULT,
1161  PNG_FILTER_TYPE_DEFAULT);
1162 
1163  png_write_png( pp, info, PNG_TRANSFORM_IDENTITY, NULL );
1164 
1165  // free the PNG data - we reuse the pixel array next call.
1166  png_destroy_write_struct(&pp, &info);
1167 
1168  fclose(fp);
1169 
1170  printf( "Saved %s\n", filename );
1171 }
1172 
1173 void Canvas::perspectiveCb( Fl_Widget* w, void* p )
1174 {
1175  Canvas* canvas = static_cast<Canvas*>( w );
1176  Option* opt = static_cast<Option*>( p ); // pCamOn
1177  if ( opt ) {
1178  // Perspective mode is on, change camera
1179  canvas->current_camera = &canvas->perspective_camera;
1180  }
1181  else {
1182  canvas->current_camera = &canvas->camera;
1183  }
1184 
1185  canvas->invalidate();
1186 }
1187 
1188 void Canvas::createMenuItems( Fl_Menu_Bar* menu, std::string path )
1189 {
1190  showData.createMenuItem( menu, path );
1191  // visualizeAll.createMenuItem( menu, path );
1192  showBlocks.createMenuItem( menu, path );
1193  showFlags.createMenuItem( menu, path );
1194  showClock.createMenuItem( menu, path );
1195  showFlags.createMenuItem( menu, path );
1196  showFollow.createMenuItem( menu, path );
1197  showFootprints.createMenuItem( menu, path );
1198  showGrid.createMenuItem( menu, path );
1199  showStatus.createMenuItem( menu, path );
1200  pCamOn.createMenuItem( menu, path );
1202  showOccupancy.createMenuItem( menu, path );
1203  showTrailArrows.createMenuItem( menu, path );
1204  showTrails.createMenuItem( menu, path );
1205  showTrailRise.createMenuItem( menu, path ); // broken
1206  showBBoxes.createMenuItem( menu, path );
1207  //showVoxels.createMenuItem( menu, path );
1208  showScreenshots.createMenuItem( menu, path );
1209 }
1210 
1211 
1212 void Canvas::Load( Worldfile* wf, int sec )
1213 {
1214  this->wf = wf;
1215  camera.Load( wf, sec );
1216  perspective_camera.Load( wf, sec );
1217 
1218  interval = wf->ReadInt(sec, "interval", interval );
1219 
1220  screenshot_frame_skip = wf->ReadInt( sec, "screenshot_skip", screenshot_frame_skip );
1221  if( screenshot_frame_skip < 1 )
1222  screenshot_frame_skip = 1; // avoids div-by-zero if poorly set
1223 
1224  showData.Load( wf, sec );
1225  showFlags.Load( wf, sec );
1226  showBlocks.Load( wf, sec );
1227  showBBoxes.Load( wf, sec );
1228  showBlur.Load( wf, sec );
1229  showClock.Load( wf, sec );
1230  showFollow.Load( wf, sec );
1231  showFootprints.Load( wf, sec );
1232  showGrid.Load( wf, sec );
1233  showOccupancy.Load( wf, sec );
1234  showTrailArrows.Load( wf, sec );
1235  showTrailRise.Load( wf, sec );
1236  showTrails.Load( wf, sec );
1237  //showVoxels.Load( wf, sec );
1238  showScreenshots.Load( wf, sec );
1239  pCamOn.Load( wf, sec );
1240 
1241  if( ! world->paused )
1242  // // start the timer that causes regular redraws
1243  Fl::add_timeout( ((double)interval/1000),
1244  (Fl_Timeout_Handler)Canvas::TimerCallback,
1245  this);
1246 
1247  invalidate(); // we probably changed something
1248 }
1249 
1250 void Canvas::Save( Worldfile* wf, int sec )
1251 {
1252  camera.Save( wf, sec );
1253  perspective_camera.Save( wf, sec );
1254 
1255  wf->WriteInt(sec, "interval", interval );
1256 
1257  showData.Save( wf, sec );
1258  showBlocks.Save( wf, sec );
1259  showBBoxes.Save( wf, sec );
1260  showBlur.Save( wf, sec );
1261  showClock.Save( wf, sec );
1262  showFlags.Save( wf, sec );
1263  showFollow.Save( wf, sec );
1264  showFootprints.Save( wf, sec );
1265  showGrid.Save( wf, sec );
1266  showOccupancy.Save( wf, sec );
1267  showTrailArrows.Save( wf, sec );
1268  showTrailRise.Save( wf, sec );
1269  showTrails.Save( wf, sec );
1270  showVoxels.Save( wf, sec );
1271  showScreenshots.Save( wf, sec );
1272  pCamOn.Save( wf, sec );
1273 }
1274 
1275 
1277 {
1278  //Enable the following to debug camera model
1279  // if( loaded_texture == true && pCamOn == true )
1280  // return;
1281 
1282  if (!valid() )
1283  {
1284  if( ! init_done )
1285  InitGl();
1286  if( ! texture_load_done )
1287  InitTextures();
1288 
1289  if( pCamOn == true )
1290  {
1291  perspective_camera.setAspect( static_cast< float >( w() ) / static_cast< float >( h() ) );
1294  }
1295  else
1296  {
1297  bounds3d_t extent = world->GetExtent();
1298  camera.SetProjection( w(), h(), extent.y.min, extent.y.max );
1300  }
1301 
1302  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1303  }
1304 
1305  //Follow the selected robot
1306  if( showFollow && last_selection )
1307  {
1308  Pose gpose = last_selection->GetGlobalPose();
1309  if( pCamOn == true )
1310  {
1311  perspective_camera.setPose( gpose.x, gpose.y, 0.2 );
1312  perspective_camera.setYaw( rtod( gpose.a ) - 90.0 );
1313  }
1314  else
1315  {
1316  camera.setPose( gpose.x, gpose.y );
1317  }
1318  }
1319 
1320  current_camera->Draw();
1321  renderFrame();
1322 }
1323 
1324 void Canvas::resize(int X,int Y,int W,int H)
1325 {
1326  Fl_Gl_Window::resize(X,Y,W,H);
1327 
1328  if( ! init_done ) // hack - should capture a create event to do this rather thann have it in multiple places
1329  InitGl();
1330 
1331  FixViewport(W,H);
1332  invalidate();
1333 }
void redraw(int val)
Model class
Definition: stage.hh:1742
int starty
Definition: canvas.hh:62
GLuint checkTex
Definition: canvas.cc:40
float scale
Definition: make_rsn.c:26
Bounds y
volume extent along y axis, initially zero
Definition: stage.hh:453
bool selectedModel
Definition: canvas.hh:63
GLuint loadTexture(const char *filename)
load a texture on the GPU, returned value is the texture ID, or 0 for failure
void Save(Worldfile *wf, int sec)
Definition: camera.cc:98
virtual void Draw(void) const =0
Option showClock
Definition: canvas.hh:81
WorldGui * world
Definition: canvas.hh:105
double max
largest value in range, initially zero
Definition: stage.hh:435
OrthoCamera camera
Definition: canvas.hh:57
The Stage library uses its own namespace.
Definition: canvas.hh:8
static const int checkImageWidth
Definition: canvas.cc:31
void InitTextures()
Definition: canvas.cc:144
void select(Model *mod)
Definition: canvas.cc:301
void setPose(double x, double y)
Definition: stage.hh:1483
std::list< Model * > models_sorted
Definition: canvas.hh:54
meters_t x
Definition: stage.hh:228
void EnterScreenCS()
Definition: canvas.cc:1087
static bool texture_load_done
Definition: canvas.cc:37
void setDirtyBuffer(void)
Definition: canvas.hh:135
static joules_t global_capacity
Definition: stage.hh:1685
virtual void DrawPicker()
Definition: model_draw.cc:612
Option showScreenshots
Definition: canvas.hh:81
void DrawFloor()
Definition: canvas.cc:697
Option showStatus
Definition: canvas.hh:81
void AddToPose(const Pose &pose)
Definition: model.cc:782
void DrawGlobalGrid()
Definition: canvas.cc:618
void Load(Worldfile *wf, int sec)
Definition: camera.cc:92
void forward(double amount)
Definition: camera.cc:86
static TextureManager & getInstance(void)
void EraseAll(T thing, C &cont)
Definition: stage.hh:621
double min
smallest value in range, initially zero
Definition: stage.hh:433
void setYaw(double yaw)
Definition: stage.hh:1418
virtual int handle(int event)
Definition: canvas.cc:364
Size size
extent
Definition: stage.hh:395
bool dirty_buffer
Definition: canvas.hh:59
uint32_t id
Definition: stage.hh:1901
void createMenuItems(Fl_Menu_Bar *menu, std::string path)
Definition: canvas.cc:1188
Model * last_selection
Definition: canvas.hh:67
void DrawBoundingBoxes()
Definition: canvas.cc:720
void draw_string_multiline(float x, float y, float w, float h, const char *string, Fl_Align align)
Definition: gl.cc:77
void setPose(double x, double y, double z)
Definition: stage.hh:1412
Canvas(WorldGui *world, int x, int y, int width, int height)
Definition: canvas.cc:56
PerspectiveCamera perspective_camera
Definition: canvas.hh:58
void DrawBlocks()
Definition: canvas.cc:714
bool graphics
Definition: canvas.hh:104
Option visualizeAll
Definition: canvas.hh:81
void resetCamera()
Definition: canvas.cc:734
void DataVisualizeTree(Camera *cam)
Definition: model_draw.cc:632
void PushColor(Color col)
Definition: canvas.hh:138
void Save(Worldfile *wf, int sec)
Definition: camera.cc:213
meters_t y
Definition: stage.hh:251
void Save(Worldfile *wf, int section)
Definition: option.cc:39
Camera * current_camera
Definition: canvas.hh:56
void WriteInt(int entity, const char *name, int value)
Definition: worldfile.cc:1409
void scale(double scale, double shift_x=0, double h=0, double shift_y=0, double w=0)
Definition: camera.cc:168
static GLubyte checkImage[checkImageHeight][checkImageWidth][4]
Definition: canvas.cc:33
void Screenshot()
Definition: canvas.cc:1111
void FixViewport(int W, int H)
Definition: canvas.cc:600
int screenshot_frame_skip
Definition: canvas.hh:107
void CanvasToWorld(int px, int py, double *wx, double *wy, double *wz)
Definition: canvas.cc:327
void addYaw(double yaw)
Definition: stage.hh:1472
Option showTrailRise
Definition: canvas.hh:81
Option showFootprints
Definition: canvas.hh:81
Pose GetGlobalPose() const
Definition: model.cc:1379
double rtod(double r)
Definition: stage.hh:148
bool operator()(const Model *a, const Model *b) const
Definition: canvas.cc:774
void addPitch(double pitch)
Definition: stage.hh:1474
virtual void SetProjection(double pixels_width, double pixels_height, double y_min, double y_max)
Definition: camera.cc:135
const bounds3d_t & GetExtent() const
Definition: stage.hh:1181
void unSelectAll()
Definition: canvas.cc:321
void createMenuItem(Fl_Menu_Bar *menu, std::string path)
Definition: option.cc:58
static bool blur
Definition: canvas.cc:34
double meters_t
Definition: stage.hh:174
void RemoveModel(Model *mod)
Definition: canvas.cc:612
meters_t y
Definition: stage.hh:228
virtual void draw()
Definition: canvas.cc:1276
int empty_space_starty
Definition: canvas.hh:65
Option showBBoxes
Definition: canvas.hh:81
int startx
Definition: canvas.hh:62
void addPitch(double pitch)
Definition: stage.hh:1423
bool dirtyBuffer(void) const
Definition: canvas.hh:136
DistFuncObj(meters_t x, meters_t y)
Definition: canvas.cc:771
Worldfile * wf
Definition: canvas.hh:60
virtual void SetProjection(void) const =0
void draw_string(float x, float y, float z, const char *string)
Definition: gl.cc:65
static Model * LookupId(uint32_t id)
Definition: stage.hh:2206
Bounds x
volume extent along x axis, intially zero
Definition: stage.hh:451
void LeaveScreenCS()
Definition: canvas.cc:1101
Option showTrails
Definition: canvas.hh:81
static std::string findFile(const std::string &filename)
Definition: file_manager.cc:36
void menuCallback(Fl_Callback *cb, Fl_Widget *w)
Definition: option.cc:53
bool paused
if true, the simulation is stopped
Definition: stage.hh:921
Option showFollow
Definition: canvas.hh:81
virtual void SetProjection(void) const
Definition: camera.cc:54
Option showBlur
Definition: canvas.hh:81
void Push(double r, double g, double b, double a=1.0)
Definition: canvas.hh:23
double pitch(void) const
Definition: stage.hh:1379
Model * getModel(int x, int y)
Definition: canvas.cc:223
void strafe(double amount)
Definition: camera.cc:80
void AddModel(Model *mod)
Definition: canvas.cc:606
Option showData
Definition: canvas.hh:81
void setScale(double scale)
Definition: stage.hh:1482
void PopColor()
Definition: canvas.hh:144
static void perspectiveCb(Fl_Widget *w, void *p)
Definition: canvas.cc:1173
void Save(Worldfile *wf, int section)
Definition: canvas.cc:1250
static const int checkImageHeight
Definition: canvas.cc:32
void scroll(double dy)
Definition: stage.hh:1428
Option showTrailArrows
Definition: canvas.hh:81
Option showGrid
Definition: canvas.hh:81
void Load(Worldfile *wf, int section)
Definition: option.cc:33
#define PRINT_ERR1(m, a)
Definition: stage.hh:626
void addYaw(double yaw)
Definition: stage.hh:1421
std::list< Model * > selected_models
Definition: canvas.hh:66
meters_t y
Definition: canvas.cc:770
void Load(Worldfile *wf, int sec)
Definition: camera.cc:206
void DrawBoundingBoxTree()
Definition: worldgui.cc:851
void Load(Worldfile *wf, int section)
Definition: canvas.cc:1212
Option showFlags
Definition: canvas.hh:81
Option showBlocks
Definition: canvas.hh:81
int ReadInt(int entity, const char *name, int value)
Definition: worldfile.cc:1398
#define FOR_EACH(I, C)
Definition: stage.hh:616
void InitGl()
Definition: canvas.cc:111
Pose GetPose() const
Definition: stage.hh:2382
class Stg::Model::GuiState gui
radians_t a
rotation about the z axis.
Definition: stage.hh:252
unsigned long frames_rendered_count
Definition: canvas.hh:106
#define PRINT_DEBUG(m)
Definition: stage.hh:666
void setAspect(double aspect)
update vertical fov based on window aspect and current horizontal fov
Definition: stage.hh:1417
Option showVoxels
Definition: canvas.hh:81
Option pCamOn
Definition: canvas.hh:81
void move(double x, double y, double z)
Definition: camera.cc:26
msec_t interval
(even if it is now unselected).
Definition: canvas.hh:70
class Stg::Canvas::GlColorStack colorstack
static bool init_done
Definition: canvas.cc:36
void move(double x, double y)
Definition: camera.cc:144
bool selected(Model *mod)
Definition: canvas.cc:296
void resize(int X, int Y, int W, int H)
Definition: canvas.cc:1324
virtual void renderFrame()
Definition: canvas.cc:787
meters_t x
Definition: stage.hh:251
Option showOccupancy
Definition: canvas.hh:81
const char * Token() const
Definition: stage.hh:715
static void TimerCallback(Canvas *canvas)
Definition: canvas.cc:42
bool clicked_empty_space
Definition: canvas.hh:64
void unSelect(Model *mod)
Definition: canvas.cc:312
Geom GetGeom() const
Definition: stage.hh:2378
int empty_space_startx
Definition: canvas.hh:65


stage
Author(s): Richard Vaughan , Brian Gerkey , Reed Hedges , Andrew Howard , Toby Collett , Pooya Karimian , Jeremy Asher , Alex Couture-Beil , Geoff Biggs , Rich Mattes , Abbas Sadat
autogenerated on Mon Jun 10 2019 15:06:09