Browse Source

use NodePath interface

David Rose 23 years ago
parent
commit
99413ba1b3

+ 7 - 20
panda/src/distort/nonlinearImager.I

@@ -18,28 +18,15 @@
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: NonlinearImager::set_camera
+//     Function: NonlinearImager::get_viewer
 //       Access: Published
-//  Description: Specifies the virtual camera that will be used to
-//               view the various ProjectionScreens.  It should be in
-//               the same scene graph with the ProjectionScreens, to
-//               establish a relative coordinate system with them.
+//  Description: Returns the NodePath to the LensNode that is to serve
+//               as the viewer for this screen, or empty if no
+//               viewer is associated.
 ////////////////////////////////////////////////////////////////////
-INLINE void NonlinearImager::
-set_camera(LensNode *camera) {
-  _camera = camera;
-  _stale = true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NonlinearImager::get_camera
-//       Access: Published
-//  Description: Returns the virtual camera that will be used to
-//               view the various ProjectionScreens.
-////////////////////////////////////////////////////////////////////
-INLINE LensNode *NonlinearImager::
-get_camera() const {
-  return _camera;
+INLINE const NodePath &NonlinearImager::
+get_viewer() const {
+  return _viewer;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 35 - 12
panda/src/distort/nonlinearImager.cxx

@@ -249,6 +249,28 @@ get_active(int index) const {
   return _screens[index]._active;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NonlinearImager::set_viewer
+//       Access: Published
+//  Description: Specifies the LensNode that is to serve as the
+//               viewer for this screen.  The relative position of
+//               the LensNode to the NonlinearImager, as well as the
+//               properties of the lens associated with the LensNode,
+//               determines the UV's that will be assigned to the
+//               geometry within the NonlinearImager.
+//
+//               The NodePath must refer to a LensNode (or a Camera).
+////////////////////////////////////////////////////////////////////
+void NonlinearImager::
+set_viewer(const NodePath &viewer) {
+  _viewer_node = (LensNode *)NULL;
+  _viewer = viewer;
+  _stale = true;
+  nassertv(!viewer.is_empty() && 
+           viewer.node()->is_of_type(LensNode::get_class_type()));
+  _viewer_node = DCAST(LensNode, viewer.node());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NonlinearImager::recompute
 //       Access: Published
@@ -263,8 +285,9 @@ recompute() {
     }
   }
 
-  if (_camera != (LensNode *)NULL && _camera->get_lens() != (Lens *)NULL) {
-    _camera_lens_change = _camera->get_lens()->get_last_change();
+  if (_viewer_node != (LensNode *)NULL && 
+      _viewer_node->get_lens() != (Lens *)NULL) {
+    _viewer_lens_change = _viewer_node->get_lens()->get_last_change();
   }
   _stale = false;
 }
@@ -298,10 +321,10 @@ render(GraphicsEngine *engine) {
 ////////////////////////////////////////////////////////////////////
 void NonlinearImager::
 recompute_if_stale() {
-  if (_camera != (LensNode *)NULL && 
-      _camera->get_lens() != (Lens *)NULL) {
-    UpdateSeq lens_change = _camera->get_lens()->get_last_change();
-    if (_stale || lens_change != _camera_lens_change) {
+  if (_viewer_node != (LensNode *)NULL && 
+      _viewer_node->get_lens() != (Lens *)NULL) {
+    UpdateSeq lens_change = _viewer_node->get_lens()->get_last_change();
+    if (_stale || lens_change != _viewer_lens_change) {
       recompute();
     } else {
       // We're not overall stale, but maybe we need to recompute one
@@ -328,12 +351,12 @@ void NonlinearImager::
 recompute_screen(NonlinearImager::Screen &screen) {
   screen._mesh.remove_node();
   screen._texture.clear();
-  if (_camera == (LensNode *)NULL || !screen._active) {
-    // Not much we can do without a camera.
+  if (_viewer_node == (LensNode *)NULL || !screen._active) {
+    // Not much we can do without a viewer.
     return;
   }
 
-  PT(PandaNode) mesh = screen._screen->make_flat_mesh(_camera);
+  PT(PandaNode) mesh = screen._screen->make_flat_mesh(_viewer);
   screen._mesh = _internal_scene.attach_new_node(mesh);
 
   PT(Texture) texture = new Texture;
@@ -383,7 +406,7 @@ render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) {
   screen._texture->copy(gsg, scratch_region, 
                         gsg->get_render_buffer(RenderBuffer::T_back));
 
-  // 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.
+  // It might be nice if we didn't throw away the scratch region every
+  // time, which prevents us from preserving cull state from one frame
+  // to the next.
 }

+ 10 - 8
panda/src/distort/nonlinearImager.h

@@ -46,10 +46,11 @@ class GraphicsEngine;
 //               
 //               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).
+//               placed, of arbitrary size and shape and at any
+//               arbitrary position and orientation to each other.
+//               Onto each of these screens is projected the view as
+//               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
@@ -74,8 +75,8 @@ PUBLISHED:
   void set_active(int index, bool active);
   bool get_active(int index) const;
 
-  INLINE void set_camera(LensNode *camera);
-  INLINE LensNode *get_camera() const;
+  void set_viewer(const NodePath &viewer);
+  INLINE const NodePath &get_viewer() const;
 
   INLINE NodePath get_internal_scene() const;
 
@@ -103,13 +104,14 @@ private:
   typedef pvector<Screen> Screens;
   Screens _screens;
 
-  PT(LensNode) _camera;
+  NodePath _viewer;
+  PT(LensNode) _viewer_node;
 
   PT(Camera) _internal_camera;
   NodePath _internal_scene;
 
   bool _stale;
-  UpdateSeq _camera_lens_change;
+  UpdateSeq _viewer_lens_change;
 };
 
 #include "nonlinearImager.I"

+ 4 - 20
panda/src/distort/projectionScreen.I

@@ -17,31 +17,15 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: ProjectionScreen::set_projector
-//       Access: Published
-//  Description: Specifies the LensNode that is to serve as the
-//               projector for this screen.  The relative position of
-//               the LensNode to the ProjectionScreen, as well as the
-//               properties of the lens associated with the LensNode,
-//               determines the UV's that will be assigned to the
-//               geometry within the ProjectionScreen.
-////////////////////////////////////////////////////////////////////
-INLINE void ProjectionScreen::
-set_projector(LensNode *projector) {
-  _projector = projector;
-  _stale = true;
-}
-
 
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::get_projector
 //       Access: Published
-//  Description: Returns the LensNode that is to serve as the
-//               projector for this screen, or NULL if no LensNode is
-//               associated.
+//  Description: Returns the NodePath to the LensNode that is to serve
+//               as the projector for this screen, or empty if no
+//               projector is associated.
 ////////////////////////////////////////////////////////////////////
-INLINE LensNode *ProjectionScreen::
+INLINE const NodePath &ProjectionScreen::
 get_projector() const {
   return _projector;
 }

+ 120 - 75
panda/src/distort/projectionScreen.cxx

@@ -21,6 +21,7 @@
 #include "geom.h"
 #include "geomTristrip.h"
 #include "transformState.h"
+#include "workingNodePath.h"
 
 TypeHandle ProjectionScreen::_type_handle;
 
@@ -57,6 +58,7 @@ ProjectionScreen::
 ProjectionScreen(const ProjectionScreen &copy) :
   PandaNode(copy),
   _projector(copy._projector),
+  _projector_node(copy._projector_node),
   _vignette_on(copy._vignette_on),
   _vignette_color(copy._vignette_color),
   _frame_color(copy._frame_color)
@@ -117,6 +119,28 @@ cull_callback(CullTraverser *, CullTraverserData &) {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::set_projector
+//       Access: Published
+//  Description: Specifies the LensNode that is to serve as the
+//               projector for this screen.  The relative position of
+//               the LensNode to the ProjectionScreen, as well as the
+//               properties of the lens associated with the LensNode,
+//               determines the UV's that will be assigned to the
+//               geometry within the ProjectionScreen.
+//
+//               The NodePath must refer to a LensNode (or a Camera).
+////////////////////////////////////////////////////////////////////
+void ProjectionScreen::
+set_projector(const NodePath &projector) {
+  _projector_node = (LensNode *)NULL;
+  _projector = projector;
+  _stale = true;
+  nassertv(!projector.is_empty() && 
+           projector.node()->is_of_type(LensNode::get_class_type()));
+  _projector_node = DCAST(LensNode, projector.node());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::generate_screen
 //       Access: Published
@@ -138,21 +162,23 @@ cull_callback(CullTraverser *, CullTraverserData &) {
 //               distance of the screen from the lens center.
 ////////////////////////////////////////////////////////////////////
 PT(GeomNode) ProjectionScreen::
-generate_screen(LensNode *projector, const string &screen_name,
+generate_screen(const NodePath &projector, const string &screen_name,
                 int num_x_verts, int num_y_verts, float distance) {
-  nassertr(projector != (LensNode *)NULL, NULL);
-  nassertr(projector->get_lens() != NULL, NULL);
+  nassertr(!projector.is_empty() && 
+           projector.node()->is_of_type(LensNode::get_class_type()),
+           NULL);
+  LensNode *projector_node = DCAST(LensNode, projector.node());
+  nassertr(projector_node->get_lens() != NULL, NULL);
 
   // First, get the relative coordinate space of the projector.
   LMatrix4f rel_mat;
-  NodePath projector_np(projector);
   NodePath this_np(this);
-  rel_mat = projector_np.get_mat(this_np);
+  rel_mat = projector.get_mat(this_np);
 
   // Now compute all the vertices for the screen.  These are arranged
   // in order from left to right and bottom to top.
   int num_verts = num_x_verts * num_y_verts;
-  Lens *lens = projector->get_lens();
+  Lens *lens = projector_node->get_lens();
   float t = (distance - lens->get_near()) / (lens->get_far() - lens->get_near());
 
   PTA_Vertexf coords;
@@ -234,7 +260,7 @@ generate_screen(LensNode *projector, const string &screen_name,
 //               generate_screen().
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
-regenerate_screen(LensNode *projector, const string &screen_name,
+regenerate_screen(const NodePath &projector, const string &screen_name,
                   int num_x_verts, int num_y_verts, float distance) {
   // First, remove all existing children.
   remove_all_children();
@@ -261,23 +287,27 @@ regenerate_screen(LensNode *projector, const string &screen_name,
 //               lens, to generate the effect of seeing the image
 //               through the specified non-linear lens.
 //
-//               The returned node has no parent; it is up to the user
-//               to caller to parent it somewhere or store it so that
-//               it does not get dereferenced and deleted.
+//               The returned node has no parent; it is up to the
+//               caller to parent it somewhere or store it so that it
+//               does not get dereferenced and deleted.
 ////////////////////////////////////////////////////////////////////
 PT(PandaNode) ProjectionScreen::
-make_flat_mesh(LensNode *camera) {
-  nassertr(camera != (LensNode *)NULL, NULL);
-  nassertr(camera->get_lens() != (Lens *)NULL, NULL);
+make_flat_mesh(const NodePath &camera) {
+  nassertr(!camera.is_empty() && 
+           camera.node()->is_of_type(LensNode::get_class_type()),
+           NULL);
+  LensNode *camera_node = DCAST(LensNode, camera.node());
+  nassertr(camera_node->get_lens() != (Lens *)NULL, NULL);
 
   // First, ensure the UV's are up-to-date.
   recompute_if_stale();
 
   PT(PandaNode) top = new PandaNode(get_name());
+  NodePath this_np(this);
 
   LMatrix4f rel_mat;
   bool computed_rel_mat = false;
-  make_mesh_children(top, this, camera, rel_mat, computed_rel_mat);
+  make_mesh_children(top, this_np, camera, rel_mat, computed_rel_mat);
 
   return top;
 }
@@ -297,19 +327,8 @@ make_flat_mesh(LensNode *camera) {
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
 recompute() {
-  if (_projector != (LensNode *)NULL && 
-      _projector->get_lens() != (Lens *)NULL) {
-    _colors.clear();
-    _colors.push_back(_vignette_color);
-    _colors.push_back(_frame_color);
-
-    recompute_node(this, _rel_top_mat, _computed_rel_top_mat);
-    // Make sure this flag is set to false for next time.
-    _computed_rel_top_mat = false;
-
-    _projector_lens_change = _projector->get_lens()->get_last_change();
-    _stale = false;
-  }
+  NodePath this_np(this);
+  do_recompute(this_np);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -322,26 +341,47 @@ recompute() {
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
 recompute_if_stale() {
-  if (_projector != (LensNode *)NULL && 
-      _projector->get_lens() != (Lens *)NULL) {
-    UpdateSeq lens_change = _projector->get_lens()->get_last_change();
+  if (_projector_node != (LensNode *)NULL && 
+      _projector_node->get_lens() != (Lens *)NULL) {
+    UpdateSeq lens_change = _projector_node->get_lens()->get_last_change();
     if (_stale || lens_change != _projector_lens_change) {
       recompute();
 
     } else {
       // Get the relative transform to ensure it hasn't changed.
       NodePath this_np(this);
-      NodePath projector_np(_projector);
-      const LMatrix4f &top_mat = this_np.get_mat(projector_np);
+      const LMatrix4f &top_mat = this_np.get_mat(_projector);
       if (!_rel_top_mat.almost_equal(top_mat)) {
         _rel_top_mat = top_mat;
         _computed_rel_top_mat = true;
-        recompute();
+        do_recompute(this_np);
       }
     }
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::do_recompute
+//       Access: Private
+//  Description: Starts the recomputation process.
+////////////////////////////////////////////////////////////////////
+void ProjectionScreen::
+do_recompute(const NodePath &this_np) {
+  if (_projector_node != (LensNode *)NULL && 
+      _projector_node->get_lens() != (Lens *)NULL) {
+    _colors.clear();
+    _colors.push_back(_vignette_color);
+    _colors.push_back(_frame_color);
+
+    recompute_node(this_np, _rel_top_mat, _computed_rel_top_mat);
+    // Make sure this flag is set to false for next time.
+    _computed_rel_top_mat = false;
+
+    _projector_lens_change = _projector_node->get_lens()->get_last_change();
+    _stale = false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::recompute_node
 //       Access: Private
@@ -351,9 +391,11 @@ recompute_if_stale() {
 //               encountered, a new relative matrix is computed.
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
-recompute_node(PandaNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat) {
+recompute_node(const WorkingNodePath &np, LMatrix4f &rel_mat,
+               bool &computed_rel_mat) {
+  PandaNode *node = np.node();
   if (node->is_geom_node()) {
-    recompute_geom_node(DCAST(GeomNode, node), rel_mat, computed_rel_mat);
+    recompute_geom_node(np, rel_mat, computed_rel_mat);
   }
 
   // Now recurse on children.
@@ -361,20 +403,20 @@ recompute_node(PandaNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat) {
   for (int i = 0; i < num_children; i++) {
     PandaNode *child = node->get_child(i);
 
-    /*
-      This needs to be ported to new scene graph.
-    if (arc->has_transition(TransformTransition::get_class_type())) {
-      // This arc has a transform; therefore, we must recompute the
-      // relative matrix from this point.
+    const TransformState *transform = child->get_transform();
+    if (!transform->is_identity()) {
+      // This child node has a transform; therefore, we must recompute
+      // the relative matrix from this point.
       LMatrix4f new_rel_mat;
       bool computed_new_rel_mat = false;
-      recompute_node(arc->get_child(), new_rel_mat, computed_new_rel_mat);
-    } else
-    */
+      recompute_node(WorkingNodePath(np, child), new_rel_mat,
+                     computed_new_rel_mat);
 
-    // This arc has no transform, so we can use the same transform
-    // space from before.
-    recompute_node(child, rel_mat, computed_rel_mat);
+    } else {
+      // This child has no transform, so we can use the same transform
+      // space from before.
+      recompute_node(WorkingNodePath(np, child), rel_mat, computed_rel_mat);
+    }
   }
 }
 
@@ -384,13 +426,13 @@ recompute_node(PandaNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat) {
 //  Description: Recomputes the UV's just for the indicated GeomNode.
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
-recompute_geom_node(GeomNode *node, LMatrix4f &rel_mat, 
+recompute_geom_node(const WorkingNodePath &np, LMatrix4f &rel_mat, 
                     bool &computed_rel_mat) {
+  GeomNode *node = DCAST(GeomNode, np.node());
   if (!computed_rel_mat) {
     // All right, time to compute the matrix.
-    NodePath node_np(node);
-    NodePath projector_np(_projector);
-    rel_mat = node_np.get_mat(projector_np);
+    NodePath true_np = np.get_node_path();
+    rel_mat = true_np.get_mat(_projector);
     computed_rel_mat = true;
   }
 
@@ -415,7 +457,7 @@ recompute_geom(Geom *geom, const LMatrix4f &rel_mat) {
 
   PTA_TexCoordf uvs;
   PTA_ushort color_index;
-  Lens *lens = _projector->get_lens();
+  Lens *lens = _projector_node->get_lens();
   nassertv(lens != (Lens *)NULL);
 
   // Iterate through all the vertices in the Geom.
@@ -455,11 +497,13 @@ recompute_geom(Geom *geom, const LMatrix4f &rel_mat) {
 //               below, and generates a corresponding node hierarchy
 //               with all the geometry copied, but flattened into 2-d,
 //               as seen from the indicated camera.  Returns the newly
-//               created, arc, or NULL if no arc was created.
+//               created node, or NULL if no node was created.
 ////////////////////////////////////////////////////////////////////
 PandaNode *ProjectionScreen::
-make_mesh_node(PandaNode *result_parent, PandaNode *node, LensNode *camera,
+make_mesh_node(PandaNode *result_parent, const WorkingNodePath &np,
+               const NodePath &camera,
                LMatrix4f &rel_mat, bool &computed_rel_mat) {
+  PandaNode *node = np.node();
   if (!node->safe_to_flatten()) {
     // If we can't safely flatten this node, ignore it (and all of its
     // children) completely.  It's got no business being here anyway.
@@ -468,16 +512,14 @@ make_mesh_node(PandaNode *result_parent, PandaNode *node, LensNode *camera,
 
   PT(PandaNode) new_node;
   if (node->is_geom_node()) {
-    new_node =
-      make_mesh_geom_node(DCAST(GeomNode, node), camera,
-                          rel_mat, computed_rel_mat);
+    new_node = make_mesh_geom_node(np, camera, rel_mat, computed_rel_mat);
   } else {
     new_node = node->make_copy();
   }
 
   // Now attach the new node to the result.
   result_parent->add_child(new_node);
-  make_mesh_children(new_node, node, camera, rel_mat, computed_rel_mat);
+  make_mesh_children(new_node, np, camera, rel_mat, computed_rel_mat);
   return new_node;
 }
 
@@ -488,28 +530,30 @@ make_mesh_node(PandaNode *result_parent, PandaNode *node, LensNode *camera,
 //               node, calling make_mesh_node() on each one.
 ////////////////////////////////////////////////////////////////////
 void ProjectionScreen::
-make_mesh_children(PandaNode *new_node, PandaNode *node, LensNode *camera,
+make_mesh_children(PandaNode *new_node, const WorkingNodePath &np,
+                   const NodePath &camera,
                    LMatrix4f &rel_mat, bool &computed_rel_mat) {
+  PandaNode *node = np.node();
   int num_children = node->get_num_children();
   for (int i = 0; i < num_children; i++) {
     PandaNode *child = node->get_child(i);
     PandaNode *new_child;
 
-    /*
-    if (arc->has_transition(TransformTransition::get_class_type())) {
-      // This arc has a transform; therefore, we must recompute the
-      // relative matrix from this point.
+    const TransformState *transform = child->get_transform();
+    if (!transform->is_identity()) {
+      // This child node has a transform; therefore, we must recompute
+      // the relative matrix from this point.
       LMatrix4f new_rel_mat;
       bool computed_new_rel_mat = false;
-      new_arc = make_mesh_node(new_node, arc->get_child(), camera,
-                               new_rel_mat, computed_new_rel_mat);
-    } else
-    */
+      new_child = make_mesh_node(new_node, WorkingNodePath(np, child), camera,
+                                 new_rel_mat, computed_new_rel_mat);
 
-    // This arc has no transform, so we can use the same transform
-    // space from before.
-    new_child = make_mesh_node(new_node, child, camera,
-                               rel_mat, computed_rel_mat);
+    } else {
+      // This child has no transform, so we can use the same transform
+      // space from before.
+      new_child = make_mesh_node(new_node, WorkingNodePath(np, child), camera,
+                                 rel_mat, computed_rel_mat);
+    }
 
     // Copy all of the render state (except TransformState) to the
     // new arc.
@@ -525,15 +569,16 @@ make_mesh_children(PandaNode *new_node, PandaNode *node, LensNode *camera,
 //               indicated camera.
 ////////////////////////////////////////////////////////////////////
 PT(GeomNode) ProjectionScreen::
-make_mesh_geom_node(GeomNode *node, LensNode *camera,
+make_mesh_geom_node(const WorkingNodePath &np, const NodePath &camera,
                     LMatrix4f &rel_mat, bool &computed_rel_mat) {
+  GeomNode *node = DCAST(GeomNode, np.node());
   PT(GeomNode) new_node = new GeomNode(node->get_name());
+  LensNode *lens_node = DCAST(LensNode, camera.node());
 
   if (!computed_rel_mat) {
     // All right, time to compute the matrix.
-    NodePath node_np(node);
-    NodePath camera_np(camera);
-    rel_mat = node_np.get_mat(camera_np);
+    NodePath true_np = np.get_node_path();
+    rel_mat = true_np.get_mat(camera);
     computed_rel_mat = true;
   }
 
@@ -541,7 +586,7 @@ make_mesh_geom_node(GeomNode *node, LensNode *camera,
   for (int i = 0; i < num_geoms; i++) {
     Geom *geom = node->get_geom(i);
     PT(Geom) new_geom = 
-      make_mesh_geom(geom, camera->get_lens(), rel_mat);
+      make_mesh_geom(geom, lens_node->get_lens(), rel_mat);
     if (new_geom != (Geom *)NULL) {
       new_node->add_geom(new_geom, node->get_geom_state(i));
     }

+ 24 - 17
panda/src/distort/projectionScreen.h

@@ -24,8 +24,10 @@
 #include "pandaNode.h"
 #include "lensNode.h"
 #include "geomNode.h"
+#include "nodePath.h"
 
 class Geom;
+class WorkingNodePath;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : ProjectionScreen
@@ -59,16 +61,16 @@ public:
   virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
 
 PUBLISHED:
-  INLINE void set_projector(LensNode *projector);
-  INLINE LensNode *get_projector() const;
-
-  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,
+  void set_projector(const NodePath &projector);
+  INLINE const NodePath &get_projector() const;
+
+  PT(GeomNode) generate_screen(const NodePath &projector,
+                               const string &screen_name,
+                               int num_x_verts, int num_y_verts,
+                               float distance);
+  void regenerate_screen(const NodePath &projector, const string &screen_name,
                          int num_x_verts, int num_y_verts, float distance);
-  PT(PandaNode) make_flat_mesh(LensNode *camera);
+  PT(PandaNode) make_flat_mesh(const NodePath &camera);
 
   INLINE void set_vignette_on(bool vignette_on);
   INLINE bool get_vignette_on() const;
@@ -85,22 +87,27 @@ public:
 
 private:
   void recompute_if_stale();
-  void recompute_node(PandaNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat);
-  void recompute_geom_node(GeomNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat);
+  void do_recompute(const NodePath &this_np);
+  void recompute_node(const WorkingNodePath &np, LMatrix4f &rel_mat, bool &computed_rel_mat);
+  void recompute_geom_node(const WorkingNodePath &np, LMatrix4f &rel_mat, bool &computed_rel_mat);
   void recompute_geom(Geom *geom, const LMatrix4f &rel_mat);
 
   PandaNode *
-  make_mesh_node(PandaNode *result_parent, PandaNode *node, LensNode *camera,
+  make_mesh_node(PandaNode *result_parent, const WorkingNodePath &np,
+                 const NodePath &camera,
                  LMatrix4f &rel_mat, bool &computed_rel_mat);
-  void make_mesh_children(PandaNode *new_node, PandaNode *node, 
-                          LensNode *camera,
+  void make_mesh_children(PandaNode *new_node, const WorkingNodePath &np,
+                          const NodePath &camera,
                           LMatrix4f &rel_mat, bool &computed_rel_mat);
-  PT(GeomNode) make_mesh_geom_node(GeomNode *node, LensNode *camera,
-                                     LMatrix4f &rel_mat, bool &computed_rel_mat);
+  PT(GeomNode) make_mesh_geom_node(const WorkingNodePath &np, 
+                                   const NodePath &camera,
+                                   LMatrix4f &rel_mat,
+                                   bool &computed_rel_mat);
   PT(Geom) make_mesh_geom(Geom *geom, Lens *lens, LMatrix4f &rel_mat);
 
 
-  PT(LensNode) _projector;
+  NodePath _projector;
+  PT(LensNode) _projector_node;
   bool _vignette_on;
   Colorf _vignette_color;
   Colorf _frame_color;