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


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 Feb 28 2022 23:48:55