Browse Source

make NonlinearImager work with new scene graph

David Rose 23 years ago
parent
commit
1557ea2481

+ 22 - 6
panda/src/display/graphicsEngine.cxx

@@ -99,6 +99,24 @@ render_frame() {
   PStatClient::main_tick();
   PStatClient::main_tick();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::render_subframe
+//       Access: Published
+//  Description: Performs a complete cull and draw pass for one
+//               particular display region.  This is normally useful
+//               only for special effects, like shaders, that require
+//               a complete offscreen render pass before they can
+//               complete.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
+  if (cull_sorting) {
+    cull_bin_draw(gsg, dr);
+  } else {
+    cull_and_draw_together(gsg, dr);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::cull_and_draw_together
 //     Function: GraphicsEngine::cull_and_draw_together
 //       Access: Private
 //       Access: Private
@@ -118,7 +136,7 @@ cull_and_draw_together() {
       int num_display_regions = win->get_num_display_regions();
       int num_display_regions = win->get_num_display_regions();
       for (int i = 0; i < num_display_regions; i++) {
       for (int i = 0; i < num_display_regions; i++) {
         DisplayRegion *dr = win->get_display_region(i);
         DisplayRegion *dr = win->get_display_region(i);
-        cull_and_draw_together(win, dr);
+        cull_and_draw_together(win->get_gsg(), dr);
       }
       }
       win->end_frame();
       win->end_frame();
     }
     }
@@ -134,8 +152,7 @@ cull_and_draw_together() {
 //               windows in the same pass.
 //               windows in the same pass.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 void GraphicsEngine::
-cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
+cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
 
   PT(SceneSetup) scene_setup = setup_scene(dr->get_camera(), gsg);
   PT(SceneSetup) scene_setup = setup_scene(dr->get_camera(), gsg);
@@ -169,7 +186,7 @@ cull_bin_draw() {
       int num_display_regions = win->get_num_display_regions();
       int num_display_regions = win->get_num_display_regions();
       for (int i = 0; i < num_display_regions; i++) {
       for (int i = 0; i < num_display_regions; i++) {
         DisplayRegion *dr = win->get_display_region(i);
         DisplayRegion *dr = win->get_display_region(i);
-        cull_bin_draw(win, dr);
+        cull_bin_draw(win->get_gsg(), dr);
       }
       }
       win->end_frame();
       win->end_frame();
     }
     }
@@ -185,8 +202,7 @@ cull_bin_draw() {
 //               then draw the bins.  This is the normal method.
 //               then draw the bins.  This is the normal method.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 void GraphicsEngine::
-cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
+cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
 
   PT(CullResult) cull_result = dr->_cull_result;
   PT(CullResult) cull_result = dr->_cull_result;

+ 3 - 2
panda/src/display/graphicsEngine.h

@@ -51,13 +51,14 @@ PUBLISHED:
   bool remove_window(GraphicsWindow *window);
   bool remove_window(GraphicsWindow *window);
 
 
   void render_frame();
   void render_frame();
+  void render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr);
 
 
 private:
 private:
   void cull_and_draw_together();
   void cull_and_draw_together();
-  void cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr);
+  void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
 
 
   void cull_bin_draw();
   void cull_bin_draw();
-  void cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr);
+  void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr);
 
 
   PT(SceneSetup) setup_scene(const NodePath &camera, 
   PT(SceneSetup) setup_scene(const NodePath &camera, 
                              GraphicsStateGuardian *gsg);
                              GraphicsStateGuardian *gsg);

+ 26 - 57
panda/src/distort/nonlinearImager.cxx

@@ -22,6 +22,7 @@
 #include "graphicsStateGuardian.h"
 #include "graphicsStateGuardian.h"
 #include "matrixLens.h"
 #include "matrixLens.h"
 #include "graphicsWindow.h"
 #include "graphicsWindow.h"
+#include "graphicsEngine.h"
 #include "dcast.h"
 #include "dcast.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -37,10 +38,11 @@ NonlinearImager::
 NonlinearImager(DisplayRegion *dr) {
 NonlinearImager(DisplayRegion *dr) {
   _dr = dr;
   _dr = dr;
 
 
+  // The internal camera is an identity-matrix camera that simply
+  // views the meshes that represent the user's specified camera.
   _internal_camera = new Camera("NonlinearImager");
   _internal_camera = new Camera("NonlinearImager");
   _internal_camera->set_lens(new MatrixLens);
   _internal_camera->set_lens(new MatrixLens);
-  _internal_scene_node = new PandaNode("screens");
-  _internal_scene = NodePath(_internal_scene_node);
+  _internal_scene = NodePath("screens");
   _internal_camera->set_scene(_internal_scene);
   _internal_camera->set_scene(_internal_scene);
 
 
   NodePath camera_np = _internal_scene.attach_new_node(_internal_camera);
   NodePath camera_np = _internal_scene.attach_new_node(_internal_camera);
@@ -102,15 +104,6 @@ add_screen(ProjectionScreen *screen) {
   new_screen._last_screen = screen->get_last_screen();
   new_screen._last_screen = screen->get_last_screen();
   new_screen._active = true;
   new_screen._active = true;
 
 
-  // If the LensNode associated with the ProjectionScreen is an actual
-  // Camera, then it has a scene associated.  Otherwise, the user will
-  // have to specify the scene later.
-  LensNode *projector = screen->get_projector();
-  if (projector->is_of_type(Camera::get_class_type())) {
-    Camera *camera = DCAST(Camera, projector);
-    new_screen._scene = camera->get_scene();
-  }
-
   _stale = true;
   _stale = true;
   return _screens.size() - 1;
   return _screens.size() - 1;
 }
 }
@@ -205,35 +198,21 @@ set_size(int index, int width, int height) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NonlinearImager::set_source
-//       Access: Published
-//  Description: Specifies the camera and root of the scene that will
-//               be used to render the image for this particular
-//               screen.
-////////////////////////////////////////////////////////////////////
-void NonlinearImager::
-set_source(int index, LensNode *source, const NodePath &scene) {
-  nassertv(index >= 0 && index < (int)_screens.size());
-  _screens[index]._source = source;
-  _screens[index]._scene = scene;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NonlinearImager::set_source
+//     Function: NonlinearImager::set_source_camera
 //       Access: Published
 //       Access: Published
-//  Description: Specifies the camera and root of the scene that will
-//               be used to render the image for this particular
-//               screen.
+//  Description: Specifies the camera that will be used to render the
+//               image for this particular screen.
 //
 //
-//               Since this flavor accepts a Camera node, instead of
-//               just a LensNode, the scene is specified within the
-//               Camera itself.
+//               The parameter must be a NodePath whose node is a
+//               Camera.  The camera itself indicates the scene that
+//               is to be rendered.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NonlinearImager::
 void NonlinearImager::
-set_source(int index, Camera *source) {
+set_source_camera(int index, const NodePath &source_camera) {
   nassertv(index >= 0 && index < (int)_screens.size());
   nassertv(index >= 0 && index < (int)_screens.size());
-  _screens[index]._source = source;
-  _screens[index]._scene = source->get_scene();
+  nassertv(!source_camera.is_empty() && 
+           source_camera.node()->is_of_type(Camera::get_class_type()));
+  _screens[index]._source_camera = source_camera;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -301,13 +280,13 @@ recompute() {
 //               rendering.
 //               rendering.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NonlinearImager::
 void NonlinearImager::
-render() {
+render(GraphicsEngine *engine) {
   recompute_if_stale();
   recompute_if_stale();
 
 
   Screens::iterator si;
   Screens::iterator si;
   for (si = _screens.begin(); si != _screens.end(); ++si) {
   for (si = _screens.begin(); si != _screens.end(); ++si) {
     if ((*si)._active) {
     if ((*si)._active) {
-      render_screen(*si);
+      render_screen(engine, *si);
     }
     }
   }
   }
 }
 }
@@ -377,44 +356,34 @@ recompute_screen(NonlinearImager::Screen &screen) {
 //               the screen's own texture.
 //               the screen's own texture.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NonlinearImager::
 void NonlinearImager::
-render_screen(NonlinearImager::Screen &screen) {
-  if (screen._source == (LensNode *)NULL) {
-    distort_cat.error()
-      << "No source lens specified for screen " << screen._screen->get_name()
-      << "\n";
-    return;
-  }
-
-  if (screen._scene.is_empty()) {
+render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) {
+  if (screen._source_camera.is_empty()) {
     distort_cat.error()
     distort_cat.error()
-      << "No scene specified for screen " << screen._screen->get_name()
+      << "No source camera specified for screen " << screen._screen->get_name()
       << "\n";
       << "\n";
     return;
     return;
   }
   }
 
 
   // Got to update this to new scene graph.
   // Got to update this to new scene graph.
-
-  /*
   GraphicsStateGuardian *gsg = _dr->get_window()->get_gsg();
   GraphicsStateGuardian *gsg = _dr->get_window()->get_gsg();
 
 
   // Make a display region of the proper size and clear it to prepare for
   // Make a display region of the proper size and clear it to prepare for
   // rendering the scene.
   // rendering the scene.
   PT(DisplayRegion) scratch_region =
   PT(DisplayRegion) scratch_region =
     gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height);
     gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height);
+  scratch_region->set_camera(screen._source_camera);
+
   gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
   gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
                                     RenderBuffer::T_depth), 
                                     RenderBuffer::T_depth), 
              scratch_region);
              scratch_region);
-
-  DisplayRegionStack old_dr = gsg->push_display_region(scratch_region);
-  gsg->prepare_display_region();
-  gsg->render_scene(screen._scene, screen._source);
+  engine->render_subframe(gsg, scratch_region);
 
 
   // Copy the results of the render from the frame buffer into the
   // Copy the results of the render from the frame buffer into the
   // screen's texture.
   // screen's texture.
   screen._texture->copy(gsg, scratch_region, 
   screen._texture->copy(gsg, scratch_region, 
                         gsg->get_render_buffer(RenderBuffer::T_back));
                         gsg->get_render_buffer(RenderBuffer::T_back));
-  
-  // Restore the original display region.
-  gsg->pop_display_region(old_dr);
-  */
+
+  // It might be nice if we didn't through away the scratch region
+  // every time, which prevents us from preserving cull state from one
+  // frame to the next.
 }
 }

+ 18 - 13
panda/src/distort/nonlinearImager.h

@@ -30,6 +30,8 @@
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pvector.h"
 #include "pvector.h"
 
 
+class GraphicsEngine;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : NonlinearImager
 //       Class : NonlinearImager
 // Description : This class object combines the rendered output of a
 // Description : This class object combines the rendered output of a
@@ -41,12 +43,18 @@
 //               fisheye camera, even though the 3-d graphics engine
 //               fisheye camera, even though the 3-d graphics engine
 //               only supports linear cameras.
 //               only supports linear cameras.
 //
 //
-//               The NonlinearImager collects together a number of
-//               ProjectionScreens, each of which has a standard,
-//               linear Camera.  Each frame, the Imager renders each
-//               scene into a texture and then maps that texture onto
-//               a mesh which is presented to the graphics engine for
-//               rendering the final, non-linear output.
+//               
+//               A NonlinearImager may be visualized as a theater room
+//               into which a number of projection screens have been
+//               placed, at any arbitrary position and orientation to
+//               each other.  Each of these projection screens
+//               displays the view seen by a normal perspective camera
+//               that exists in the world (that is, under render).
+//
+//               There is also in the theater a single, possibly
+//               nonlinear, camera that observes these screens.  The
+//               user's window (or DisplayRegion) will display the
+//               output of this camera.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAFX NonlinearImager {
 class EXPCL_PANDAFX NonlinearImager {
 PUBLISHED:
 PUBLISHED:
@@ -61,8 +69,7 @@ PUBLISHED:
   int get_num_screens() const;
   int get_num_screens() const;
   ProjectionScreen *get_screen(int index) const;
   ProjectionScreen *get_screen(int index) const;
   void set_size(int index, int width, int height);
   void set_size(int index, int width, int height);
-  void set_source(int index, LensNode *source, const NodePath &scene);
-  void set_source(int index, Camera *source);
+  void set_source_camera(int index, const NodePath &source_camera);
 
 
   void set_active(int index, bool active);
   void set_active(int index, bool active);
   bool get_active(int index) const;
   bool get_active(int index) const;
@@ -73,7 +80,7 @@ PUBLISHED:
   INLINE NodePath get_internal_scene() const;
   INLINE NodePath get_internal_scene() const;
 
 
   void recompute();
   void recompute();
-  void render();
+  void render(GraphicsEngine *engine);
 
 
 private:
 private:
   class Screen {
   class Screen {
@@ -81,8 +88,7 @@ private:
     PT(ProjectionScreen) _screen;
     PT(ProjectionScreen) _screen;
     NodePath _mesh;
     NodePath _mesh;
     PT(Texture) _texture;
     PT(Texture) _texture;
-    PT(LensNode) _source;
-    NodePath _scene;
+    NodePath _source_camera;
     int _tex_width, _tex_height;
     int _tex_width, _tex_height;
     UpdateSeq _last_screen;
     UpdateSeq _last_screen;
     bool _active;
     bool _active;
@@ -90,7 +96,7 @@ private:
 
 
   void recompute_if_stale();
   void recompute_if_stale();
   void recompute_screen(Screen &screen);
   void recompute_screen(Screen &screen);
-  void render_screen(Screen &screen);
+  void render_screen(GraphicsEngine *engine, Screen &screen);
 
 
   PT(DisplayRegion) _dr;
   PT(DisplayRegion) _dr;
 
 
@@ -101,7 +107,6 @@ private:
 
 
   PT(Camera) _internal_camera;
   PT(Camera) _internal_camera;
   NodePath _internal_scene;
   NodePath _internal_scene;
-  PT(PandaNode) _internal_scene_node;
 
 
   bool _stale;
   bool _stale;
   UpdateSeq _camera_lens_change;
   UpdateSeq _camera_lens_change;

+ 34 - 8
panda/src/distort/projectionScreen.cxx

@@ -67,7 +67,7 @@ ProjectionScreen(const ProjectionScreen &copy) :
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::make_copy
 //     Function: ProjectionScreen::make_copy
-//       Access: Protected, Virtual
+//       Access: Public, Virtual
 //  Description: Returns a newly-allocated Node that is a shallow copy
 //  Description: Returns a newly-allocated Node that is a shallow copy
 //               of this one.  It will be a different Node pointer,
 //               of this one.  It will be a different Node pointer,
 //               but its internal data may or may not be shared with
 //               but its internal data may or may not be shared with
@@ -78,18 +78,44 @@ make_copy() const {
   return new ProjectionScreen(*this);
   return new ProjectionScreen(*this);
 }
 }
 
 
-/*
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ProjectionScreen::app_traverse
+//     Function: ProjectionScreen::has_cull_callback
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: This is called by the App traversal by virtue of the
-//               ProjectionScreen node's being present in the scene graph.
+//  Description: Should be overridden by derived classes to return
+//               true if cull_callback() has been defined.  Otherwise,
+//               returns false to indicate cull_callback() does not
+//               need to be called for this node during the cull
+//               traversal.
+////////////////////////////////////////////////////////////////////
+bool ProjectionScreen::
+has_cull_callback() const {
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void ProjectionScreen::
-app_traverse(const ArcChain &) {
+//     Function: ProjectionScreen::cull_callback
+//       Access: Public, Virtual
+//  Description: If has_cull_callback() returns true, this function
+//               will be called during the cull traversal to perform
+//               any additional operations that should be performed at
+//               cull time.  This may include additional manipulation
+//               of render state or additional visible/invisible
+//               decisions, or any other arbitrary operation.
+//
+//               By the time this function is called, the node has
+//               already passed the bounding-volume test for the
+//               viewing frustum, and the node's transform and state
+//               have already been applied to the indicated
+//               CullTraverserData object.
+//
+//               The return value is true if this node should be
+//               visible, or false if it should be culled.
+////////////////////////////////////////////////////////////////////
+bool ProjectionScreen::
+cull_callback(CullTraverser *, CullTraverserData &) {
   recompute_if_stale();
   recompute_if_stale();
+  return true;
 }
 }
-*/
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::generate_screen
 //     Function: ProjectionScreen::generate_screen

+ 4 - 0
panda/src/distort/projectionScreen.h

@@ -52,7 +52,11 @@ PUBLISHED:
 
 
 protected:
 protected:
   ProjectionScreen(const ProjectionScreen &copy);
   ProjectionScreen(const ProjectionScreen &copy);
+
+public:
   virtual PandaNode *make_copy() const;
   virtual PandaNode *make_copy() const;
+  virtual bool has_cull_callback() const;
+  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE void set_projector(LensNode *projector);
   INLINE void set_projector(LensNode *projector);