Panda3D
nonlinearImager.cxx
1 // Filename: nonlinearImager.cxx
2 // Created by: drose (12Dec01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "nonlinearImager.h"
16 #include "config_distort.h"
17 
18 #include "graphicsStateGuardian.h"
19 #include "matrixLens.h"
20 #include "graphicsOutput.h"
21 #include "graphicsEngine.h"
22 #include "dcast.h"
23 #include "cPointerCallbackObject.h"
24 #include "asyncTaskManager.h"
25 #include "genericAsyncTask.h"
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: NonlinearImager::Constructor
29 // Access: Published
30 // Description:
31 ////////////////////////////////////////////////////////////////////
32 NonlinearImager::
33 NonlinearImager() {
34  _engine = (GraphicsEngine *)NULL;
35  _stale = true;
36 }
37 
38 ////////////////////////////////////////////////////////////////////
39 // Function: NonlinearImager::Destructor
40 // Access: Published
41 // Description:
42 ////////////////////////////////////////////////////////////////////
43 NonlinearImager::
44 ~NonlinearImager() {
47 
48  if (_recompute_task != (AsyncTask *)NULL) {
50  task_mgr->remove(_recompute_task);
51  }
52 }
53 
54 ////////////////////////////////////////////////////////////////////
55 // Function: NonlinearImager::add_screen
56 // Access: Published
57 // Description: This version of this method is deprecated and will
58 // soon be removed. Use the version that takes two
59 // parameters instead.
60 ////////////////////////////////////////////////////////////////////
63  return add_screen(NodePath(screen), screen->get_name());
64 }
65 
66 ////////////////////////////////////////////////////////////////////
67 // Function: NonlinearImager::add_screen
68 // Access: Published
69 // Description: Adds a new ProjectionScreen to the list of screens
70 // that will be processed by the NonlinearImager. Each
71 // ProjectionScreen represents a view into the world.
72 // It must be based on a linear camera (or whatever kind
73 // of camera is respected by the graphics engine).
74 //
75 // Each ProjectionScreen object should already have some
76 // screen geometry created.
77 //
78 // As each frame is rendered, an offscreen image will be
79 // rendered from the source camera associated with each
80 // ProjectionScreen, and the resulting image will be
81 // applied to the screen geometry.
82 //
83 // The return value is the index number of the new
84 // screen.
85 ////////////////////////////////////////////////////////////////////
87 add_screen(const NodePath &screen, const string &name) {
88  nassertr(!screen.is_empty() &&
89  screen.node()->is_of_type(ProjectionScreen::get_class_type()), -1);
90 
91  ProjectionScreen *screen_node = DCAST(ProjectionScreen, screen.node());
92 
93  _screens.push_back(Screen());
94  Screen &new_screen = _screens.back();
95  new_screen._screen = screen;
96  new_screen._screen_node = screen_node;
97  new_screen._name = name;
98  new_screen._buffer = (GraphicsOutput *)NULL;
99  new_screen._tex_width = 256;
100  new_screen._tex_height = 256;
101  new_screen._active = true;
102 
103  // Slot a mesh for each viewer.
104  size_t vi;
105  for (vi = 0; vi < _viewers.size(); ++vi) {
106  new_screen._meshes.push_back(Mesh());
107  new_screen._meshes[vi]._last_screen = screen_node->get_last_screen();
108  }
109 
110  _stale = true;
111 
112  if (_dark_room.is_empty()) {
113  _dark_room = screen.get_top();
114  } else {
115  nassertr(_dark_room.is_same_graph(screen), _screens.size() - 1);
116  }
117 
118  return _screens.size() - 1;
119 }
120 
121 ////////////////////////////////////////////////////////////////////
122 // Function: NonlinearImager::find_screen
123 // Access: Published
124 // Description: Returns the index number of the first appearance of
125 // the indicated screen within the imager's list, or -1
126 // if it does not appear.
127 ////////////////////////////////////////////////////////////////////
129 find_screen(const NodePath &screen) const {
130  for (size_t i = 0; i < _screens.size(); i++) {
131  if (_screens[i]._screen == screen) {
132  return i;
133  }
134  }
135 
136  return -1;
137 }
138 
139 ////////////////////////////////////////////////////////////////////
140 // Function: NonlinearImager::remove_screen
141 // Access: Published
142 // Description: Removes the screen with the indicated index number
143 // from the imager.
144 ////////////////////////////////////////////////////////////////////
146 remove_screen(int index) {
147  nassertv_always(index >= 0 && index < (int)_screens.size());
148  Screen &screen = _screens[index];
149  for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
150  screen._meshes[vi]._mesh.remove_node();
151  }
152  _screens.erase(_screens.begin() + index);
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: NonlinearImager::remove_all_screens
157 // Access: Published
158 // Description: Removes all screens from the imager.
159 ////////////////////////////////////////////////////////////////////
162  while (!_screens.empty()) {
163  remove_screen(_screens.size() - 1);
164  }
165 }
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: NonlinearImager::get_num_screens
169 // Access: Published
170 // Description: Returns the number of screens that have been added to
171 // the imager.
172 ////////////////////////////////////////////////////////////////////
175  return _screens.size();
176 }
177 
178 ////////////////////////////////////////////////////////////////////
179 // Function: NonlinearImager::get_screen
180 // Access: Published
181 // Description: Returns the nth screen that has been added to the
182 // imager.
183 ////////////////////////////////////////////////////////////////////
185 get_screen(int index) const {
186  nassertr(index >= 0 && index < (int)_screens.size(), NodePath());
187  return _screens[index]._screen;
188 }
189 
190 ////////////////////////////////////////////////////////////////////
191 // Function: NonlinearImager::get_buffer
192 // Access: Published
193 // Description: Returns the offscreen buffer that is automatically
194 // created for the nth projection screen. This may
195 // return NULL if the screen is inactive or if it has
196 // not been rendered yet.
197 ////////////////////////////////////////////////////////////////////
199 get_buffer(int index) const {
200  nassertr(index >= 0 && index < (int)_screens.size(), (GraphicsOutput *)NULL);
201  return _screens[index]._buffer;
202 }
203 
204 ////////////////////////////////////////////////////////////////////
205 // Function: NonlinearImager::set_texture_size
206 // Access: Published
207 // Description: Sets the width and height of the texture used to
208 // render the scene for the indicated screen. This must
209 // be less than or equal to the window size, and it
210 // should be a power of two.
211 //
212 // In general, the larger the texture, the greater the
213 // detail of the rendered scene.
214 ////////////////////////////////////////////////////////////////////
216 set_texture_size(int index, int width, int height) {
217  nassertv(index >= 0 && index < (int)_screens.size());
218 
219  Screen &screen = _screens[index];
220 
221  screen._tex_width = width;
222  screen._tex_height = height;
223 
224  if (screen._buffer != (GraphicsOutput *)NULL) {
225  bool removed = _engine->remove_window(screen._buffer);
226  screen._buffer = (GraphicsOutput *)NULL;
227  nassertv(removed);
228  }
229 
230  _stale = true;
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: NonlinearImager::set_source_camera
235 // Access: Published
236 // Description: Specifies the camera that will be used to render the
237 // image for this particular screen.
238 //
239 // The parameter must be a NodePath whose node is a
240 // Camera. The camera itself indicates the scene that
241 // is to be rendered.
242 ////////////////////////////////////////////////////////////////////
244 set_source_camera(int index, const NodePath &source_camera) {
245  nassertv(index >= 0 && index < (int)_screens.size());
246  nassertv(!source_camera.is_empty() &&
247  source_camera.node()->is_of_type(Camera::get_class_type()));
248  _screens[index]._source_camera = source_camera;
249 }
250 
251 ////////////////////////////////////////////////////////////////////
252 // Function: NonlinearImager::set_screen_active
253 // Access: Published
254 // Description: Sets the active flag on the indicated screen. If the
255 // active flag is true, the screen will be used;
256 // otherwise, it will not appear.
257 ////////////////////////////////////////////////////////////////////
259 set_screen_active(int index, bool active) {
260  nassertv(index >= 0 && index < (int)_screens.size());
261 
262  Screen &screen = _screens[index];
263  screen._active = active;
264 
265  if (!active) {
266  // If we've just made this screen inactive, remove its meshes.
267  for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
268  screen._meshes[vi]._mesh.remove_node();
269  }
270 
271  // Also remove its buffer.
272  if (screen._buffer != (GraphicsOutput *)NULL) {
273  bool removed = _engine->remove_window(screen._buffer);
274  screen._buffer = (GraphicsOutput *)NULL;
275  nassertv(removed);
276  }
277 
278  // Hide the screen in the dark room. This doesn't really matter,
279  // since the dark room isn't normally rendered, but hide it anyway
280  // in case the user stuck a camera in there for fun.
281  screen._screen.hide();
282 
283  } else {
284  // If we've just made it active, it needs to be recomputed.
285  _stale = true;
286 
287  screen._screen.show();
288  }
289 }
290 
291 ////////////////////////////////////////////////////////////////////
292 // Function: NonlinearImager::get_screen_active
293 // Access: Published
294 // Description: Returns the active flag on the indicated screen.
295 ////////////////////////////////////////////////////////////////////
297 get_screen_active(int index) const {
298  nassertr(index >= 0 && index < (int)_screens.size(), false);
299  return _screens[index]._active;
300 }
301 
302 
303 ////////////////////////////////////////////////////////////////////
304 // Function: NonlinearImager::add_viewer
305 // Access: Published
306 // Description: Adds the indicated DisplayRegion as a viewer into the
307 // NonlinearImager room. The camera associated with the
308 // DisplayRegion at the time add_viewer() is called is
309 // used as the initial viewer camera; it may have a
310 // nonlinear lens, like a fisheye or cylindrical lens.
311 //
312 // This sets up a special scene graph for this
313 // DisplayRegion alone and sets up the DisplayRegion
314 // with a specialty camera. If future changes to the
315 // camera are desired, you should use the
316 // set_viewer_camera() interface.
317 //
318 // All viewers must share the same GraphicsEngine.
319 //
320 // The return value is the index of the new viewer.
321 ////////////////////////////////////////////////////////////////////
324  GraphicsOutput *window = dr->get_window();
325  nassertr(window != (GraphicsOutput *)NULL, -1);
326 
327  GraphicsStateGuardian *gsg = window->get_gsg();
328  nassertr(gsg != (GraphicsStateGuardian *)NULL, -1);
329 
330  GraphicsEngine *engine = gsg->get_engine();
331  nassertr(engine != (GraphicsEngine *)NULL, -1);
332 
333  nassertr(_viewers.empty() || (engine == _engine), -1);
334  if (_engine == (GraphicsEngine *)NULL) {
335  _engine = engine;
336  }
337 
338  if (_recompute_task == (AsyncTask *)NULL) {
339  _recompute_task =
340  new GenericAsyncTask("nli_recompute", recompute_callback, (void *)this);
342  task_mgr->add(_recompute_task);
343  }
344 
345  int previous_vi = find_viewer(dr);
346  if (previous_vi >= 0) {
347  return previous_vi;
348  }
349 
350  size_t vi = _viewers.size();
351  _viewers.push_back(Viewer());
352  Viewer &viewer = _viewers[vi];
353 
354  viewer._dr = dr;
355 
356  // Get the current camera off of the DisplayRegion, if any.
357  viewer._viewer = dr->get_camera();
358  if (viewer._viewer.is_empty()) {
359  viewer._viewer_node = (LensNode *)NULL;
360  } else {
361  viewer._viewer_node = DCAST(LensNode, viewer._viewer.node());
362  }
363 
364  // The internal camera is an identity-matrix camera that simply
365  // views the meshes that represent the user's specified camera.
366  viewer._internal_camera = new Camera("internal_camera");
367  viewer._internal_camera->set_lens(new MatrixLens);
368  viewer._internal_scene = NodePath("internal_screens");
369  viewer._internal_camera->set_scene(viewer._internal_scene);
370 
371  NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera);
372  viewer._dr->set_camera(camera_np);
373 
374  // Enable face culling on the wireframe mesh. This will help us to
375  // cull out invalid polygons that result from vertices crossing a
376  // singularity (for instance, at the back of a fisheye lens).
377  viewer._internal_scene.set_two_sided(0);
378 
379  // Finally, slot a new mesh for each screen.
380  Screens::iterator si;
381  for (si = _screens.begin(); si != _screens.end(); ++si) {
382  Screen &screen = (*si);
383  screen._meshes.push_back(Mesh());
384  nassertr(screen._meshes.size() == _viewers.size(), -1);
385  }
386 
387  _stale = true;
388 
389  if (_dark_room.is_empty()) {
390  _dark_room = viewer._viewer.get_top();
391  } else {
392  nassertr(_dark_room.is_same_graph(viewer._viewer), vi);
393  }
394 
395  return vi;
396 }
397 
398 ////////////////////////////////////////////////////////////////////
399 // Function: NonlinearImager::find_viewer
400 // Access: Published
401 // Description: Returns the index number of the indicated
402 // DisplayRegion within the list of viewers, or -1 if it
403 // is not found.
404 ////////////////////////////////////////////////////////////////////
407  for (size_t vi = 0; vi < _viewers.size(); vi++) {
408  if (_viewers[vi]._dr == dr) {
409  return vi;
410  }
411  }
412 
413  return -1;
414 }
415 
416 ////////////////////////////////////////////////////////////////////
417 // Function: NonlinearImager::remove_viewer
418 // Access: Published
419 // Description: Removes the viewer with the indicated index number
420 // from the imager.
421 ////////////////////////////////////////////////////////////////////
423 remove_viewer(int index) {
424  nassertv_always(index >= 0 && index < (int)_viewers.size());
425  Viewer &viewer = _viewers[index];
426  viewer._internal_camera->set_scene(NodePath());
427  viewer._dr->set_camera(viewer._viewer);
428 
429  // Also remove the corresponding mesh from each screen.
430  Screens::iterator si;
431  for (si = _screens.begin(); si != _screens.end(); ++si) {
432  Screen &screen = (*si);
433  nassertv(index < (int)screen._meshes.size());
434  screen._meshes[index]._mesh.remove_node();
435  screen._meshes.erase(screen._meshes.begin() + index);
436  }
437 
438  _viewers.erase(_viewers.begin() + index);
439 }
440 
441 ////////////////////////////////////////////////////////////////////
442 // Function: NonlinearImager::remove_all_viewers
443 // Access: Published
444 // Description: Removes all viewers from the imager.
445 ////////////////////////////////////////////////////////////////////
448  while (!_viewers.empty()) {
449  remove_viewer(_viewers.size() - 1);
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////
454 // Function: NonlinearImager::set_viewer_camera
455 // Access: Published
456 // Description: Specifies the LensNode that is to serve as the
457 // viewer for this screen. The relative position of
458 // the LensNode to the NonlinearImager, as well as the
459 // properties of the lens associated with the LensNode,
460 // determines the UV's that will be assigned to the
461 // geometry within the NonlinearImager.
462 //
463 // It is not necessary to call this except to change the
464 // camera after a viewer has been added, since the
465 // default is to use whatever camera is associated with
466 // the DisplayRegion at the time the viewer is added.
467 //
468 // The NodePath must refer to a LensNode (or a Camera).
469 ////////////////////////////////////////////////////////////////////
471 set_viewer_camera(int index, const NodePath &viewer_camera) {
472  nassertv(index >= 0 && index < (int)_viewers.size());
473  nassertv(!viewer_camera.is_empty() &&
474  viewer_camera.node()->is_of_type(LensNode::get_class_type()));
475  Viewer &viewer = _viewers[index];
476  viewer._viewer = viewer_camera;
477  viewer._viewer_node = DCAST(LensNode, viewer_camera.node());
478  _stale = true;
479 
480  if (_dark_room.is_empty()) {
481  _dark_room = viewer._viewer.get_top();
482  } else {
483  nassertv(_dark_room.is_same_graph(viewer._viewer));
484  }
485 }
486 
487 ////////////////////////////////////////////////////////////////////
488 // Function: NonlinearImager::get_viewer_camera
489 // Access: Published
490 // Description: Returns the NodePath to the LensNode that is to serve
491 // as nth viewer for this screen.
492 ////////////////////////////////////////////////////////////////////
494 get_viewer_camera(int index) const {
495  nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
496  return _viewers[index]._viewer;
497 }
498 
499 ////////////////////////////////////////////////////////////////////
500 // Function: NonlinearImager::get_viewer_scene
501 // Access: Published
502 // Description: Returns a pointer to the root node of the internal
503 // scene graph for the nth viewer, which is used to
504 // render all of the screen meshes for this viewer.
505 //
506 // This is the scene graph in which the screen meshes
507 // within the dark room have been flattened into the
508 // appropriate transformation according to the viewer's
509 // lens properties (and position relative to the
510 // screens). It is this scene graph that is finally
511 // rendered to the window.
512 ////////////////////////////////////////////////////////////////////
514 get_viewer_scene(int index) const {
515  nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
516  return _viewers[index]._internal_scene;
517 }
518 
519 ////////////////////////////////////////////////////////////////////
520 // Function: NonlinearImager::get_num_viewers
521 // Access: Published
522 // Description: Returns the number of viewers that have been added to
523 // the imager.
524 ////////////////////////////////////////////////////////////////////
527  return _viewers.size();
528 }
529 
530 ////////////////////////////////////////////////////////////////////
531 // Function: NonlinearImager::get_viewer
532 // Access: Published
533 // Description: Returns the nth viewer's DisplayRegion that has been
534 // added to the imager.
535 ////////////////////////////////////////////////////////////////////
537 get_viewer(int index) const {
538  nassertr(index >= 0 && index < (int)_viewers.size(), (DisplayRegion *)NULL);
539  return _viewers[index]._dr;
540 }
541 
542 ////////////////////////////////////////////////////////////////////
543 // Function: NonlinearImager::get_dark_room
544 // Access: Published
545 // Description: Returns the NodePath to the root of the dark room
546 // scene. This is the scene in which all of the
547 // ProjectionScreens and the viewer cameras reside.
548 // It's a standalone scene with a few projection screens
549 // arranged artfully around one or more viewers; it's so
550 // named because it's a little virtual theater.
551 //
552 // Normally this scene is not rendered directly; it only
553 // exists as an abstract concept, and to define the
554 // relation between the ProjectionScreens and the
555 // viewers. But it may be rendered to help visualize
556 // the NonlinearImager's behavior.
557 ////////////////////////////////////////////////////////////////////
559 get_dark_room() const {
560  return _dark_room;
561 }
562 
563 ////////////////////////////////////////////////////////////////////
564 // Function: NonlinearImager::get_graphics_engine
565 // Access: Published
566 // Description: Returns the GraphicsEngine that all of the viewers
567 // added to the NonlinearImager have in common.
568 ////////////////////////////////////////////////////////////////////
571  return _engine;
572 }
573 
574 ////////////////////////////////////////////////////////////////////
575 // Function: NonlinearImager::recompute
576 // Access: Published
577 // Description: Forces a regeneration of all the mesh objects, etc.
578 ////////////////////////////////////////////////////////////////////
581  size_t vi;
582  for (vi = 0; vi < _viewers.size(); ++vi) {
583  Viewer &viewer = _viewers[vi];
584 
585  Screens::iterator si;
586  for (si = _screens.begin(); si != _screens.end(); ++si) {
587  Screen &screen = (*si);
588  if (screen._active) {
589  recompute_screen(screen, vi);
590  }
591  }
592 
593  if (viewer._viewer_node != (LensNode *)NULL &&
594  viewer._viewer_node->get_lens() != (Lens *)NULL) {
595  viewer._viewer_lens_change =
596  viewer._viewer_node->get_lens()->get_last_change();
597  }
598  }
599 
600  _stale = false;
601 }
602 
603 ////////////////////////////////////////////////////////////////////
604 // Function: NonlinearImager::recompute_callback
605 // Access: Private, Static
606 // Description: This function is added as a task, to ensure that all
607 // frames are up-to-date.
608 ////////////////////////////////////////////////////////////////////
609 AsyncTask::DoneStatus NonlinearImager::
611  NonlinearImager *self = (NonlinearImager *)data;
612  self->recompute_if_stale();
613  return AsyncTask::DS_cont;
614 }
615 
616 ////////////////////////////////////////////////////////////////////
617 // Function: NonlinearImager::recompute_if_stale
618 // Access: Private
619 // Description: Calls recompute() if it needs to be called.
620 ////////////////////////////////////////////////////////////////////
623  if (_stale) {
624  recompute();
625  } else {
626  size_t vi;
627  for (vi = 0; vi < _viewers.size(); ++vi) {
628  Viewer &viewer = _viewers[vi];
629  if (viewer._viewer_node != (LensNode *)NULL) {
630  UpdateSeq lens_change =
631  viewer._viewer_node->get_lens()->get_last_change();
632  if (lens_change != viewer._viewer_lens_change) {
633  // The viewer has changed, so we need to recompute all screens
634  // on this viewer.
635  Screens::iterator si;
636  for (si = _screens.begin(); si != _screens.end(); ++si) {
637  Screen &screen = (*si);
638  if (screen._active) {
639  recompute_screen(screen, vi);
640  }
641  }
642 
643  } else {
644  // We may not need to recompute all screens, but maybe some of
645  // them.
646  Screens::iterator si;
647  for (si = _screens.begin(); si != _screens.end(); ++si) {
648  Screen &screen = (*si);
649  if (screen._active &&
650  screen._meshes[vi]._last_screen != screen._screen_node->get_last_screen()) {
651  recompute_screen(screen, vi);
652  } else {
653  screen._screen_node->recompute_if_stale(screen._screen);
654  }
655  }
656  }
657  }
658  }
659  }
660 }
661 
662 ////////////////////////////////////////////////////////////////////
663 // Function: NonlinearImager::recompute_screen
664 // Access: Private
665 // Description: Regenerates the mesh objects just for the indicated
666 // screen.
667 ////////////////////////////////////////////////////////////////////
668 void NonlinearImager::
669 recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
670  nassertv(vi < screen._meshes.size());
671  screen._meshes[vi]._mesh.remove_node();
672  if (!screen._active) {
673  return;
674  }
675 
676  screen._screen_node->recompute_if_stale(screen._screen);
677 
678  Viewer &viewer = _viewers[vi];
679  PT(PandaNode) mesh =
680  screen._screen_node->make_flat_mesh(screen._screen, viewer._viewer);
681  if (mesh != (PandaNode *)NULL) {
682  screen._meshes[vi]._mesh = viewer._internal_scene.attach_new_node(mesh);
683  }
684 
685  if (screen._buffer == (GraphicsOutput *)NULL) {
686  GraphicsOutput *win = viewer._dr->get_window();
687  GraphicsOutput *buffer = win->make_texture_buffer
688  (screen._name, screen._tex_width, screen._tex_height, NULL, false);
689 
690  if (buffer != (GraphicsOutput *)NULL) {
691  screen._buffer = buffer;
692  DisplayRegion *dr = buffer->make_display_region();
693  dr->set_camera(screen._source_camera);
694 
695  } else {
696  screen._meshes[vi]._mesh.clear_texture();
697  }
698  }
699 
700  if (screen._buffer != (GraphicsOutput *)NULL) {
701  screen._meshes[vi]._mesh.set_texture(screen._buffer->get_texture());
702 
703  // We don't really need to set the texture on the dark room
704  // screen, since that's normally not rendered, but we do anyway
705  // just for debugging purposes (in case the user does try to
706  // render it, to see what's going on).
707  screen._screen.set_texture(screen._buffer->get_texture());
708  }
709 
710  screen._meshes[vi]._last_screen = screen._screen_node->get_last_screen();
711 }
void set_texture_size(int index, int width, int height)
Sets the width and height of the texture used to render the scene for the indicated screen...
NodePath get_screen(int index) const
Returns the nth screen that has been added to the imager.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
bool remove(AsyncTask *task)
Removes the indicated task from the active queue.
bool get_screen_active(int index) const
Returns the active flag on the indicated screen.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:45
A completely generic linear lens.
Definition: matrixLens.h:31
void recompute()
Forces a regeneration of all the mesh objects, etc.
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
void remove_all_screens()
Removes all screens from the imager.
A node that contains a Lens.
Definition: lensNode.h:32
NodePath get_camera(Thread *current_thread=Thread::get_current_thread()) const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
void remove_all_viewers()
Removes all viewers from the imager.
int find_screen(const NodePath &screen) const
Returns the index number of the first appearance of the indicated screen within the imager&#39;s list...
GraphicsOutput * get_buffer(int index) const
Returns the offscreen buffer that is automatically created for the nth projection screen...
static AsyncTask::DoneStatus recompute_callback(GenericAsyncTask *task, void *data)
This function is added as a task, to ensure that all frames are up-to-date.
void recompute_if_stale()
Calls recompute() if it needs to be called.
void set_viewer_camera(int index, const NodePath &viewer_camera)
Specifies the LensNode that is to serve as the viewer for this screen.
NodePath get_viewer_camera(int index) const
Returns the NodePath to the LensNode that is to serve as nth viewer for this screen.
void set_screen_active(int index, bool active)
Sets the active flag on the indicated screen.
DisplayRegion * make_display_region()
Creates a new DisplayRegion that covers the entire window.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
This class object combines the rendered output of a 3-d from one or more linear (e.g.
void add(AsyncTask *task)
Adds the indicated task to the active queue.
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:723
int add_viewer(DisplayRegion *dr)
Adds the indicated DisplayRegion as a viewer into the NonlinearImager room.
DisplayRegion * get_viewer(int index) const
Returns the nth viewer&#39;s DisplayRegion that has been added to the imager.
int get_num_screens() const
Returns the number of screens that have been added to the imager.
int add_screen(ProjectionScreen *screen)
This version of this method is deprecated and will soon be removed.
Associates a generic C-style function pointer with an AsyncTask object.
A ProjectionScreen implements a simple system for projective texturing.
int find_viewer(DisplayRegion *dr) const
Returns the index number of the indicated DisplayRegion within the list of viewers, or -1 if it is not found.
NodePath get_viewer_scene(int index) const
Returns a pointer to the root node of the internal scene graph for the nth viewer, which is used to render all of the screen meshes for this viewer.
This is a base class for the various different classes that represent the result of a frame of render...
NodePath get_dark_room() const
Returns the NodePath to the root of the dark room scene.
bool is_same_graph(const NodePath &other, Thread *current_thread=Thread::get_current_thread()) const
Returns true if the node represented by this NodePath is parented within the same graph as that of th...
Definition: nodePath.I:344
void remove_screen(int index)
Removes the screen with the indicated index number from the imager.
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:43
virtual void set_camera(const NodePath &camera)
Sets the camera that is associated with this DisplayRegion.
GraphicsStateGuardian * get_gsg() const
Returns the GSG that is associated with this window.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:284
Encapsulates all the communication with a particular instance of a given rendering backend...
void remove_viewer(int index)
Removes the viewer with the indicated index number from the imager.
NodePath get_top(Thread *current_thread=Thread::get_current_thread()) const
Returns a singleton NodePath that represents the top of the path, or empty NodePath if this path is e...
Definition: nodePath.cxx:317
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:61
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
This class is the main interface to controlling the render process.
void set_source_camera(int index, const NodePath &source_camera)
Specifies the camera that will be used to render the image for this particular screen.
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:37
int get_num_viewers() const
Returns the number of viewers that have been added to the imager.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
void set_two_sided(bool two_sided, int priority=0)
Specifically sets or disables two-sided rendering mode on this particular node.
Definition: nodePath.cxx:5135
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
GraphicsEngine * get_graphics_engine() const
Returns the GraphicsEngine that all of the viewers added to the NonlinearImager have in common...