Browse Source

refinements to nonlinearImager

David Rose 24 years ago
parent
commit
4a5d763b17

+ 12 - 0
panda/src/distort/nonlinearImager.I

@@ -41,3 +41,15 @@ INLINE LensNode *NonlinearImager::
 get_camera() const {
 get_camera() const {
   return _camera;
   return _camera;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: NonlinearImager::get_internal_scene
+//       Access: Published
+//  Description: Returns a pointer to the root node of the internal
+//               scene graph, which is used to render all of the
+//               screen meshes.
+////////////////////////////////////////////////////////////////////
+INLINE Node *NonlinearImager::
+get_internal_scene() const {
+  return _internal_scene_top;
+}

+ 58 - 5
panda/src/distort/nonlinearImager.cxx

@@ -24,6 +24,7 @@
 #include "matrixLens.h"
 #include "matrixLens.h"
 #include "renderRelation.h"
 #include "renderRelation.h"
 #include "graphicsWindow.h"
 #include "graphicsWindow.h"
+#include "cullFaceTransition.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NonlinearImager::Constructor
 //     Function: NonlinearImager::Constructor
@@ -40,10 +41,20 @@ NonlinearImager(DisplayRegion *dr) {
 
 
   _internal_camera = new Camera("NonlinearImager");
   _internal_camera = new Camera("NonlinearImager");
   _internal_camera->set_lens(new MatrixLens);
   _internal_camera->set_lens(new MatrixLens);
-  _internal_scene = new NamedNode("NonlinearImager");
-  _internal_camera->set_scene(_internal_scene);
+  _internal_scene_top = new NamedNode("NonlinearImager");
+  _internal_scene = new NamedNode("screens");
+  _internal_camera->set_scene(_internal_scene_top);
   _dr->set_camera(_internal_camera);
   _dr->set_camera(_internal_camera);
 
 
+  RenderRelation *top_arc = 
+    new RenderRelation(_internal_scene_top, _internal_scene);
+
+  // Enable face culling on the wireframe mesh.  This will help us to
+  // cull out invalid polygons that result from vertices crossing a
+  // singularity (for instance, at the back of a fisheye lens).
+  CullFaceTransition *cfa = new CullFaceTransition(CullFaceProperty::M_cull_clockwise);
+  top_arc->set_transition(cfa);
+
   _stale = true;
   _stale = true;
 }
 }
 
 
@@ -93,6 +104,7 @@ add_screen(ProjectionScreen *screen) {
   new_screen._texture = (Texture *)NULL;
   new_screen._texture = (Texture *)NULL;
   new_screen._tex_width = 256;
   new_screen._tex_width = 256;
   new_screen._tex_height = 256;
   new_screen._tex_height = 256;
+  new_screen._active = true;
 
 
   // If the LensNode associated with the ProjectionScreen is an actual
   // If the LensNode associated with the ProjectionScreen is an actual
   // Camera, then it has a scene associated.  Otherwise, the user will
   // Camera, then it has a scene associated.  Otherwise, the user will
@@ -232,6 +244,43 @@ set_source(int index, Camera *source) {
   _screens[index]._scene = source->get_scene();
   _screens[index]._scene = source->get_scene();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NonlinearImager::set_active
+//       Access: Published
+//  Description: Sets the active flag on the indicated screen.  If the
+//               active flag is true, the screen will be used;
+//               otherwise, it will not appear.
+////////////////////////////////////////////////////////////////////
+void NonlinearImager::
+set_active(int index, bool active) {
+  nassertv(index >= 0 && index < (int)_screens.size());
+  _screens[index]._active = active;
+
+  if (!active) {
+    Screen &screen = _screens[index];
+    // If we've just made this screen inactive, remove its mesh.
+    if (screen._mesh_arc != (NodeRelation *)NULL) {
+      remove_arc(screen._mesh_arc);
+      screen._mesh_arc = (NodeRelation *)NULL;
+    }
+    screen._texture.clear();
+  } else {
+    // If we've just made it active, it needs to be recomputed.
+    _stale = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NonlinearImager::get_active
+//       Access: Published
+//  Description: Returns the active flag on the indicated screen.
+////////////////////////////////////////////////////////////////////
+bool NonlinearImager::
+get_active(int index) const {
+  nassertr(index >= 0 && index < (int)_screens.size(), false);
+  return _screens[index]._active;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NonlinearImager::recompute
 //     Function: NonlinearImager::recompute
 //       Access: Published
 //       Access: Published
@@ -241,7 +290,9 @@ void NonlinearImager::
 recompute() {
 recompute() {
   Screens::iterator si;
   Screens::iterator si;
   for (si = _screens.begin(); si != _screens.end(); ++si) {
   for (si = _screens.begin(); si != _screens.end(); ++si) {
-    recompute_screen(*si);
+    if ((*si)._active) {
+      recompute_screen(*si);
+    }
   }
   }
 
 
   if (_camera != (LensNode *)NULL && _camera->get_lens() != (Lens *)NULL) {
   if (_camera != (LensNode *)NULL && _camera->get_lens() != (Lens *)NULL) {
@@ -266,7 +317,9 @@ render() {
 
 
   Screens::iterator si;
   Screens::iterator si;
   for (si = _screens.begin(); si != _screens.end(); ++si) {
   for (si = _screens.begin(); si != _screens.end(); ++si) {
-    render_screen(*si);
+    if ((*si)._active) {
+      render_screen(*si);
+    }
   }
   }
 }
 }
 
 
@@ -299,7 +352,7 @@ recompute_screen(NonlinearImager::Screen &screen) {
     screen._mesh_arc = (NodeRelation *)NULL;
     screen._mesh_arc = (NodeRelation *)NULL;
   }
   }
   screen._texture.clear();
   screen._texture.clear();
-  if (_camera == (LensNode *)NULL) {
+  if (_camera == (LensNode *)NULL || !screen._active) {
     // Not much we can do without a camera.
     // Not much we can do without a camera.
     return;
     return;
   }
   }

+ 7 - 0
panda/src/distort/nonlinearImager.h

@@ -61,9 +61,14 @@ PUBLISHED:
   void set_source(int index, LensNode *source, Node *scene);
   void set_source(int index, LensNode *source, Node *scene);
   void set_source(int index, Camera *source);
   void set_source(int index, Camera *source);
 
 
+  void set_active(int index, bool active);
+  bool get_active(int index) const;
+
   INLINE void set_camera(LensNode *camera);
   INLINE void set_camera(LensNode *camera);
   INLINE LensNode *get_camera() const;
   INLINE LensNode *get_camera() const;
 
 
+  INLINE Node *get_internal_scene() const;
+
   void recompute();
   void recompute();
   void render();
   void render();
 
 
@@ -76,6 +81,7 @@ private:
     PT(LensNode) _source;
     PT(LensNode) _source;
     PT_Node _scene;
     PT_Node _scene;
     int _tex_width, _tex_height;
     int _tex_width, _tex_height;
+    bool _active;
   };
   };
 
 
   void recompute_if_stale();
   void recompute_if_stale();
@@ -90,6 +96,7 @@ private:
   PT(LensNode) _camera;
   PT(LensNode) _camera;
 
 
   PT(Camera) _internal_camera;
   PT(Camera) _internal_camera;
+  PT_Node _internal_scene_top;
   PT_Node _internal_scene;
   PT_Node _internal_scene;
 
 
   bool _stale;
   bool _stale;

+ 30 - 10
panda/src/distort/projectionScreen.cxx

@@ -109,10 +109,10 @@ app_traverse(const ArcChain &) {
 //     Function: ProjectionScreen::generate_screen
 //     Function: ProjectionScreen::generate_screen
 //       Access: Published
 //       Access: Published
 //  Description: Synthesizes a polygon mesh based on the projection
 //  Description: Synthesizes a polygon mesh based on the projection
-//               area of the indicated projector.  This generates a
-//               new GeomNode and automatically parents it to the
-//               ProjectionScreen; the new GeomNode is also returned
-//               for reference.
+//               area of the indicated projector.  This generates and
+//               returns a new GeomNode but does not automatically
+//               parent it to the ProjectionScreen node; see
+//               regenerate_screen().
 //
 //
 //               The specified projector need not be the same as the
 //               The specified projector need not be the same as the
 //               projector given to the ProjectionScreen with
 //               projector given to the ProjectionScreen with
@@ -125,7 +125,7 @@ app_traverse(const ArcChain &) {
 //               respectively; distance represents the approximate
 //               respectively; distance represents the approximate
 //               distance of the screen from the lens center.
 //               distance of the screen from the lens center.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-GeomNode *ProjectionScreen::
+PT(GeomNode) ProjectionScreen::
 generate_screen(LensNode *projector, const string &screen_name,
 generate_screen(LensNode *projector, const string &screen_name,
                 int num_x_verts, int num_y_verts, float distance) {
                 int num_x_verts, int num_y_verts, float distance) {
   nassertr(projector != (LensNode *)NULL, NULL);
   nassertr(projector != (LensNode *)NULL, NULL);
@@ -204,16 +204,35 @@ generate_screen(LensNode *projector, const string &screen_name,
   geom->set_colors(colors, G_OVERALL);
   geom->set_colors(colors, G_OVERALL);
 
 
   // Now create a GeomNode to hold this mesh.
   // Now create a GeomNode to hold this mesh.
-  GeomNode *geom_node = new GeomNode(screen_name);
+  PT(GeomNode) geom_node = new GeomNode(screen_name);
   geom_node->add_geom(geom);
   geom_node->add_geom(geom);
 
 
-  // And parent it to ourselves.
-  new RenderRelation(this, geom_node);
   _stale = true;
   _stale = true;
-
   return geom_node;
   return geom_node;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::regenerate_screen
+//       Access: Published
+//  Description: Removes all the children from the ProjectionScreen
+//               node, and adds the newly generated child returned by
+//               generate_screen().
+////////////////////////////////////////////////////////////////////
+void ProjectionScreen::
+regenerate_screen(LensNode *projector, const string &screen_name,
+                  int num_x_verts, int num_y_verts, float distance) {
+  // First, remove all existing children.
+  while (get_num_children(RenderRelation::get_class_type()) > 0) {
+    remove_arc(get_child(RenderRelation::get_class_type(), 0));
+  }
+
+  // And attach a new child.
+  PT(GeomNode) geom_node = 
+    generate_screen(projector, screen_name, num_x_verts, num_y_verts, 
+                    distance);
+  new RenderRelation(this, geom_node);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::make_flat_mesh
 //     Function: ProjectionScreen::make_flat_mesh
 //       Access: Published
 //       Access: Published
@@ -518,7 +537,8 @@ make_mesh_geom_node(GeomNode *node, LensNode *camera,
 //       Access: Private
 //       Access: Private
 //  Description: Makes a new Geom, just like the given one, except
 //  Description: Makes a new Geom, just like the given one, except
 //               flattened into two dimensions as seen by the
 //               flattened into two dimensions as seen by the
-//               indicated lens.
+//               indicated lens.  Any triangle in the original mesh
+//               that involves an unprojectable vertex is eliminated.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(dDrawable) ProjectionScreen::
 PT(dDrawable) ProjectionScreen::
 make_mesh_geom(Geom *geom, Lens *lens, LMatrix4f &rel_mat) {
 make_mesh_geom(Geom *geom, Lens *lens, LMatrix4f &rel_mat) {

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

@@ -61,8 +61,10 @@ PUBLISHED:
   INLINE void set_projector(LensNode *projector);
   INLINE void set_projector(LensNode *projector);
   INLINE LensNode *get_projector() const;
   INLINE LensNode *get_projector() const;
 
 
-  GeomNode *generate_screen(LensNode *projector, const string &screen_name,
-                            int num_x_verts, int num_y_verts, float distance);
+  PT(GeomNode) generate_screen(LensNode *projector, const string &screen_name,
+                               int num_x_verts, int num_y_verts, float distance);
+  void regenerate_screen(LensNode *projector, const string &screen_name,
+                         int num_x_verts, int num_y_verts, float distance);
   PT_Node make_flat_mesh(LensNode *camera);
   PT_Node make_flat_mesh(LensNode *camera);
 
 
   INLINE void set_vignette_on(bool vignette_on);
   INLINE void set_vignette_on(bool vignette_on);

+ 3 - 1
panda/src/sgattrib/cullFaceTransition.h

@@ -23,7 +23,9 @@
 
 
 #include "cullFaceProperty.h"
 #include "cullFaceProperty.h"
 
 
-#include <onTransition.h>
+#include "nodeTransition.h"
+#include "pointerTo.h"
+#include "onTransition.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : CullFaceTransition
 //       Class : CullFaceTransition