Panda3D
 All Classes Functions Variables Enumerations
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.
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.
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_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
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
void remove_all_viewers()
Removes all viewers from the imager.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:284
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_dark_room() const
Returns the NodePath to the root of the dark room scene.
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.
NodePath get_viewer_camera(int index) const
Returns the NodePath to the LensNode that is to serve as nth viewer for this screen.
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.
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...
This class object combines the rendered output of a 3-d from one or more linear (e.g.
int get_num_screens() const
Returns the number of screens that have been added to the imager.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
void add(AsyncTask *task)
Adds the indicated task to the active queue.
int add_viewer(DisplayRegion *dr)
Adds the indicated DisplayRegion as a viewer into the NonlinearImager room.
GraphicsEngine * get_graphics_engine() const
Returns the GraphicsEngine that all of the viewers added to the NonlinearImager have in common...
bool get_screen_active(int index) const
Returns the active flag on the indicated screen.
int add_screen(ProjectionScreen *screen)
This version of this method is deprecated and will soon be removed.
GraphicsStateGuardian * get_gsg() const
Returns the GSG that is associated with this window.
Associates a generic C-style function pointer with an AsyncTask object.
A ProjectionScreen implements a simple system for projective texturing.
This is a base class for the various different classes that represent the result of a frame of render...
GraphicsOutput * get_buffer(int index) const
Returns the offscreen buffer that is automatically created for the nth projection screen...
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.
int get_num_viewers() const
Returns the number of viewers that have been added to the imager.
GraphicsOutput * make_texture_buffer(const string &name, int x_size, int y_size, Texture *tex=NULL, bool to_ram=false, FrameBufferProperties *fbp=NULL)
Creates and returns an offscreen buffer for rendering into, the result of which will be a texture sui...
Encapsulates all the communication with a particular instance of a given rendering backend...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
void remove_viewer(int index)
Removes the viewer with the indicated index number from the imager.
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:61
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
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 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.
DisplayRegion * get_viewer(int index) const
Returns the nth viewer&#39;s DisplayRegion that has been added to the imager.
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
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
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 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...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
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