Panda3D
pview.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pview.cxx
10  * @author drose
11  * @date 2002-02-25
12  */
13 
14 #include "pandaFramework.h"
15 #include "pandaSystem.h"
16 #include "textNode.h"
17 #include "configVariableBool.h"
18 #include "texturePool.h"
19 #include "multitexReducer.h"
20 #include "sceneGraphReducer.h"
21 #include "partGroup.h"
22 #include "cardMaker.h"
23 #include "bamCache.h"
24 #include "virtualFileSystem.h"
25 #include "panda_getopt.h"
26 #include "preprocess_argv.h"
27 #include "graphicsPipeSelection.h"
28 #include "asyncTaskManager.h"
29 #include "asyncTask.h"
30 #include "boundingSphere.h"
31 
32 using std::cerr;
33 using std::endl;
34 
35 PandaFramework framework;
36 
37 ConfigVariableBool pview_test_hack
38 ("pview-test-hack", false,
39  "Enable the '0' key in pview to run whatever hacky test happens to be in "
40  "there right now.");
41 
42 bool
43 output_screenshot(Filename &fn)
44 {
45  Thread *current_thread = Thread::get_current_thread();
46 
47  // Only one frame crashes.
48  framework.do_frame(current_thread);
49  framework.do_frame(current_thread);
50 
51  WindowFramework *wf = framework.get_window(0);
52  bool ok = wf->get_graphics_output()->save_screenshot(fn, "from pview");
53  if (!ok) {
54  cerr << "Could not generate screenshot " << fn << "\n";
55  }
56  return ok;
57 }
58 
59 void
60 event_W(const Event *, void *) {
61  // shift-W: open a new window on the same scene.
62 
63  // If we already have a window, use the same GSG.
64  GraphicsPipe *pipe = nullptr;
65  GraphicsStateGuardian *gsg = nullptr;
66 
67  if (framework.get_num_windows() > 0) {
68  WindowFramework *old_window = framework.get_window(0);
69  GraphicsOutput *win = old_window->get_graphics_output();
70  pipe = win->get_pipe();
71  // gsg = win->get_gsg();
72  }
73 
74  WindowFramework *window = framework.open_window(pipe, gsg);
75  if (window != nullptr) {
76  window->enable_keyboard();
77  window->setup_trackball();
78  framework.get_models().instance_to(window->get_render());
79  }
80 }
81 
82 void
83 event_F(const Event *, void *) {
84  // shift-F: flatten the model hierarchy.
85  framework.get_models().flatten_strong();
86 }
87 
88 void
89 event_Enter(const Event *, void *) {
90  // alt-enter: toggle between windowfullscreen in the same scene.
91 
92  // If we already have a window, use the same GSG.
93  GraphicsPipe *pipe = nullptr;
94  GraphicsStateGuardian *gsg = nullptr;
95 
96  WindowProperties props;
97 
98  for (int i = 0; i < framework.get_num_windows(); ++i) {
99  WindowFramework *old_window = framework.get_window(i);
100  GraphicsWindow *win = old_window->get_graphics_window();
101  if (win != nullptr) {
102  pipe = win->get_pipe();
103  gsg = win->get_gsg();
104  props = win->get_properties();
105  framework.close_window(old_window);
106  break;
107  }
108  }
109 
110  // set the toggle
111  props.set_fullscreen(!props.get_fullscreen());
112  int flags = GraphicsPipe::BF_require_window;
113 
114  WindowFramework *window = framework.open_window(props, flags, pipe, gsg);
115  if (window != nullptr) {
116  window->enable_keyboard();
117  window->setup_trackball();
118  framework.get_models().instance_to(window->get_render());
119  }
120 }
121 
122 void
123 event_2(const Event *event, void *) {
124  // 2: split the window into two display regions.
125 
126  EventParameter param = event->get_parameter(0);
127  WindowFramework *wf;
128  DCAST_INTO_V(wf, param.get_ptr());
129 
130  WindowFramework *split = wf->split_window();
131  if (split != nullptr) {
132  split->enable_keyboard();
133  split->setup_trackball();
134  framework.get_models().instance_to(split->get_render());
135  }
136 }
137 
138 void
139 event_0(const Event *event, void *) {
140  // 0: run hacky test.
141  EventParameter param = event->get_parameter(0);
142  WindowFramework *wf;
143  DCAST_INTO_V(wf, param.get_ptr());
144 
145  // Create a new offscreen buffer.
146  GraphicsOutput *win = wf->get_graphics_output();
147  PT(GraphicsOutput) buffer = win->make_texture_buffer("tex", 256, 256);
148  cerr << buffer->get_type() << "\n";
149 
150  // Set the offscreen buffer to render the same scene as the main camera.
151  DisplayRegion *dr = buffer->make_display_region();
152  dr->set_camera(NodePath(wf->get_camera(0)));
153 
154  // Make the clear color on the buffer be yellow, so it's obviously different
155  // from the main scene's background color.
156  buffer->set_clear_color(LColor(1, 1, 0, 0));
157 
158  // Apply the offscreen buffer's texture to a card in the main window.
159  CardMaker cm("card");
160  cm.set_frame(0, 1, 0, 1);
161  NodePath card_np(cm.generate());
162 
163  card_np.reparent_to(wf->get_render_2d());
164  card_np.set_texture(buffer->get_texture());
165 }
166 
167 void
168 usage() {
169  cerr <<
170  "\n"
171  "Usage: pview [opts] model [model ...]\n"
172  " pview -h\n\n";
173 }
174 
175 void
176 help() {
177  usage();
178  cerr <<
179  "pview opens a quick Panda window for viewing one or more models and/or\n"
180  "animations.\n\n"
181 
182  "Options:\n\n"
183 
184  " -a\n"
185  " Convert and play animations, if loading an external file type\n"
186  " (like .mb) directly and if the converter supports animations.\n"
187  " Also implicitly enables the animation controls.\n\n"
188 
189  " -c\n"
190  " Automatically center models within the viewing window on startup.\n"
191  " This can also be achieved with the 'c' hotkey at runtime.\n\n"
192 
193  " -l\n"
194  " Open the window before loading any models with the text \"Loading\"\n"
195  " displayed in the window. The default is not to open the window\n"
196  " until all models are loaded.\n\n"
197 
198  " -i\n"
199  " Ignore bundle/group names. Normally, the <group> name must match\n"
200  " the <bundle> name, or the animation will not be used.\n\n"
201 
202  " -s filename\n"
203  " After displaying the models, immediately take a screenshot and\n"
204  " exit.\n\n"
205 
206  " -D\n"
207  " Delete the model files after loading them (presumably this option\n"
208  " will only be used when loading a temporary model file).\n\n"
209 
210  " -L\n"
211  " Enable lighting in the scene. This can also be achieved with\n"
212  " the 'l' hotkey at runtime.\n\n"
213 
214  " -P <pipe>\n"
215  " Select the given graphics pipe for the window, rather than using\n"
216  " the platform default. The allowed values for <pipe> are those\n"
217  " from the Config.prc variables 'load-display' and 'aux-display'.\n\n"
218 
219  " -V\n"
220  " Report the current version of Panda, and exit.\n\n"
221 
222  " -h\n"
223  " Display this help text.\n\n";
224 }
225 
226 void
227 report_version() {
228  nout << "\n";
230  ps->write(nout);
231  nout << "\n";
232 }
233 
234 // Task that dynamically adjusts the camera len's near/far clipping
235 // planes to ensure the user can zoom in as close as needed to a model.
236 //
237 // Code adapted from WindowFramework::center_trackball(), but
238 // without moving the camera. When the camera is inside the model,
239 // the near clip is set to near-zero.
240 //
241 class AdjustCameraClipPlanesTask : public AsyncTask {
242 public:
243  AdjustCameraClipPlanesTask(const std::string &name, Camera *camera) :
244  AsyncTask(name), _camera(camera), _lens(camera->get_lens(0)), _sphere(nullptr)
245  {
246  NodePath np = framework.get_models();
247  PT(BoundingVolume) volume = np.get_bounds();
248 
249  // We expect at least a geometric bounding volume around the world.
250  nassertv(volume != nullptr);
251  nassertv(volume->is_of_type(GeometricBoundingVolume::get_class_type()));
252  CPT(GeometricBoundingVolume) gbv = DCAST(GeometricBoundingVolume, volume);
253 
254  if (np.has_parent()) {
255  CPT(TransformState) net_transform = np.get_parent().get_net_transform();
256  PT(GeometricBoundingVolume) new_gbv = DCAST(GeometricBoundingVolume, gbv->make_copy());
257  new_gbv->xform(net_transform->get_mat());
258  gbv = new_gbv;
259  }
260 
261  // Determine the bounding sphere around the object.
262  if (gbv->is_infinite()) {
263  framework_cat.warning()
264  << "Infinite bounding volume for " << np << "\n";
265  return;
266  }
267 
268  if (gbv->is_empty()) {
269  framework_cat.warning()
270  << "Empty bounding volume for " << np << "\n";
271  return;
272  }
273 
274  // The BoundingVolume might be a sphere (it's likely), but since it
275  // might not, we'll take no chances and make our own sphere.
276  _sphere = new BoundingSphere(gbv->get_approx_center(), 0.0f);
277  if (!_sphere->extend_by(gbv)) {
278  framework_cat.warning()
279  << "Cannot determine bounding volume of " << np << "\n";
280  return;
281  }
282  }
283  ALLOC_DELETED_CHAIN(AdjustCameraClipPlanesTask);
284 
285  virtual DoneStatus do_task() {
286  if (!_sphere) {
287  return DS_done;
288  }
289 
290  if (framework.get_num_windows() == 0) {
291  return DS_cont;
292  }
293 
294  WindowFramework *wf = framework.get_window(0);
295  if (!wf) {
296  return DS_cont;
297  }
298 
299  // Get current camera position.
300  NodePath cameraNP = wf->get_camera_group();
301  LPoint3 pos = cameraNP.get_pos();
302 
303  // See how far or close the camera is
304  LPoint3 center = _sphere->get_center();
305  PN_stdfloat radius = _sphere->get_radius();
306 
307  PN_stdfloat min_distance = 0.001 * radius;
308 
309  // Choose a suitable distance to view the whole volume in our frame.
310  // This is based on the camera lens in use.
311  PN_stdfloat distance;
312  CPT(GeometricBoundingVolume) gbv = DCAST(GeometricBoundingVolume, _sphere);
313  if (gbv->contains(pos)) {
314  // See as up-close to the model as possible
315  distance = min_distance;
316  } else {
317  // View from a distance
318  distance = (center - pos).length();
319  }
320 
321  // Ensure the far plane is far enough back to see the entire object.
322  PN_stdfloat ideal_far_plane = distance + radius * 1.5;
323  _lens->set_far(std::max(_lens->get_default_far(), ideal_far_plane));
324 
325  // And that the near plane is far enough forward, but if inside
326  // the sphere, keep above 0.
327  PN_stdfloat ideal_near_plane = std::max(min_distance * 10, distance - radius);
328  _lens->set_near(std::min(_lens->get_default_near(), ideal_near_plane));
329 
330  return DS_cont;
331  }
332 
333  Camera *_camera;
334  Lens *_lens;
335  PT(BoundingSphere) _sphere;
336 };
337 
338 
339 int
340 main(int argc, char **argv) {
341  preprocess_argv(argc, argv);
342  framework.open_framework(argc, argv);
343  framework.set_window_title("Panda Viewer");
344 
345  bool anim_controls = false;
346  bool auto_center = false;
347  bool show_loading = false;
348  bool auto_screenshot = false;
349  int hierarchy_match_flags = PartGroup::HMF_ok_part_extra |
350  PartGroup::HMF_ok_anim_extra;
351  Filename screenshotfn;
352  bool delete_models = false;
353  bool apply_lighting = false;
354  PointerTo<GraphicsPipe> pipe = nullptr;
355 
356  extern char *optarg;
357  extern int optind;
358  static const char *optflags = "acls:DVhiLP:";
359  int flag = getopt(argc, argv, optflags);
360 
361  while (flag != EOF) {
362  switch (flag) {
363  case 'a':
364  anim_controls = true;
365  PandaFramework::_loader_options.set_flags(PandaFramework::_loader_options.get_flags() | LoaderOptions::LF_convert_anim);
366  break;
367 
368  case 'c':
369  auto_center = true;
370  break;
371 
372  case 'l':
373  show_loading = true;
374  break;
375 
376  case 'i':
377  hierarchy_match_flags |= PartGroup::HMF_ok_wrong_root_name;
378  break;
379 
380  case 's':
381  auto_screenshot = true;
382  screenshotfn = optarg;
383  break;
384 
385  case 'D':
386  delete_models = true;
387  break;
388 
389  case 'L':
390  apply_lighting = true;
391  break;
392 
393  case 'P': {
394  pipe = GraphicsPipeSelection::get_global_ptr()->make_module_pipe(optarg);
395  if (!pipe) {
396  cerr << "No such pipe '" << optarg << "' available." << endl;
397  return 1;
398  }
399  break;
400  }
401 
402  case 'V':
403  report_version();
404  return 1;
405 
406  case 'h':
407  help();
408  return 1;
409 
410  case '?':
411  usage();
412  return 1;
413 
414  default:
415  cerr << "Unhandled switch: " << flag << endl;
416  break;
417  }
418  flag = getopt(argc, argv, optflags);
419  }
420  argc -= (optind - 1);
421  argv += (optind - 1);
422 
423  WindowFramework *window = framework.open_window(pipe, nullptr);
424  if (window != nullptr) {
425  // We've successfully opened a window.
426 
427  NodePath loading_np;
428 
429  if (show_loading) {
430  // Put up a "loading" message for the user's benefit.
431  NodePath aspect_2d = window->get_aspect_2d();
432  PT(TextNode) loading = new TextNode("loading");
433  loading_np = aspect_2d.attach_new_node(loading);
434  loading_np.set_scale(0.125f);
435  loading->set_text_color(1.0f, 1.0f, 1.0f, 1.0f);
436  loading->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
437  loading->set_shadow(0.04, 0.04);
438  loading->set_align(TextNode::A_center);
439  loading->set_text("Loading...");
440 
441  // Allow a couple of frames to go by so the window will be fully created
442  // and the text will be visible.
443  Thread *current_thread = Thread::get_current_thread();
444  framework.do_frame(current_thread);
445  framework.do_frame(current_thread);
446  }
447 
448  window->enable_keyboard();
449  window->setup_trackball();
450  framework.get_models().instance_to(window->get_render());
451  if (argc < 2) {
452  // If we have no arguments, get that trusty old triangle out.
453  window->load_default_model(framework.get_models());
454  } else {
455  window->load_models(framework.get_models(), argc, argv);
456 
457  if (delete_models) {
459  for (int i = 1; i < argc && argv[i] != nullptr; i++) {
460  Filename model = Filename::from_os_specific(argv[i]);
461  if (vfs->exists(model)) {
462  nout << "Deleting " << model << "\n";
463  vfs->delete_file(model);
464  }
465  }
466  }
467  }
468  window->loop_animations(hierarchy_match_flags);
469 
470  // Make sure the textures are preloaded.
471  framework.get_models().prepare_scene(window->get_graphics_output()->get_gsg());
472 
473  loading_np.remove_node();
474 
475  if (apply_lighting) {
476  window->set_lighting(true);
477  }
478 
479  if (auto_center) {
480  window->center_trackball(framework.get_models());
481  }
482 
483  if (auto_screenshot) {
484  return(output_screenshot(screenshotfn) ? 0:1);
485  }
486 
487  if (anim_controls) {
488  window->set_anim_controls(true);
489  }
490 
491  PT(AdjustCameraClipPlanesTask) task = new AdjustCameraClipPlanesTask("Adjust Camera Bounds", window->get_camera(0));
492  framework.get_task_mgr().add(task);
493 
494  framework.enable_default_keys();
495  framework.define_key("shift-w", "open a new window", event_W, nullptr);
496  framework.define_key("shift-f", "flatten hierarchy", event_F, nullptr);
497  framework.define_key("alt-enter", "toggle between window/fullscreen", event_Enter, nullptr);
498  framework.define_key("2", "split the window", event_2, nullptr);
499  if (pview_test_hack) {
500  framework.define_key("0", "run quick hacky test", event_0, nullptr);
501  }
502  framework.main_loop();
503  framework.report_frame_rate(nout);
504  }
505 
506  framework.close_framework();
507  return (0);
508 }
void report_frame_rate(std::ostream &out) const
Reports the currently measured average frame rate to the indicated ostream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static PandaSystem * get_global_ptr()
Returns the global PandaSystem object.
NodePath get_render_2d()
Returns the root of the 2-d scene graph.
int get_num_windows() const
Returns the number of windows that are currently open.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Indicates a coordinate-system transform on vertices.
This class is used as a namespace to group several global properties of Panda.
Definition: pandaSystem.h:26
void loop_animations(int hierarchy_match_flags=PartGroup::HMF_ok_part_extra|PartGroup::HMF_ok_anim_extra)
Looks for characters and their matching animation files in the scene graph; binds and loops any match...
void enable_default_keys()
Sets callbacks on the event handler to handle all of the normal viewer keys, like t to toggle texture...
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
An optional parameter associated with an event.
NodePath & get_models()
Returns the root of the scene graph normally reserved for parenting models and such.
NodePath get_render()
Returns the root of the 3-d scene graph.
void close_framework()
Should be called at the end of an application to close Panda.
set_fullscreen
Specifies whether the window should be opened in fullscreen mode (true) or normal windowed mode (fals...
A hierarchy of directories and files that appears to be one continuous file system,...
This is a convenience class to specialize ConfigVariable as a boolean type.
NodePath get_aspect_2d()
Returns the node under the 2-d scene graph that is scaled to suit the window's aspect ratio.
GraphicsOutput * get_graphics_output() const
Returns a pointer to the underlying GraphicsOutput object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines a bounding sphere, consisting of a center and a radius.
void set_scale(PN_stdfloat scale)
Sets the scale component of the transform, leaving translation and rotation untouched.
Definition: nodePath.I:675
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This encapsulates the data that is normally associated with a single window, or with a single display...
void set_anim_controls(bool enable)
Creates an onscreen animation slider for frame-stepping through the animations.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_lighting(bool enable)
Turns lighting on (true) or off (false).
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
Definition: nodePath.h:244
void open_framework()
Should be called once at the beginning of the application to initialize Panda (and the framework) for...
NodePath instance_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Adds the referenced node of the NodePath as a child of the referenced node of the indicated other Nod...
Definition: nodePath.cxx:471
NodePath load_default_model(const NodePath &parent)
Loads our favorite blue triangle.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
void prepare_scene(GraphicsStateGuardianBase *gsg)
Walks through the scene graph beginning at the bottom node, and does whatever initialization is requi...
Definition: nodePath.cxx:5327
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
void reparent_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread())
Removes the referenced node of the NodePath from its current parent and attaches it to the referenced...
Definition: nodePath.cxx:391
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
A container for the various kinds of properties we might ask to have on a graphics window before we o...
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
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:563
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
get_pipe
Returns the GraphicsPipe that this window is associated with.
void main_loop()
Called to yield control to the panda framework.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
bool save_screenshot(const Filename &filename, const std::string &image_comment="")
Saves a screenshot of the region to the indicated filename.
void enable_keyboard()
Creates a ButtonThrower to listen to button presses and throw them as events.
WindowFramework * open_window()
Opens a window on the default graphics pipe.
static GraphicsPipeSelection * get_global_ptr()
Returns a pointer to the one global GraphicsPipeSelection object.
This class generates 2-d "cards", that is, rectangular polygons, particularly useful for showing text...
Definition: cardMaker.h:29
AsyncTaskManager & get_task_mgr()
Returns the Task Manager object that manages tasks in the framework.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void close_window(int n)
Closes the nth window and removes it from the list.
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
This is a base class for the various different classes that represent the result of a frame of render...
void define_key(const std::string &event_name, const std::string &description, EventHandler::EventCallbackFunction *function, void *data)
Sets up a handler for the indicated key.
LPoint3 get_pos() const
Retrieves the translation component of the transform.
Definition: nodePath.cxx:992
void preprocess_argv(int &argc, char **&argv)
Processes the argc, argv pair as needed before passing it to getopt().
set_camera
Sets the camera that is associated with this DisplayRegion.
Definition: displayRegion.h:94
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:32
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int flatten_strong()
The strongest possible flattening.
Definition: nodePath.cxx:5543
A thread; that is, a lightweight process.
Definition: thread.h:46
A named event, possibly with parameters.
Definition: event.h:33
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition: nodePath.cxx:591
bool load_models(const NodePath &parent, int argc, char *argv[], int first_arg=1)
Loads up all the model files listed in the indicated argument list.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_window_title(const std::string &title)
Specifies the title that is set for all subsequently created windows.
get_properties
Returns the current properties of the window.
The primary interface to this module.
Definition: textNode.h:48
Encapsulates all the communication with a particular instance of a given rendering backend.
WindowFramework * split_window(SplitType split_type=ST_default)
Divides the window into two display regions, each of which gets its own trackball and keyboard events...
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This file defines the classes PointerTo and ConstPointerTo (and their abbreviations,...
Definition: pointerTo.h:69
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
GraphicsWindow * get_graphics_window() const
Returns a pointer to the underlying GraphicsWindow object, if it is in fact a window; or NULL if it i...
bool delete_file(const Filename &filename)
Attempts to delete the indicated file or directory.
void setup_trackball()
Sets up the mouse to trackball around the camera.
get_fullscreen
Returns true if the window is in fullscreen mode.
has_parent
Returns true if the referenced node has a parent; i.e.
Definition: nodePath.h:244
Camera * get_camera(int n) const
Returns the nth camera associated with the window.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework * get_window(int n) const
Returns the nth window currently open.
NodePath get_camera_group()
Returns the node above the collection of 3-d cameras in the scene graph.
get_gsg
Returns the GSG that is associated with this window.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
virtual bool do_frame(Thread *current_thread)
Renders one frame and performs all associated processing.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.