浏览代码

Further optimizations to the cull pipeline.
The only transform still stored in CullableObject is internal transform.

NB: I haven't tested my PipeOcclusionCullTraverser changes. Please contact me if you encounter problems with it.

rdb 11 年之前
父节点
当前提交
0ad0d4ec33
共有 38 个文件被更改,包括 436 次插入403 次删除
  1. 21 25
      panda/src/collide/collisionVisualizer.cxx
  2. 4 4
      panda/src/cull/cullBinBackToFront.cxx
  3. 4 4
      panda/src/cull/cullBinFrontToBack.cxx
  4. 2 2
      panda/src/cull/cullBinStateSorted.I
  5. 3 0
      panda/src/display/graphicsEngine.cxx
  6. 1 1
      panda/src/display/graphicsStateGuardian.I
  7. 5 5
      panda/src/display/graphicsStateGuardian.cxx
  8. 13 0
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  9. 2 0
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  10. 69 53
      panda/src/grutil/pipeOcclusionCullTraverser.cxx
  11. 10 9
      panda/src/grutil/pipeOcclusionCullTraverser.h
  12. 3 3
      panda/src/gsgbase/graphicsStateGuardianBase.h
  13. 58 66
      panda/src/parametrics/ropeNode.cxx
  14. 18 20
      panda/src/parametrics/sheetNode.cxx
  15. 2 2
      panda/src/pgraph/cullBin.cxx
  16. 3 4
      panda/src/pgraph/cullHandler.cxx
  17. 21 22
      panda/src/pgraph/cullPlanes.cxx
  18. 8 13
      panda/src/pgraph/cullTraverser.cxx
  19. 3 6
      panda/src/pgraph/cullTraverser.h
  20. 22 0
      panda/src/pgraph/cullTraverserData.I
  21. 0 11
      panda/src/pgraph/cullTraverserData.cxx
  22. 8 5
      panda/src/pgraph/cullTraverserData.h
  23. 0 30
      panda/src/pgraph/cullableObject.I
  24. 19 17
      panda/src/pgraph/cullableObject.cxx
  25. 0 8
      panda/src/pgraph/cullableObject.h
  26. 2 5
      panda/src/pgraph/geomNode.cxx
  27. 1 0
      panda/src/pgraph/geomNode.h
  28. 27 0
      panda/src/pgraph/nodePath.I
  29. 5 0
      panda/src/pgraph/nodePath.h
  30. 6 10
      panda/src/pgraph/occluderNode.cxx
  31. 6 8
      panda/src/pgraph/planeNode.cxx
  32. 25 0
      panda/src/pgraph/sceneSetup.I
  33. 4 0
      panda/src/pgraph/sceneSetup.h
  34. 3 5
      panda/src/pgraphnodes/callbackNode.cxx
  35. 2 4
      panda/src/pgraphnodes/computeNode.cxx
  36. 2 4
      panda/src/pgraphnodes/nodeCullCallbackData.cxx
  37. 4 5
      panda/src/rocket/rocketRenderInterface.cxx
  38. 50 52
      panda/src/speedtree/speedTreeNode.cxx

+ 21 - 25
panda/src/collide/collisionVisualizer.cxx

@@ -122,14 +122,14 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
     const VizInfo &viz_info = (*di).second;
     const VizInfo &viz_info = (*di).second;
 
 
     CullTraverserData xform_data(data);
     CullTraverserData xform_data(data);
-    
+
     // We don't want to inherit the transform from above!  We ignore
     // We don't want to inherit the transform from above!  We ignore
     // whatever transforms were above the CollisionVisualizer node; it
     // whatever transforms were above the CollisionVisualizer node; it
     // always renders its objects according to their appropriate net
     // always renders its objects according to their appropriate net
     // transform.
     // transform.
     xform_data._net_transform = TransformState::make_identity();
     xform_data._net_transform = TransformState::make_identity();
     xform_data._view_frustum = trav->get_view_frustum();
     xform_data._view_frustum = trav->get_view_frustum();
-    xform_data.apply_transform_and_state(trav, net_transform, 
+    xform_data.apply_transform_and_state(trav, net_transform,
                                          RenderState::make_empty(),
                                          RenderState::make_empty(),
                                          RenderEffects::make_empty(),
                                          RenderEffects::make_empty(),
                                          ClipPlaneAttrib::make());
                                          ClipPlaneAttrib::make());
@@ -148,7 +148,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       PT(PandaNode) node = solid->get_viz(trav, xform_data, !was_detected);
       PT(PandaNode) node = solid->get_viz(trav, xform_data, !was_detected);
       if (node != (PandaNode *)NULL) {
       if (node != (PandaNode *)NULL) {
         CullTraverserData next_data(xform_data, node);
         CullTraverserData next_data(xform_data, node);
-        
+
         // We don't want to inherit the render state from above for
         // We don't want to inherit the render state from above for
         // these guys.
         // these guys.
         next_data._state = get_viz_state();
         next_data._state = get_viz_state();
@@ -161,16 +161,16 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       CPT(RenderState) empty_state = RenderState::make_empty();
       CPT(RenderState) empty_state = RenderState::make_empty();
       CPT(RenderState) point_state = RenderState::make(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, 1.0f, false));
       CPT(RenderState) point_state = RenderState::make(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, 1.0f, false));
 
 
-      PT(GeomVertexArrayFormat) point_array_format = 
+      PT(GeomVertexArrayFormat) point_array_format =
         new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
         new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
                                   Geom::NT_stdfloat, Geom::C_point,
                                   Geom::NT_stdfloat, Geom::C_point,
                                   InternalName::get_color(), 1,
                                   InternalName::get_color(), 1,
                                   Geom::NT_packed_dabc, Geom::C_color,
                                   Geom::NT_packed_dabc, Geom::C_color,
-                                  InternalName::get_size(), 1, 
+                                  InternalName::get_size(), 1,
                                   Geom::NT_stdfloat, Geom::C_other);
                                   Geom::NT_stdfloat, Geom::C_other);
-      CPT(GeomVertexFormat) point_format = 
+      CPT(GeomVertexFormat) point_format =
         GeomVertexFormat::register_format(point_array_format);
         GeomVertexFormat::register_format(point_array_format);
-        
+
       Points::const_iterator pi;
       Points::const_iterator pi;
       for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
       for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
         const CollisionPoint &point = (*pi);
         const CollisionPoint &point = (*pi);
@@ -178,9 +178,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
         // Draw a small red point at the surface point, and a smaller
         // Draw a small red point at the surface point, and a smaller
         // white point at the interior point.
         // white point at the interior point.
         {
         {
-          PT(GeomVertexData) point_vdata = 
+          PT(GeomVertexData) point_vdata =
             new GeomVertexData("viz", point_format, Geom::UH_stream);
             new GeomVertexData("viz", point_format, Geom::UH_stream);
-          
+
           PT(GeomPoints) points = new GeomPoints(Geom::UH_stream);
           PT(GeomPoints) points = new GeomPoints(Geom::UH_stream);
 
 
           GeomVertexWriter vertex(point_vdata, InternalName::get_vertex());
           GeomVertexWriter vertex(point_vdata, InternalName::get_vertex());
@@ -203,19 +203,17 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
 
 
           PT(Geom) geom = new Geom(point_vdata);
           PT(Geom) geom = new Geom(point_vdata);
           geom->add_primitive(points);
           geom->add_primitive(points);
-            
-          CullableObject *object = 
-            new CullableObject(geom, point_state, 
-                               xform_data.get_net_transform(trav),
-                               xform_data.get_modelview_transform(trav),
-                               trav->get_scene());
-          
+
+          CullableObject *object =
+            new CullableObject(geom, point_state,
+                               xform_data.get_internal_transform(trav));
+
           trav->get_cull_handler()->record_object(object, trav);
           trav->get_cull_handler()->record_object(object, trav);
         }
         }
 
 
         // Draw the normal vector at the surface point.
         // Draw the normal vector at the surface point.
         if (!point._surface_normal.almost_equal(LVector3::zero())) {
         if (!point._surface_normal.almost_equal(LVector3::zero())) {
-          PT(GeomVertexData) line_vdata = 
+          PT(GeomVertexData) line_vdata =
             new GeomVertexData("viz", GeomVertexFormat::get_v3cp(),
             new GeomVertexData("viz", GeomVertexFormat::get_v3cp(),
                                Geom::UH_stream);
                                Geom::UH_stream);
 
 
@@ -225,7 +223,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
           GeomVertexWriter color(line_vdata, InternalName::get_color());
           GeomVertexWriter color(line_vdata, InternalName::get_color());
 
 
           vertex.add_data3(point._surface_point);
           vertex.add_data3(point._surface_point);
-          vertex.add_data3(point._surface_point + 
+          vertex.add_data3(point._surface_point +
                             point._surface_normal * _normal_scale);
                             point._surface_normal * _normal_scale);
           color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
           color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
           color.add_data4(1.0f, 1.0f, 1.0f, 1.0f);
           color.add_data4(1.0f, 1.0f, 1.0f, 1.0f);
@@ -234,13 +232,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
 
 
           PT(Geom) geom = new Geom(line_vdata);
           PT(Geom) geom = new Geom(line_vdata);
           geom->add_primitive(lines);
           geom->add_primitive(lines);
-          
-          CullableObject *object = 
-            new CullableObject(geom, empty_state, 
-                               xform_data.get_net_transform(trav),
-                               xform_data.get_modelview_transform(trav),
-                               trav->get_scene());
-          
+
+          CullableObject *object =
+            new CullableObject(geom, empty_state,
+                               xform_data.get_internal_transform(trav));
+
           trav->get_cull_handler()->record_object(object, trav);
           trav->get_cull_handler()->record_object(object, trav);
         }
         }
       }
       }

+ 4 - 4
panda/src/cull/cullBinBackToFront.cxx

@@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) {
 
 
   const GeometricBoundingVolume *gbv;
   const GeometricBoundingVolume *gbv;
   DCAST_INTO_V(gbv, volume);
   DCAST_INTO_V(gbv, volume);
-  
+
   LPoint3 center = gbv->get_approx_center();
   LPoint3 center = gbv->get_approx_center();
-  nassertv(object->_modelview_transform != (const TransformState *)NULL);
-  center = center * object->_modelview_transform->get_mat();
-  
+  nassertv(object->_internal_transform != (const TransformState *)NULL);
+  center = center * object->_internal_transform->get_mat();
+
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   _objects.push_back(ObjectData(object, distance));
   _objects.push_back(ObjectData(object, distance));
 }
 }

+ 4 - 4
panda/src/cull/cullBinFrontToBack.cxx

@@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) {
 
 
   const GeometricBoundingVolume *gbv;
   const GeometricBoundingVolume *gbv;
   DCAST_INTO_V(gbv, volume);
   DCAST_INTO_V(gbv, volume);
-  
+
   LPoint3 center = gbv->get_approx_center();
   LPoint3 center = gbv->get_approx_center();
-  nassertv(object->_modelview_transform != (const TransformState *)NULL);
-  center = center * object->_modelview_transform->get_mat();
-  
+  nassertv(object->_internal_transform != (const TransformState *)NULL);
+  center = center * object->_internal_transform->get_mat();
+
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   _objects.push_back(ObjectData(object, distance));
   _objects.push_back(ObjectData(object, distance));
 }
 }

+ 2 - 2
panda/src/cull/cullBinStateSorted.I

@@ -47,8 +47,8 @@ INLINE bool CullBinStateSorted::ObjectData::
 operator < (const ObjectData &other) const {
 operator < (const ObjectData &other) const {
   // First group objects by transform, since transform changes are
   // First group objects by transform, since transform changes are
   // supposed to be expensive.
   // supposed to be expensive.
-  if (_object->_modelview_transform != other._object->_modelview_transform) {
-    return _object->_modelview_transform < other._object->_modelview_transform;
+  if (_object->_internal_transform != other._object->_internal_transform) {
+    return _object->_internal_transform < other._object->_internal_transform;
   }
   }
 
 
   // Then group by other state changes, in approximate order from
   // Then group by other state changes, in approximate order from

+ 3 - 0
panda/src/display/graphicsEngine.cxx

@@ -1994,6 +1994,9 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
   CPT(TransformState) cs_transform = gsg->get_cs_transform_for(lens->get_coordinate_system());
   CPT(TransformState) cs_transform = gsg->get_cs_transform_for(lens->get_coordinate_system());
   scene_setup->set_cs_transform(cs_transform);
   scene_setup->set_cs_transform(cs_transform);
 
 
+  CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
+  scene_setup->set_cs_world_transform(cs_world_transform);
+
   return scene_setup;
   return scene_setup;
 }
 }
 
 

+ 1 - 1
panda/src/display/graphicsStateGuardian.I

@@ -204,7 +204,7 @@ set_loader(Loader *loader) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_loader
 //     Function: GraphicsStateGuardian::get_loader
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Returns the Loader object that will be used by this
 //  Description: Returns the Loader object that will be used by this
 //               GSG to load textures when necessary, if
 //               GSG to load textures when necessary, if
 //               get_incomplete_render() is true.
 //               get_incomplete_render() is true.

+ 5 - 5
panda/src/display/graphicsStateGuardian.cxx

@@ -878,14 +878,14 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::compute_distance_to
 //     Function: GraphicsStateGuardian::compute_distance_to
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: This function may only be called during a render
-//               traversal; it will compute the distance to the
+//  Description: This function will compute the distance to the
 //               indicated point, assumed to be in eye coordinates,
 //               indicated point, assumed to be in eye coordinates,
-//               from the camera plane.
+//               from the camera plane.  The point is assumed to be
+//               in the GSG's internal coordinate system.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PN_stdfloat GraphicsStateGuardian::
 PN_stdfloat GraphicsStateGuardian::
 compute_distance_to(const LPoint3 &point) const {
 compute_distance_to(const LPoint3 &point) const {
-  switch (_coordinate_system) {
+  switch (_internal_coordinate_system) {
   case CS_zup_right:
   case CS_zup_right:
     return point[1];
     return point[1];
 
 
@@ -901,7 +901,7 @@ compute_distance_to(const LPoint3 &point) const {
   default:
   default:
     gsg_cat.error()
     gsg_cat.error()
       << "Invalid coordinate system in compute_distance_to: "
       << "Invalid coordinate system in compute_distance_to: "
-      << (int)_coordinate_system << "\n";
+      << (int)_internal_coordinate_system << "\n";
     return 0.0f;
     return 0.0f;
   }
   }
 }
 }

+ 13 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -5157,6 +5157,19 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
   return GeomMunger::register_munger(munger, current_thread);
   return GeomMunger::register_munger(munger, current_thread);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::compute_distance_to
+//       Access: Public, Virtual
+//  Description: This function will compute the distance to the
+//               indicated point, assumed to be in eye coordinates,
+//               from the camera plane.  The point is assumed to be
+//               in the GSG's internal coordinate system.
+////////////////////////////////////////////////////////////////////
+PN_stdfloat GLGraphicsStateGuardian::
+compute_distance_to(const LPoint3 &point) const {
+  return -point[2];
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::framebuffer_copy_to_texture
 //     Function: GLGraphicsStateGuardian::framebuffer_copy_to_texture
 //       Access: Public, Virtual
 //       Access: Public, Virtual

+ 2 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -326,6 +326,8 @@ public:
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
                                           Thread *current_thread);
                                           Thread *current_thread);
 
 
+  virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const;
+
   virtual void clear(DrawableRegion *region);
   virtual void clear(DrawableRegion *region);
 
 
   virtual bool framebuffer_copy_to_texture
   virtual bool framebuffer_copy_to_texture

+ 69 - 53
panda/src/grutil/pipeOcclusionCullTraverser.cxx

@@ -76,7 +76,7 @@ static ConfigVariableInt occlusion_depth_bits
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipeOcclusionCullTraverser::Constructor
 //     Function: PipeOcclusionCullTraverser::Constructor
 //       Access: Published
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PipeOcclusionCullTraverser::
 PipeOcclusionCullTraverser::
 PipeOcclusionCullTraverser(GraphicsOutput *host) {
 PipeOcclusionCullTraverser(GraphicsOutput *host) {
@@ -103,7 +103,7 @@ PipeOcclusionCullTraverser(GraphicsOutput *host) {
     win_prop.set_size(occlusion_size[0], occlusion_size[1]);
     win_prop.set_size(occlusion_size[0], occlusion_size[1]);
   }
   }
 
 
-  _buffer = engine->make_output(pipe, "occlusion", 0, fb_prop, win_prop, 
+  _buffer = engine->make_output(pipe, "occlusion", 0, fb_prop, win_prop,
                                 GraphicsPipe::BF_refuse_window,
                                 GraphicsPipe::BF_refuse_window,
                                 gsg, host->get_host());
                                 gsg, host->get_host());
   nassertv(_buffer != (GraphicsOutput *)NULL);
   nassertv(_buffer != (GraphicsOutput *)NULL);
@@ -125,7 +125,7 @@ PipeOcclusionCullTraverser(GraphicsOutput *host) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipeOcclusionCullTraverser::Copy Constructor
 //     Function: PipeOcclusionCullTraverser::Copy Constructor
 //       Access: Published
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PipeOcclusionCullTraverser::
 PipeOcclusionCullTraverser::
 PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser &copy) :
 PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser &copy) :
@@ -137,7 +137,7 @@ PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipeOcclusionCullTraverser::set_scene
 //     Function: PipeOcclusionCullTraverser::set_scene
 //       Access: Published, Virtual
 //       Access: Published, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PipeOcclusionCullTraverser::
 void PipeOcclusionCullTraverser::
 set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
 set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
@@ -154,7 +154,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
 
 
   Thread *current_thread = get_current_thread();
   Thread *current_thread = get_current_thread();
   if (!_buffer->begin_frame(GraphicsOutput::FM_render, current_thread)) {
   if (!_buffer->begin_frame(GraphicsOutput::FM_render, current_thread)) {
-    cerr << "begin_frame failed\n";
+    grutil_cat.error() << "begin_frame failed\n";
     return;
     return;
   }
   }
   _buffer->clear(current_thread);
   _buffer->clear(current_thread);
@@ -166,7 +166,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
 
 
   _scene = new SceneSetup(*scene_setup);
   _scene = new SceneSetup(*scene_setup);
   _scene->set_display_region(_display_region);
   _scene->set_display_region(_display_region);
-  _scene->set_viewport_size(_display_region->get_pixel_width(), 
+  _scene->set_viewport_size(_display_region->get_pixel_width(),
                             _display_region->get_pixel_height());
                             _display_region->get_pixel_height());
 
 
   if (_scene->get_cull_center() != _scene->get_camera_path()) {
   if (_scene->get_cull_center() != _scene->get_camera_path()) {
@@ -177,13 +177,22 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
     NodePath scene_parent = _scene->get_scene_root().get_parent(current_thread);
     NodePath scene_parent = _scene->get_scene_root().get_parent(current_thread);
     CPT(TransformState) camera_transform = cull_center.get_transform(scene_parent, current_thread);
     CPT(TransformState) camera_transform = cull_center.get_transform(scene_parent, current_thread);
     CPT(TransformState) world_transform = scene_parent.get_transform(cull_center, current_thread);
     CPT(TransformState) world_transform = scene_parent.get_transform(cull_center, current_thread);
+    CPT(TransformState) cs_world_transform = _scene->get_cs_transform()->compose(world_transform);
     _scene->set_camera_transform(camera_transform);
     _scene->set_camera_transform(camera_transform);
     _scene->set_world_transform(world_transform);
     _scene->set_world_transform(world_transform);
+    _scene->set_cs_world_transform(cs_world_transform);
+
+    // We use this to recover the original net_transform.
+    _inv_cs_world_transform = cs_world_transform->get_inverse();
+  } else {
+    _inv_cs_world_transform = _scene->get_cs_world_transform()->get_inverse();
   }
   }
-    
+
+  nassertv(_scene->get_cs_transform() == scene_setup->get_cs_transform());
+
   gsg->set_scene(_scene);
   gsg->set_scene(_scene);
   if (!gsg->begin_scene()) {
   if (!gsg->begin_scene()) {
-    cerr << "begin_scene failed\n";
+    grutil_cat.error() << "begin_scene failed\n";
     return;
     return;
   }
   }
 
 
@@ -202,7 +211,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase,
 
 
   _current_query = NULL;
   _current_query = NULL;
   _next_query = NULL;
   _next_query = NULL;
-  
+
   // Begin by rendering all the occluders into our internal scene.
   // Begin by rendering all the occluders into our internal scene.
   PStatTimer timer2(_draw_occlusion_pcollector);
   PStatTimer timer2(_draw_occlusion_pcollector);
   _internal_trav->traverse(_scene->get_scene_root());
   _internal_trav->traverse(_scene->get_scene_root());
@@ -299,7 +308,7 @@ get_texture() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipeOcclusionCullTraverser::is_in_view
 //     Function: PipeOcclusionCullTraverser::is_in_view
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PipeOcclusionCullTraverser::
 bool PipeOcclusionCullTraverser::
 is_in_view(CullTraverserData &data) {
 is_in_view(CullTraverserData &data) {
@@ -335,12 +344,12 @@ is_in_view(CullTraverserData &data) {
 
 
     CPT(BoundingVolume) vol = node_reader->get_bounds();
     CPT(BoundingVolume) vol = node_reader->get_bounds();
     CPT(TransformState) net_transform = data.get_net_transform(this);
     CPT(TransformState) net_transform = data.get_net_transform(this);
-    CPT(TransformState) modelview_transform;
+    CPT(TransformState) internal_transform;
 
 
     CPT(Geom) geom;
     CPT(Geom) geom;
-    if (get_volume_viz(vol, geom, net_transform, modelview_transform)) {
-      _next_query = 
-        perform_occlusion_test(geom, net_transform, modelview_transform);
+    if (get_volume_viz(vol, geom, net_transform, internal_transform)) {
+      _next_query =
+        perform_occlusion_test(geom, net_transform, internal_transform);
     }
     }
   }
   }
 
 
@@ -408,12 +417,12 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
   } else {
   } else {
     // Issue an occlusion test for this object.
     // Issue an occlusion test for this object.
     CPT(BoundingVolume) vol = object->_geom->get_bounds(current_thread);
     CPT(BoundingVolume) vol = object->_geom->get_bounds(current_thread);
-    CPT(TransformState) net_transform = object->_net_transform;
-    CPT(TransformState) modelview_transform;
+    CPT(TransformState) net_transform = _inv_cs_world_transform->compose(object->_internal_transform);
+    CPT(TransformState) internal_transform;
     CPT(Geom) geom;
     CPT(Geom) geom;
-    if (get_volume_viz(vol, geom, net_transform, modelview_transform)) {
-      pobj._query = 
-        perform_occlusion_test(geom, net_transform, modelview_transform);
+    if (get_volume_viz(vol, geom, net_transform, internal_transform)) {
+      pobj._query =
+        perform_occlusion_test(geom, net_transform, internal_transform);
     }
     }
   }
   }
 
 
@@ -437,7 +446,7 @@ make_sphere() {
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("occlusion_sphere", GeomVertexFormat::get_v3(), Geom::UH_static);
     ("occlusion_sphere", GeomVertexFormat::get_v3(), Geom::UH_static);
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
-  
+
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
   for (int sl = 0; sl < num_slices; ++sl) {
   for (int sl = 0; sl < num_slices; ++sl) {
     PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
     PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
@@ -449,11 +458,11 @@ make_sphere() {
       vertex.add_data3(compute_sphere_point(latitude, longitude1));
       vertex.add_data3(compute_sphere_point(latitude, longitude1));
     }
     }
     vertex.add_data3(compute_sphere_point(1.0, longitude0));
     vertex.add_data3(compute_sphere_point(1.0, longitude0));
-    
+
     strip->add_next_vertices(num_stacks * 2);
     strip->add_next_vertices(num_stacks * 2);
     strip->close_primitive();
     strip->close_primitive();
   }
   }
-  
+
   _sphere_geom = new Geom(vdata);
   _sphere_geom = new Geom(vdata);
   _sphere_geom->add_primitive(strip);
   _sphere_geom->add_primitive(strip);
 }
 }
@@ -462,7 +471,7 @@ make_sphere() {
 //     Function: PipeOcclusionCullTraverser::compute_sphere_point
 //     Function: PipeOcclusionCullTraverser::compute_sphere_point
 //       Access: Private, Static
 //       Access: Private, Static
 //  Description: Returns a point on the surface of the unit sphere.
 //  Description: Returns a point on the surface of the unit sphere.
-//               latitude and longitude range from 0.0 to 1.0.  
+//               latitude and longitude range from 0.0 to 1.0.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 LVertex PipeOcclusionCullTraverser::
 LVertex PipeOcclusionCullTraverser::
 compute_sphere_point(PN_stdfloat latitude, PN_stdfloat longitude) {
 compute_sphere_point(PN_stdfloat latitude, PN_stdfloat longitude) {
@@ -487,7 +496,7 @@ make_box() {
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static);
     ("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static);
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
-  
+
   vertex.add_data3(0.0f, 0.0f, 0.0f);
   vertex.add_data3(0.0f, 0.0f, 0.0f);
   vertex.add_data3(0.0f, 0.0f, 1.0f);
   vertex.add_data3(0.0f, 0.0f, 1.0f);
   vertex.add_data3(0.0f, 1.0f, 0.0f);
   vertex.add_data3(0.0f, 1.0f, 0.0f);
@@ -496,7 +505,7 @@ make_box() {
   vertex.add_data3(1.0f, 0.0f, 1.0f);
   vertex.add_data3(1.0f, 0.0f, 1.0f);
   vertex.add_data3(1.0f, 1.0f, 0.0f);
   vertex.add_data3(1.0f, 1.0f, 0.0f);
   vertex.add_data3(1.0f, 1.0f, 1.0f);
   vertex.add_data3(1.0f, 1.0f, 1.0f);
-    
+
   PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
   PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
   tris->add_vertices(0, 4, 5);
   tris->add_vertices(0, 4, 5);
   tris->close_primitive();
   tris->close_primitive();
@@ -522,7 +531,7 @@ make_box() {
   tris->close_primitive();
   tris->close_primitive();
   tris->add_vertices(2, 4, 0);
   tris->add_vertices(2, 4, 0);
   tris->close_primitive();
   tris->close_primitive();
-  
+
   _box_geom = new Geom(vdata);
   _box_geom = new Geom(vdata);
   _box_geom->add_primitive(tris);
   _box_geom->add_primitive(tris);
 }
 }
@@ -554,14 +563,14 @@ make_solid_test_state() {
 //               transform to the bounding volume.  On exit (when
 //               transform to the bounding volume.  On exit (when
 //               return value is true), it will be composed with a
 //               return value is true), it will be composed with a
 //               suitable local transform to render the bounding
 //               suitable local transform to render the bounding
-//               volume properly, and modelview_transform will also be
+//               volume properly, and internal_transform will also be
 //               filled with the appropriate transform.
 //               filled with the appropriate transform.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PipeOcclusionCullTraverser::
 bool PipeOcclusionCullTraverser::
-get_volume_viz(const BoundingVolume *vol, 
+get_volume_viz(const BoundingVolume *vol,
                CPT(Geom) &geom,  // OUT
                CPT(Geom) &geom,  // OUT
                CPT(TransformState) &net_transform, // IN-OUT
                CPT(TransformState) &net_transform, // IN-OUT
-               CPT(TransformState) &modelview_transform  // OUT
+               CPT(TransformState) &internal_transform  // OUT
                ) {
                ) {
   if (vol->is_infinite() || vol->is_empty()) {
   if (vol->is_infinite() || vol->is_empty()) {
     return false;
     return false;
@@ -569,13 +578,14 @@ get_volume_viz(const BoundingVolume *vol,
 
 
   if (vol->is_exact_type(BoundingSphere::get_class_type())) {
   if (vol->is_exact_type(BoundingSphere::get_class_type())) {
     const BoundingSphere *sphere = DCAST(BoundingSphere, vol);
     const BoundingSphere *sphere = DCAST(BoundingSphere, vol);
-    CPT(TransformState) local_transform = 
+    CPT(TransformState) local_transform =
       TransformState::make_pos_hpr_scale(sphere->get_center(),
       TransformState::make_pos_hpr_scale(sphere->get_center(),
                                          LVecBase3(0, 0, 0),
                                          LVecBase3(0, 0, 0),
                                          sphere->get_radius());
                                          sphere->get_radius());
     net_transform = net_transform->compose(local_transform);
     net_transform = net_transform->compose(local_transform);
 
 
-    modelview_transform = _internal_trav->get_world_transform()->compose(net_transform);
+    CPT(TransformState) modelview_transform =
+      _internal_trav->get_world_transform()->compose(net_transform);
 
 
     // See if the bounding sphere is clipped by the near plane.  If it
     // See if the bounding sphere is clipped by the near plane.  If it
     // is, the occlusion test may fail, so we won't bother performing
     // is, the occlusion test may fail, so we won't bother performing
@@ -587,19 +597,24 @@ get_volume_viz(const BoundingVolume *vol,
       return false;
       return false;
     }
     }
 
 
+    // Construct the internal transform for the internal traverser.
+    internal_transform = _internal_trav->get_scene()->
+      get_cs_transform()->compose(modelview_transform);
+
     // The sphere looks good.
     // The sphere looks good.
     geom = _sphere_geom;
     geom = _sphere_geom;
     return true;
     return true;
 
 
   } else if (vol->is_exact_type(BoundingBox::get_class_type())) {
   } else if (vol->is_exact_type(BoundingBox::get_class_type())) {
     const BoundingBox *box = DCAST(BoundingBox, vol);
     const BoundingBox *box = DCAST(BoundingBox, vol);
-    CPT(TransformState) local_transform = 
+    CPT(TransformState) local_transform =
       TransformState::make_pos_hpr_scale(box->get_minq(),
       TransformState::make_pos_hpr_scale(box->get_minq(),
                                          LVecBase3(0, 0, 0),
                                          LVecBase3(0, 0, 0),
                                          box->get_maxq() - box->get_minq());
                                          box->get_maxq() - box->get_minq());
     net_transform = net_transform->compose(local_transform);
     net_transform = net_transform->compose(local_transform);
 
 
-    modelview_transform = _internal_trav->get_world_transform()->compose(net_transform);
+    CPT(TransformState) modelview_transform =
+      _internal_trav->get_world_transform()->compose(net_transform);
 
 
     // See if the bounding box is clipped by the near plane.  If it
     // See if the bounding box is clipped by the near plane.  If it
     // is, the occlusion test may fail, so we won't bother performing
     // is, the occlusion test may fail, so we won't bother performing
@@ -623,6 +638,10 @@ get_volume_viz(const BoundingVolume *vol,
       }
       }
     }
     }
 
 
+    // Construct the internal transform for the internal traverser.
+    internal_transform = _internal_trav->get_scene()->
+      get_cs_transform()->compose(modelview_transform);
+
     // The box looks good.
     // The box looks good.
     geom = _box_geom;
     geom = _box_geom;
     return true;
     return true;
@@ -640,7 +659,7 @@ get_volume_viz(const BoundingVolume *vol,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(OcclusionQueryContext) PipeOcclusionCullTraverser::
 PT(OcclusionQueryContext) PipeOcclusionCullTraverser::
 perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
 perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
-                       const TransformState *modelview_transform) {
+                       const TransformState *internal_transform) {
   _occlusion_tests_pcollector.add_level(1);
   _occlusion_tests_pcollector.add_level(1);
   PStatTimer timer(_test_occlusion_pcollector);
   PStatTimer timer(_test_occlusion_pcollector);
 
 
@@ -648,9 +667,8 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
 
 
   gsg->begin_occlusion_query();
   gsg->begin_occlusion_query();
 
 
-  CullableObject *viz = 
-    new CullableObject(geom, _solid_test_state,
-                       net_transform, modelview_transform, get_scene());
+  CullableObject *viz =
+    new CullableObject(geom, _solid_test_state, internal_transform);
 
 
   static ConfigVariableBool test_occlude("test-occlude", false);
   static ConfigVariableBool test_occlude("test-occlude", false);
   if (test_occlude) {
   if (test_occlude) {
@@ -658,16 +676,16 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
   } else {
   } else {
     _internal_cull_handler->record_object(viz, _internal_trav);
     _internal_cull_handler->record_object(viz, _internal_trav);
   }
   }
-  
+
   PT(OcclusionQueryContext) query = gsg->end_occlusion_query();
   PT(OcclusionQueryContext) query = gsg->end_occlusion_query();
-    
+
   if (show_occlusion) {
   if (show_occlusion) {
     // Show the results of the occlusion.  To do this, we need to get
     // Show the results of the occlusion.  To do this, we need to get
     // the results of the query immediately.  This will stall the
     // the results of the query immediately.  This will stall the
     // pipe, but we're rendering a debug effect, so we don't mind too
     // pipe, but we're rendering a debug effect, so we don't mind too
     // much.
     // much.
     int num_fragments = query->get_num_fragments();
     int num_fragments = query->get_num_fragments();
-    show_results(num_fragments, geom, net_transform, modelview_transform);
+    show_results(num_fragments, geom, net_transform, internal_transform);
   }
   }
 
 
   return query;
   return query;
@@ -680,18 +698,18 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
 //               test for a particular bounding volume.
 //               test for a particular bounding volume.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PipeOcclusionCullTraverser::
 void PipeOcclusionCullTraverser::
-show_results(int num_fragments, const Geom *geom, 
-             const TransformState *net_transform, 
-             const TransformState *modelview_transform) {
+show_results(int num_fragments, const Geom *geom,
+             const TransformState *net_transform,
+             const TransformState *internal_transform) {
   LColor color;
   LColor color;
   if (num_fragments == 0) {
   if (num_fragments == 0) {
     // Magenta: culled
     // Magenta: culled
-    color.set(0.8f, 0.0f, 1.0f, 0.4);
+    color.set(0.8f, 0.0f, 1.0f, 0.4f);
   } else {
   } else {
     // Yellow: visible
     // Yellow: visible
-    color.set(1.0f, 1.0f, 0.5f, 0.4);
+    color.set(1.0f, 1.0f, 0.5f, 0.4f);
   }
   }
-  
+
   CPT(RenderState) state = RenderState::make
   CPT(RenderState) state = RenderState::make
     (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
     (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
      DepthTestAttrib::make(DepthTestAttrib::M_less),
      DepthTestAttrib::make(DepthTestAttrib::M_less),
@@ -700,15 +718,13 @@ show_results(int num_fragments, const Geom *geom,
 
 
   GraphicsStateGuardian *gsg = _buffer->get_gsg();
   GraphicsStateGuardian *gsg = _buffer->get_gsg();
 
 
-  CullableObject *internal_viz = 
-    new CullableObject(geom, state,
-                       net_transform, modelview_transform, get_scene());
+  CullableObject *internal_viz =
+    new CullableObject(geom, state, internal_transform);
   _internal_cull_handler->record_object(internal_viz, _internal_trav);
   _internal_cull_handler->record_object(internal_viz, _internal_trav);
 
 
   // Also render the viz in the main scene.
   // Also render the viz in the main scene.
-  modelview_transform = get_world_transform()->compose(net_transform);
-  CullableObject *main_viz = 
-    new CullableObject(geom, state,
-                       net_transform, modelview_transform, get_scene());
+  internal_transform = get_scene()->get_cs_world_transform()->compose(net_transform);
+  CullableObject *main_viz =
+    new CullableObject(geom, state, internal_transform);
   _true_cull_handler->record_object(main_viz, this);
   _true_cull_handler->record_object(main_viz, this);
 }
 }

+ 10 - 9
panda/src/grutil/pipeOcclusionCullTraverser.h

@@ -75,19 +75,19 @@ private:
 
 
   void make_solid_test_state();
   void make_solid_test_state();
 
 
-  bool get_volume_viz(const BoundingVolume *vol, 
+  bool get_volume_viz(const BoundingVolume *vol,
                       CPT(Geom) &geom,  // OUT
                       CPT(Geom) &geom,  // OUT
                       CPT(TransformState) &net_transform, // IN-OUT
                       CPT(TransformState) &net_transform, // IN-OUT
-                      CPT(TransformState) &modelview_transform  // OUT
+                      CPT(TransformState) &internal_transform  // OUT
                       );
                       );
-  PT(OcclusionQueryContext) 
-    perform_occlusion_test(const Geom *geom, 
+  PT(OcclusionQueryContext)
+    perform_occlusion_test(const Geom *geom,
                            const TransformState *net_transform,
                            const TransformState *net_transform,
-                           const TransformState *modelview_transform);
+                           const TransformState *internal_transform);
 
 
-  void show_results(int num_fragments, const Geom *geom, 
-                    const TransformState *net_transform, 
-                    const TransformState *modelview_transform);
+  void show_results(int num_fragments, const Geom *geom,
+                    const TransformState *net_transform,
+                    const TransformState *internal_transform);
 private:
 private:
   bool _live;
   bool _live;
 
 
@@ -98,6 +98,7 @@ private:
 
 
   PT(SceneSetup) _scene;
   PT(SceneSetup) _scene;
   PT(CullTraverser) _internal_trav;
   PT(CullTraverser) _internal_trav;
+  CPT(TransformState) _inv_cs_world_transform;
 
 
   CullHandler *_internal_cull_handler;
   CullHandler *_internal_cull_handler;
   CullHandler *_true_cull_handler;
   CullHandler *_true_cull_handler;
@@ -157,4 +158,4 @@ private:
 #endif
 #endif
 
 
 
 
-  
+

+ 3 - 3
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -198,9 +198,9 @@ public:
   // inconvenient to declare each of those types to be friends of this
   // inconvenient to declare each of those types to be friends of this
   // class.
   // class.
 
 
-  virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, 
+  virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader,
                                      const GeomMunger *munger,
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader, 
+                                     const GeomVertexDataPipelineReader *data_reader,
                                      bool force)=0;
                                      bool force)=0;
   virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)=0;
   virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)=0;
   virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
   virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
@@ -218,7 +218,7 @@ public:
 
 
   virtual CoordinateSystem get_internal_coordinate_system() const=0;
   virtual CoordinateSystem get_internal_coordinate_system() const=0;
 
 
-  virtual void bind_light(PointLight *light_obj, const NodePath &light, 
+  virtual void bind_light(PointLight *light_obj, const NodePath &light,
                           int light_id) { }
                           int light_id) { }
   virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
   virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
                           int light_id) { }
                           int light_id) { }

+ 58 - 66
panda/src/parametrics/ropeNode.cxx

@@ -167,15 +167,15 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
         case RM_thread:
         case RM_thread:
           render_thread(trav, data, result);
           render_thread(trav, data, result);
           break;
           break;
-          
+
         case RM_tape:
         case RM_tape:
           render_tape(trav, data, result);
           render_tape(trav, data, result);
           break;
           break;
-          
+
         case RM_billboard:
         case RM_billboard:
           render_billboard(trav, data, result);
           render_billboard(trav, data, result);
           break;
           break;
-          
+
         case RM_tube:
         case RM_tube:
           render_tube(trav, data, result);
           render_tube(trav, data, result);
           break;
           break;
@@ -183,7 +183,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       }
       }
     }
     }
   }
   }
-  
+
   return true;
   return true;
 }
 }
 
 
@@ -205,7 +205,7 @@ is_renderable() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RopeNode::output
 //     Function: RopeNode::output
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
 output(ostream &out) const {
 output(ostream &out) const {
@@ -221,7 +221,7 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RopeNode::write
 //     Function: RopeNode::write
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
@@ -258,8 +258,8 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
                         int &internal_vertices,
                         int &internal_vertices,
                         int pipeline_stage,
                         int pipeline_stage,
                         Thread *current_thread) const {
                         Thread *current_thread) const {
-  PT(BoundingVolume) bounds = 
-    do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, 
+  PT(BoundingVolume) bounds =
+    do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage,
                         current_thread);
                         current_thread);
 
 
   internal_bounds = bounds;
   internal_bounds = bounds;
@@ -304,7 +304,7 @@ get_format(bool support_normals) const {
 //  Description: Does the actual internal recompute.
 //  Description: Does the actual internal recompute.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(BoundingVolume) RopeNode::
 PT(BoundingVolume) RopeNode::
-do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, 
+do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
                     Thread *current_thread) const {
                     Thread *current_thread) const {
   // TODO: fix the bounds so that it properly reflects the indicated
   // TODO: fix the bounds so that it properly reflects the indicated
   // pipeline stage.  At the moment, we cheat and get some of the
   // pipeline stage.  At the moment, we cheat and get some of the
@@ -312,7 +312,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
 
 
   // First, get ourselves a fresh, empty bounding volume.
   // First, get ourselves a fresh, empty bounding volume.
   PT(BoundingVolume) bound = new BoundingSphere;
   PT(BoundingVolume) bound = new BoundingSphere;
-  
+
   NurbsCurveEvaluator *curve = get_curve();
   NurbsCurveEvaluator *curve = get_curve();
   if (curve != (NurbsCurveEvaluator *)NULL) {
   if (curve != (NurbsCurveEvaluator *)NULL) {
     NurbsCurveEvaluator::Vert3Array verts;
     NurbsCurveEvaluator::Vert3Array verts;
@@ -326,7 +326,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
         (*vi) = LPoint3(*vi) * mat;
         (*vi) = LPoint3(*vi) * mat;
       }
       }
     }
     }
-    
+
     GeometricBoundingVolume *gbv;
     GeometricBoundingVolume *gbv;
     DCAST_INTO_R(gbv, bound, bound);
     DCAST_INTO_R(gbv, bound, bound);
     gbv->around(&verts[0], &verts[0] + verts.size());
     gbv->around(&verts[0], &verts[0] + verts.size());
@@ -349,7 +349,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
 //               per-vertex thickness.
 //               per-vertex thickness.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
-render_thread(CullTraverser *trav, CullTraverserData &data, 
+render_thread(CullTraverser *trav, CullTraverserData &data,
               NurbsCurveResult *result) const {
               NurbsCurveResult *result) const {
   CurveSegments curve_segments;
   CurveSegments curve_segments;
   int num_curve_verts = get_connected_segments(curve_segments, result);
   int num_curve_verts = get_connected_segments(curve_segments, result);
@@ -370,21 +370,19 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
     lines->add_vertex(vi + 1);
     lines->add_vertex(vi + 1);
     lines->close_primitive();
     lines->close_primitive();
   }
   }
-  
+
   PT(Geom) geom = new Geom(vdata);
   PT(Geom) geom = new Geom(vdata);
   geom->add_primitive(lines);
   geom->add_primitive(lines);
-  
+
   CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, get_thickness());
   CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, get_thickness());
   CPT(RenderState) state = data._state->add_attrib(thick);
   CPT(RenderState) state = data._state->add_attrib(thick);
   if (get_use_vertex_color()) {
   if (get_use_vertex_color()) {
     state = state->add_attrib(ColorAttrib::make_vertex());
     state = state->add_attrib(ColorAttrib::make_vertex());
   }
   }
-  
-  CullableObject *object = 
+
+  CullableObject *object =
     new CullableObject(geom, state,
     new CullableObject(geom, state,
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }
 
 
@@ -399,7 +397,7 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
 //               determines the width of the triangle strips.
 //               determines the width of the triangle strips.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
-render_tape(CullTraverser *trav, CullTraverserData &data, 
+render_tape(CullTraverser *trav, CullTraverserData &data,
             NurbsCurveResult *result) const {
             NurbsCurveResult *result) const {
   CurveSegments curve_segments;
   CurveSegments curve_segments;
   int num_curve_verts = get_connected_segments(curve_segments, result);
   int num_curve_verts = get_connected_segments(curve_segments, result);
@@ -409,8 +407,8 @@ render_tape(CullTraverser *trav, CullTraverserData &data,
   // either side.
   // either side.
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("rope", get_format(false), Geom::UH_stream);
     ("rope", get_format(false), Geom::UH_stream);
-  
-  compute_billboard_vertices(vdata, -get_tube_up(), 
+
+  compute_billboard_vertices(vdata, -get_tube_up(),
                              curve_segments, num_curve_verts, result);
                              curve_segments, num_curve_verts, result);
 
 
   // Since this will be a nonindexed primitive, no need to pre-reserve
   // Since this will be a nonindexed primitive, no need to pre-reserve
@@ -419,11 +417,11 @@ render_tape(CullTraverser *trav, CullTraverserData &data,
   CurveSegments::const_iterator si;
   CurveSegments::const_iterator si;
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
     const CurveSegment &segment = (*si);
     const CurveSegment &segment = (*si);
-    
+
     strip->add_next_vertices(segment.size() * 2);
     strip->add_next_vertices(segment.size() * 2);
     strip->close_primitive();
     strip->close_primitive();
   }
   }
-  
+
   PT(Geom) geom = new Geom(vdata);
   PT(Geom) geom = new Geom(vdata);
   geom->add_primitive(strip);
   geom->add_primitive(strip);
 
 
@@ -431,12 +429,10 @@ render_tape(CullTraverser *trav, CullTraverserData &data,
   if (get_use_vertex_color()) {
   if (get_use_vertex_color()) {
     state = state->add_attrib(ColorAttrib::make_vertex());
     state = state->add_attrib(ColorAttrib::make_vertex());
   }
   }
-  
-  CullableObject *object = 
+
+  CullableObject *object =
     new CullableObject(geom, state,
     new CullableObject(geom, state,
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }
 
 
@@ -451,7 +447,7 @@ render_tape(CullTraverser *trav, CullTraverserData &data,
 //               determines the width of the triangle strips.
 //               determines the width of the triangle strips.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
-render_billboard(CullTraverser *trav, CullTraverserData &data, 
+render_billboard(CullTraverser *trav, CullTraverserData &data,
                  NurbsCurveResult *result) const {
                  NurbsCurveResult *result) const {
   const TransformState *net_transform = data.get_net_transform(trav);
   const TransformState *net_transform = data.get_net_transform(trav);
   const TransformState *camera_transform = trav->get_camera_transform();
   const TransformState *camera_transform = trav->get_camera_transform();
@@ -468,21 +464,21 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
   // either side.
   // either side.
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("rope", get_format(false), Geom::UH_stream);
     ("rope", get_format(false), Geom::UH_stream);
-  
-  compute_billboard_vertices(vdata, camera_vec, 
+
+  compute_billboard_vertices(vdata, camera_vec,
                              curve_segments, num_curve_verts, result);
                              curve_segments, num_curve_verts, result);
-  
+
   // Since this will be a nonindexed primitive, no need to pre-reserve
   // Since this will be a nonindexed primitive, no need to pre-reserve
   // the number of vertices.
   // the number of vertices.
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
   CurveSegments::const_iterator si;
   CurveSegments::const_iterator si;
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
     const CurveSegment &segment = (*si);
     const CurveSegment &segment = (*si);
-    
+
     strip->add_next_vertices(segment.size() * 2);
     strip->add_next_vertices(segment.size() * 2);
     strip->close_primitive();
     strip->close_primitive();
   }
   }
-  
+
   PT(Geom) geom = new Geom(vdata);
   PT(Geom) geom = new Geom(vdata);
   geom->add_primitive(strip);
   geom->add_primitive(strip);
 
 
@@ -490,12 +486,10 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
   if (get_use_vertex_color()) {
   if (get_use_vertex_color()) {
     state = state->add_attrib(ColorAttrib::make_vertex());
     state = state->add_attrib(ColorAttrib::make_vertex());
   }
   }
-  
-  CullableObject *object = 
+
+  CullableObject *object =
     new CullableObject(geom, state,
     new CullableObject(geom, state,
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }
 
 
@@ -509,7 +503,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
 //               determines the diameter of the tube.
 //               determines the diameter of the tube.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
-render_tube(CullTraverser *trav, CullTraverserData &data, 
+render_tube(CullTraverser *trav, CullTraverserData &data,
             NurbsCurveResult *result) const {
             NurbsCurveResult *result) const {
   CurveSegments curve_segments;
   CurveSegments curve_segments;
   int num_curve_verts = get_connected_segments(curve_segments, result);
   int num_curve_verts = get_connected_segments(curve_segments, result);
@@ -522,10 +516,10 @@ render_tube(CullTraverser *trav, CullTraverserData &data,
 
 
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("rope", get_format(true), Geom::UH_stream);
     ("rope", get_format(true), Geom::UH_stream);
-  
-  compute_tube_vertices(vdata, num_verts_per_slice, 
+
+  compute_tube_vertices(vdata, num_verts_per_slice,
                         curve_segments, num_curve_verts, result);
                         curve_segments, num_curve_verts, result);
-  
+
   // Finally, go through and build up the index array, to tie all the
   // Finally, go through and build up the index array, to tie all the
   // triangle strips together.  This is difficult to pre-calculate the
   // triangle strips together.  This is difficult to pre-calculate the
   // number of vertices we'll use, so we'll just let it dynamically
   // number of vertices we'll use, so we'll just let it dynamically
@@ -535,20 +529,20 @@ render_tube(CullTraverser *trav, CullTraverserData &data,
   CurveSegments::const_iterator si;
   CurveSegments::const_iterator si;
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
   for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
     const CurveSegment &segment = (*si);
     const CurveSegment &segment = (*si);
-    
+
     for (int s = 0; s < num_slices; ++s) {
     for (int s = 0; s < num_slices; ++s) {
       int s1 = (s + 1) % num_verts_per_slice;
       int s1 = (s + 1) % num_verts_per_slice;
-      
+
       for (size_t j = 0; j < segment.size(); ++j) {
       for (size_t j = 0; j < segment.size(); ++j) {
         strip->add_vertex((vi + j) * num_verts_per_slice + s);
         strip->add_vertex((vi + j) * num_verts_per_slice + s);
         strip->add_vertex((vi + j) * num_verts_per_slice + s1);
         strip->add_vertex((vi + j) * num_verts_per_slice + s1);
       }
       }
-      
+
       strip->close_primitive();
       strip->close_primitive();
     }
     }
     vi += (int)segment.size();
     vi += (int)segment.size();
   }
   }
-  
+
   PT(Geom) geom = new Geom(vdata);
   PT(Geom) geom = new Geom(vdata);
   geom->add_primitive(strip);
   geom->add_primitive(strip);
 
 
@@ -556,12 +550,10 @@ render_tube(CullTraverser *trav, CullTraverserData &data,
   if (get_use_vertex_color()) {
   if (get_use_vertex_color()) {
     state = state->add_attrib(ColorAttrib::make_vertex());
     state = state->add_attrib(ColorAttrib::make_vertex());
   }
   }
-  
-  CullableObject *object = 
+
+  CullableObject *object =
     new CullableObject(geom, state,
     new CullableObject(geom, state,
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }
 
 
@@ -598,7 +590,7 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments,
     LPoint3 point;
     LPoint3 point;
     result->eval_segment_point(segment, 0.0f, point);
     result->eval_segment_point(segment, 0.0f, point);
 
 
-    if (curve_segment == (CurveSegment *)NULL || 
+    if (curve_segment == (CurveSegment *)NULL ||
         !point.almost_equal(last_point)) {
         !point.almost_equal(last_point)) {
       // If the first point of this segment is different from the last
       // If the first point of this segment is different from the last
       // point of the previous segment, end the previous segment and
       // point of the previous segment, end the previous segment and
@@ -610,13 +602,13 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments,
       vtx._p = point;
       vtx._p = point;
       vtx._t = result->get_segment_t(segment, 0.0f);
       vtx._t = result->get_segment_t(segment, 0.0f);
       if (use_vertex_color) {
       if (use_vertex_color) {
-        result->eval_segment_extended_points(segment, 0.0f, 
-                                             get_vertex_color_dimension(), 
+        result->eval_segment_extended_points(segment, 0.0f,
+                                             get_vertex_color_dimension(),
                                              &vtx._c[0], 4);
                                              &vtx._c[0], 4);
       }
       }
       if (use_vertex_thickness) {
       if (use_vertex_thickness) {
-        vtx._thickness = 
-          result->eval_segment_extended_point(segment, 0.0f, 
+        vtx._thickness =
+          result->eval_segment_extended_point(segment, 0.0f,
                                               get_vertex_thickness_dimension());
                                               get_vertex_thickness_dimension());
       }
       }
 
 
@@ -632,13 +624,13 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments,
       result->eval_segment_point(segment, t, vtx._p);
       result->eval_segment_point(segment, t, vtx._p);
       vtx._t = result->get_segment_t(segment, t);
       vtx._t = result->get_segment_t(segment, t);
       if (use_vertex_color) {
       if (use_vertex_color) {
-        result->eval_segment_extended_points(segment, t, 
+        result->eval_segment_extended_points(segment, t,
                                              get_vertex_color_dimension(),
                                              get_vertex_color_dimension(),
                                              &vtx._c[0], 4);
                                              &vtx._c[0], 4);
       }
       }
       if (use_vertex_thickness) {
       if (use_vertex_thickness) {
-        vtx._thickness = 
-          result->eval_segment_extended_point(segment, t, 
+        vtx._thickness =
+          result->eval_segment_extended_point(segment, t,
                                               get_vertex_thickness_dimension());
                                               get_vertex_thickness_dimension());
       }
       }
 
 
@@ -868,7 +860,7 @@ compute_tube_vertices(GeomVertexData *vdata,
 //               point in the segment.
 //               point in the segment.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RopeNode::
 void RopeNode::
-compute_tangent(LVector3 &tangent, const RopeNode::CurveSegment &segment, 
+compute_tangent(LVector3 &tangent, const RopeNode::CurveSegment &segment,
                 size_t j, NurbsCurveResult *result) {
                 size_t j, NurbsCurveResult *result) {
   // First, try to evaluate the tangent at the curve.  This gives
   // First, try to evaluate the tangent at the curve.  This gives
   // better results at the ends at the endpoints where the tangent
   // better results at the ends at the endpoints where the tangent
@@ -908,17 +900,17 @@ compute_uv_t(PN_stdfloat &dist, const RopeNode::UVMode &uv_mode,
   switch (uv_mode) {
   switch (uv_mode) {
   case UV_none:
   case UV_none:
     return 0.0f;
     return 0.0f;
-    
+
   case UV_parametric:
   case UV_parametric:
     return segment[j]._t * uv_scale;
     return segment[j]._t * uv_scale;
-    
+
   case UV_distance:
   case UV_distance:
     if (j != 0) {
     if (j != 0) {
       LVector3 vec = segment[j]._p - segment[j - 1]._p;
       LVector3 vec = segment[j]._p - segment[j - 1]._p;
       dist += vec.length();
       dist += vec.length();
     }
     }
     return dist * uv_scale;
     return dist * uv_scale;
-    
+
   case UV_distance2:
   case UV_distance2:
     if (j != 0) {
     if (j != 0) {
       LVector3 vec = segment[j]._p - segment[j - 1]._p;
       LVector3 vec = segment[j]._p - segment[j - 1]._p;
@@ -929,7 +921,7 @@ compute_uv_t(PN_stdfloat &dist, const RopeNode::UVMode &uv_mode,
 
 
   return 0.0f;
   return 0.0f;
 }
 }
-  
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RopeNode::register_with_read_factory
 //     Function: RopeNode::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 18 - 20
panda/src/parametrics/sheetNode.cxx

@@ -155,13 +155,13 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
     NurbsSurfaceEvaluator *surface = get_surface();
     NurbsSurfaceEvaluator *surface = get_surface();
     if (surface != (NurbsSurfaceEvaluator *)NULL) {
     if (surface != (NurbsSurfaceEvaluator *)NULL) {
       PT(NurbsSurfaceResult) result = surface->evaluate(data._node_path.get_node_path());
       PT(NurbsSurfaceResult) result = surface->evaluate(data._node_path.get_node_path());
-      
+
       if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) {
       if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) {
         render_sheet(trav, data, result);
         render_sheet(trav, data, result);
       }
       }
     }
     }
   }
   }
-  
+
   return true;
   return true;
 }
 }
 
 
@@ -183,7 +183,7 @@ is_renderable() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SheetNode::output
 //     Function: SheetNode::output
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SheetNode::
 void SheetNode::
 output(ostream &out) const {
 output(ostream &out) const {
@@ -199,7 +199,7 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SheetNode::write
 //     Function: SheetNode::write
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SheetNode::
 void SheetNode::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
@@ -241,8 +241,8 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
                         int &internal_vertices,
                         int &internal_vertices,
                         int pipeline_stage,
                         int pipeline_stage,
                         Thread *current_thread) const {
                         Thread *current_thread) const {
-  PT(BoundingVolume) bounds = 
-    do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, 
+  PT(BoundingVolume) bounds =
+    do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage,
                         current_thread);
                         current_thread);
 
 
   internal_bounds = bounds;
   internal_bounds = bounds;
@@ -255,7 +255,7 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
 //  Description: Does the actual internal recompute.
 //  Description: Does the actual internal recompute.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(BoundingVolume) SheetNode::
 PT(BoundingVolume) SheetNode::
-do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, 
+do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
                     Thread *current_thread) const {
                     Thread *current_thread) const {
   // TODO: fix the bounds so that it properly reflects the indicated
   // TODO: fix the bounds so that it properly reflects the indicated
   // pipeline stage.  At the moment, we cheat and get some of the
   // pipeline stage.  At the moment, we cheat and get some of the
@@ -263,12 +263,12 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
 
 
   // First, get ourselves a fresh, empty bounding volume.
   // First, get ourselves a fresh, empty bounding volume.
   PT(BoundingVolume) bound = new BoundingSphere;
   PT(BoundingVolume) bound = new BoundingSphere;
-  
+
   NurbsSurfaceEvaluator *surface = get_surface();
   NurbsSurfaceEvaluator *surface = get_surface();
   if (surface != (NurbsSurfaceEvaluator *)NULL) {
   if (surface != (NurbsSurfaceEvaluator *)NULL) {
     NurbsSurfaceEvaluator::Vert3Array verts;
     NurbsSurfaceEvaluator::Vert3Array verts;
     get_surface()->get_vertices(verts, rel_to);
     get_surface()->get_vertices(verts, rel_to);
-    
+
     GeometricBoundingVolume *gbv;
     GeometricBoundingVolume *gbv;
     DCAST_INTO_R(gbv, bound, bound);
     DCAST_INTO_R(gbv, bound, bound);
     gbv->around(&verts[0], &verts[0] + verts.size());
     gbv->around(&verts[0], &verts[0] + verts.size());
@@ -283,7 +283,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
 //               length.
 //               length.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SheetNode::
 void SheetNode::
-render_sheet(CullTraverser *trav, CullTraverserData &data, 
+render_sheet(CullTraverser *trav, CullTraverserData &data,
              NurbsSurfaceResult *result) {
              NurbsSurfaceResult *result) {
   bool use_vertex_color = get_use_vertex_color();
   bool use_vertex_color = get_use_vertex_color();
 
 
@@ -312,12 +312,12 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
     for (int uni = 0; uni <= num_u_verts; uni++) {
     for (int uni = 0; uni <= num_u_verts; uni++) {
       PN_stdfloat u0 = (PN_stdfloat)uni / (PN_stdfloat)num_u_verts;
       PN_stdfloat u0 = (PN_stdfloat)uni / (PN_stdfloat)num_u_verts;
       PN_stdfloat u0_tc = result->get_segment_u(ui, u0);
       PN_stdfloat u0_tc = result->get_segment_u(ui, u0);
-      
+
       for (int vi = 0; vi < num_v_segments; vi++) {
       for (int vi = 0; vi < num_v_segments; vi++) {
         for (int vni = 0; vni < num_v_verts; vni++) {
         for (int vni = 0; vni < num_v_verts; vni++) {
           PN_stdfloat v = (PN_stdfloat)vni / (PN_stdfloat)(num_v_verts - 1);
           PN_stdfloat v = (PN_stdfloat)vni / (PN_stdfloat)(num_v_verts - 1);
           PN_stdfloat v_tc = result->get_segment_v(vi, v);
           PN_stdfloat v_tc = result->get_segment_v(vi, v);
-          
+
           LPoint3 point;
           LPoint3 point;
           LVector3 norm;
           LVector3 norm;
           result->eval_segment_point(ui, vi, u0, v, point);
           result->eval_segment_point(ui, vi, u0, v, point);
@@ -325,7 +325,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
           vertex.add_data3(point);
           vertex.add_data3(point);
           normal.add_data3(norm);
           normal.add_data3(norm);
           texcoord.add_data2(u0_tc, v_tc);
           texcoord.add_data2(u0_tc, v_tc);
-          
+
           if (use_vertex_color) {
           if (use_vertex_color) {
             LColor c0;
             LColor c0;
             result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4);
             result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4);
@@ -336,7 +336,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
     }
     }
   }
   }
   nassertv(vdata->get_num_rows() == expected_num_vertices);
   nassertv(vdata->get_num_rows() == expected_num_vertices);
-  
+
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
 
 
   int expected_num_tristrips = num_u_segments * num_u_verts * num_v_segments;
   int expected_num_tristrips = num_u_segments * num_u_verts * num_v_segments;
@@ -364,7 +364,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
     }
     }
   }
   }
   nassertv(strip->get_num_vertices() == expected_prim_vertices);
   nassertv(strip->get_num_vertices() == expected_prim_vertices);
-  
+
   PT(Geom) geom = new Geom(vdata);
   PT(Geom) geom = new Geom(vdata);
   geom->add_primitive(strip);
   geom->add_primitive(strip);
 
 
@@ -372,12 +372,10 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
   if (use_vertex_color) {
   if (use_vertex_color) {
     state = state->add_attrib(ColorAttrib::make_vertex());
     state = state->add_attrib(ColorAttrib::make_vertex());
   }
   }
-  
-  CullableObject *object = 
+
+  CullableObject *object =
     new CullableObject(geom, state,
     new CullableObject(geom, state,
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }
 
 

+ 2 - 2
panda/src/pgraph/cullBin.cxx

@@ -108,12 +108,12 @@ ResultGraphBuilder(PandaNode *root_node) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullBin::ResultGraphBuilder::
 void CullBin::ResultGraphBuilder::
 add_object(CullableObject *object) {
 add_object(CullableObject *object) {
-  if (_current_transform != object->_modelview_transform ||
+  if (_current_transform != object->_internal_transform ||
       _current_state != object->_state) {
       _current_state != object->_state) {
     // Create a new GeomNode to hold the net transform and state.  We
     // Create a new GeomNode to hold the net transform and state.  We
     // choose to create a new GeomNode for each new state, to make it
     // choose to create a new GeomNode for each new state, to make it
     // clearer to the observer when the state changes.
     // clearer to the observer when the state changes.
-    _current_transform = object->_modelview_transform;
+    _current_transform = object->_internal_transform;
     _current_state = object->_state;
     _current_state = object->_state;
     _current_node = new GeomNode("object_" + format_string(_object_index));
     _current_node = new GeomNode("object_" + format_string(_object_index));
     _root_node->add_child(_current_node);
     _root_node->add_child(_current_node);

+ 3 - 4
panda/src/pgraph/cullHandler.cxx

@@ -22,7 +22,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullHandler::Constructor
 //     Function: CullHandler::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CullHandler::
 CullHandler::
 CullHandler() {
 CullHandler() {
@@ -31,7 +31,7 @@ CullHandler() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullHandler::Destructor
 //     Function: CullHandler::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CullHandler::
 CullHandler::
 ~CullHandler() {
 ~CullHandler() {
@@ -50,7 +50,7 @@ CullHandler::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullHandler::
 void CullHandler::
 record_object(CullableObject *object, const CullTraverser *traverser) {
 record_object(CullableObject *object, const CullTraverser *traverser) {
-  nout << *object->_geom << " " << *object->_modelview_transform << " " 
+  nout << *object->_geom << " " << *object->_internal_transform << " "
        << *object->_state << "\n";
        << *object->_state << "\n";
   delete object;
   delete object;
 }
 }
@@ -65,4 +65,3 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
 void CullHandler::
 void CullHandler::
 end_traverse() {
 end_traverse() {
 }
 }
-

+ 21 - 22
panda/src/pgraph/cullPlanes.cxx

@@ -116,11 +116,11 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
           if (net_transform == (TransformState *)NULL) {
           if (net_transform == (TransformState *)NULL) {
             net_transform = data->get_net_transform(trav);
             net_transform = data->get_net_transform(trav);
           }
           }
-          
+
           PlaneNode *plane_node = DCAST(PlaneNode, clip_plane.node());
           PlaneNode *plane_node = DCAST(PlaneNode, clip_plane.node());
-          CPT(TransformState) new_transform = 
+          CPT(TransformState) new_transform =
             net_transform->invert_compose(clip_plane.get_net_transform());
             net_transform->invert_compose(clip_plane.get_net_transform());
-          
+
           LPlane plane = plane_node->get_plane() * new_transform->get_mat();
           LPlane plane = plane_node->get_plane() * new_transform->get_mat();
           new_planes->_planes[clip_plane] = new BoundingPlane(-plane);
           new_planes->_planes[clip_plane] = new BoundingPlane(-plane);
         }
         }
@@ -174,17 +174,17 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
         ccp[2] = occluder_node->get_vertex(2) * composed_mat;
         ccp[2] = occluder_node->get_vertex(2) * composed_mat;
         ccp[3] = occluder_node->get_vertex(3) * composed_mat;
         ccp[3] = occluder_node->get_vertex(3) * composed_mat;
 
 
-        LPoint3 ccp_min(min(min(ccp[0][0], ccp[1][0]), 
+        LPoint3 ccp_min(min(min(ccp[0][0], ccp[1][0]),
                      min(ccp[2][0], ccp[3][0])),
                      min(ccp[2][0], ccp[3][0])),
-                 min(min(ccp[0][1], ccp[1][1]), 
+                 min(min(ccp[0][1], ccp[1][1]),
                      min(ccp[2][1], ccp[3][1])),
                      min(ccp[2][1], ccp[3][1])),
-                 min(min(ccp[0][2], ccp[1][2]), 
+                 min(min(ccp[0][2], ccp[1][2]),
                      min(ccp[2][2], ccp[3][2])));
                      min(ccp[2][2], ccp[3][2])));
-        LPoint3 ccp_max(max(max(ccp[0][0], ccp[1][0]), 
+        LPoint3 ccp_max(max(max(ccp[0][0], ccp[1][0]),
                      max(ccp[2][0], ccp[3][0])),
                      max(ccp[2][0], ccp[3][0])),
-                 max(max(ccp[0][1], ccp[1][1]), 
+                 max(max(ccp[0][1], ccp[1][1]),
                      max(ccp[2][1], ccp[3][1])),
                      max(ccp[2][1], ccp[3][1])),
-                 max(max(ccp[0][2], ccp[1][2]), 
+                 max(max(ccp[0][2], ccp[1][2]),
                      max(ccp[2][2], ccp[3][2])));
                      max(ccp[2][2], ccp[3][2])));
 
 
         occluder_gbv = new BoundingBox(ccp_min, ccp_max);
         occluder_gbv = new BoundingBox(ccp_min, ccp_max);
@@ -209,7 +209,7 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
         points_near[2] = occluder_node->get_vertex(2) * occluder_mat_cull;
         points_near[2] = occluder_node->get_vertex(2) * occluder_mat_cull;
         points_near[3] = occluder_node->get_vertex(3) * occluder_mat_cull;
         points_near[3] = occluder_node->get_vertex(3) * occluder_mat_cull;
         LPlane plane(points_near[0], points_near[1], points_near[2]);
         LPlane plane(points_near[0], points_near[1], points_near[2]);
-        
+
         if (plane.get_normal().dot(LVector3::forward()) >= 0.0) {
         if (plane.get_normal().dot(LVector3::forward()) >= 0.0) {
           if (occluder_node->is_double_sided()) {
           if (occluder_node->is_double_sided()) {
             swap(points_near[0], points_near[3]);
             swap(points_near[0], points_near[3]);
@@ -294,22 +294,21 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
 
 
         // With these points, construct the bounding frustum of the
         // With these points, construct the bounding frustum of the
         // occluded region.
         // occluded region.
-        PT(BoundingHexahedron) frustum = 
-          new BoundingHexahedron(points_far[1], points_far[2], points_far[3], points_far[0],  
+        PT(BoundingHexahedron) frustum =
+          new BoundingHexahedron(points_far[1], points_far[2], points_far[3], points_far[0],
                                  points_near[1], points_near[2], points_near[3], points_near[0]);
                                  points_near[1], points_near[2], points_near[3], points_near[0]);
 
 
         new_planes->_occluders[occluder] = frustum;
         new_planes->_occluders[occluder] = frustum;
-        
+
         if (show_occluder_volumes) {
         if (show_occluder_volumes) {
           // Draw the frustum for visualization.
           // Draw the frustum for visualization.
           nassertr(net_transform != NULL, new_planes);
           nassertr(net_transform != NULL, new_planes);
-          trav->draw_bounding_volume(frustum, net_transform, 
-                                     data->get_modelview_transform(trav));
+          trav->draw_bounding_volume(frustum, data->get_internal_transform(trav));
         }
         }
       }
       }
     }
     }
   }
   }
-    
+
   return new_planes;
   return new_planes;
 }
 }
 
 
@@ -330,13 +329,13 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
 CPT(CullPlanes) CullPlanes::
 CPT(CullPlanes) CullPlanes::
 do_cull(int &result, CPT(RenderState) &state,
 do_cull(int &result, CPT(RenderState) &state,
         const GeometricBoundingVolume *node_gbv) const {
         const GeometricBoundingVolume *node_gbv) const {
-  result = 
+  result =
     BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
     BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
 
 
   CPT(ClipPlaneAttrib) orig_cpa = DCAST(ClipPlaneAttrib, state->get_attrib(ClipPlaneAttrib::get_class_slot()));
   CPT(ClipPlaneAttrib) orig_cpa = DCAST(ClipPlaneAttrib, state->get_attrib(ClipPlaneAttrib::get_class_slot()));
 
 
   CPT(CullPlanes) new_planes = this;
   CPT(CullPlanes) new_planes = this;
-  
+
   if (orig_cpa == (ClipPlaneAttrib *)NULL) {
   if (orig_cpa == (ClipPlaneAttrib *)NULL) {
     // If there are no clip planes in the state, the node is completely
     // If there are no clip planes in the state, the node is completely
     // in front of all zero of the clip planes.  (This can happen if
     // in front of all zero of the clip planes.  (This can happen if
@@ -385,7 +384,7 @@ do_cull(int &result, CPT(RenderState) &state,
       // The node is completely in front of this occluder.  We don't
       // The node is completely in front of this occluder.  We don't
       // need to consider this occluder ever again for any descendents of
       // need to consider this occluder ever again for any descendents of
       // this node.
       // this node.
-      
+
       // Reverse the sense of the test, because an occluder volume is
       // Reverse the sense of the test, because an occluder volume is
       // the inverse of a cull plane volume: it describes the volume
       // the inverse of a cull plane volume: it describes the volume
       // that is to be culled, not the volume that is to be kept.
       // that is to be culled, not the volume that is to be kept.
@@ -403,7 +402,7 @@ do_cull(int &result, CPT(RenderState) &state,
 
 
     result &= occluder_result;
     result &= occluder_result;
   }
   }
-    
+
   return new_planes;
   return new_planes;
 }
 }
 
 
@@ -456,11 +455,11 @@ remove_occluder(const NodePath &occluder) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullPlanes::write
 //     Function: CullPlanes::write
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullPlanes::
 void CullPlanes::
 write(ostream &out) const {
 write(ostream &out) const {
-  out << "CullPlanes (" << _planes.size() << " planes and " 
+  out << "CullPlanes (" << _planes.size() << " planes and "
       << _occluders.size() << " occluders):\n";
       << _occluders.size() << " occluders):\n";
   Planes::const_iterator pi;
   Planes::const_iterator pi;
   for (pi = _planes.begin(); pi != _planes.end(); ++pi) {
   for (pi = _planes.begin(); pi != _planes.end(); ++pi) {

+ 8 - 13
panda/src/pgraph/cullTraverser.cxx

@@ -252,20 +252,19 @@ end_traverse() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullTraverser::
 void CullTraverser::
 draw_bounding_volume(const BoundingVolume *vol,
 draw_bounding_volume(const BoundingVolume *vol,
-                     const TransformState *net_transform,
-                     const TransformState *modelview_transform) const {
+                     const TransformState *internal_transform) const {
   PT(Geom) bounds_viz = make_bounds_viz(vol);
   PT(Geom) bounds_viz = make_bounds_viz(vol);
 
 
   if (bounds_viz != (Geom *)NULL) {
   if (bounds_viz != (Geom *)NULL) {
     _geoms_pcollector.add_level(2);
     _geoms_pcollector.add_level(2);
     CullableObject *outer_viz =
     CullableObject *outer_viz =
       new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
       new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
-                         net_transform, modelview_transform, get_scene());
+                         internal_transform);
     _cull_handler->record_object(outer_viz, this);
     _cull_handler->record_object(outer_viz, this);
 
 
     CullableObject *inner_viz =
     CullableObject *inner_viz =
       new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
       new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
-                         net_transform, modelview_transform, get_scene());
+                         internal_transform);
     _cull_handler->record_object(inner_viz, this);
     _cull_handler->record_object(inner_viz, this);
   }
   }
 }
 }
@@ -292,8 +291,7 @@ is_in_view(CullTraverserData &data) {
 void CullTraverser::
 void CullTraverser::
 show_bounds(CullTraverserData &data, bool tight) {
 show_bounds(CullTraverserData &data, bool tight) {
   PandaNode *node = data.node();
   PandaNode *node = data.node();
-  CPT(TransformState) net_transform = data.get_net_transform(this);
-  CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
+  CPT(TransformState) internal_transform = data.get_internal_transform(this);
 
 
   if (tight) {
   if (tight) {
     PT(Geom) bounds_viz = make_tight_bounds_viz(node);
     PT(Geom) bounds_viz = make_tight_bounds_viz(node);
@@ -302,24 +300,21 @@ show_bounds(CullTraverserData &data, bool tight) {
       _geoms_pcollector.add_level(1);
       _geoms_pcollector.add_level(1);
       CullableObject *outer_viz =
       CullableObject *outer_viz =
         new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
         new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
-                           net_transform, modelview_transform,
-                           get_scene());
+                           internal_transform);
       _cull_handler->record_object(outer_viz, this);
       _cull_handler->record_object(outer_viz, this);
     }
     }
 
 
   } else {
   } else {
-    draw_bounding_volume(node->get_bounds(),
-                         net_transform, modelview_transform);
+    draw_bounding_volume(node->get_bounds(), internal_transform);
 
 
     if (node->is_geom_node()) {
     if (node->is_geom_node()) {
       // Also show the bounding volumes of included Geoms.
       // Also show the bounding volumes of included Geoms.
-      net_transform = net_transform->compose(node->get_transform());
-      modelview_transform = modelview_transform->compose(node->get_transform());
+      internal_transform = internal_transform->compose(node->get_transform());
       GeomNode *gnode = DCAST(GeomNode, node);
       GeomNode *gnode = DCAST(GeomNode, node);
       int num_geoms = gnode->get_num_geoms();
       int num_geoms = gnode->get_num_geoms();
       for (int i = 0; i < num_geoms; ++i) {
       for (int i = 0; i < num_geoms; ++i) {
         draw_bounding_volume(gnode->get_geom(i)->get_bounds(),
         draw_bounding_volume(gnode->get_geom(i)->get_bounds(),
-                             net_transform, modelview_transform);
+                             internal_transform);
       }
       }
     }
     }
   }
   }

+ 3 - 6
panda/src/pgraph/cullTraverser.h

@@ -27,7 +27,6 @@
 #include "drawMask.h"
 #include "drawMask.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
-#include "cullTraverserData.h"
 #include "fogAttrib.h"
 #include "fogAttrib.h"
 
 
 class GraphicsStateGuardian;
 class GraphicsStateGuardian;
@@ -90,8 +89,7 @@ PUBLISHED:
   INLINE static void flush_level();
   INLINE static void flush_level();
 
 
   void draw_bounding_volume(const BoundingVolume *vol,
   void draw_bounding_volume(const BoundingVolume *vol,
-                            const TransformState *net_transform,
-                            const TransformState *modelview_transform) const;
+                            const TransformState *internal_transform) const;
 
 
 protected:
 protected:
   INLINE void do_traverse(CullTraverserData &data);
   INLINE void do_traverse(CullTraverserData &data);
@@ -148,9 +146,8 @@ private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 };
 };
 
 
+#include "cullTraverserData.h"
+
 #include "cullTraverser.I"
 #include "cullTraverser.I"
 
 
 #endif
 #endif
-
-
-

+ 22 - 0
panda/src/pgraph/cullTraverserData.I

@@ -136,6 +136,28 @@ node_reader() const {
   return &_node_reader;
   return &_node_reader;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullTraverserData::get_modelview_transform
+//       Access: Published
+//  Description: Returns the modelview transform: the relative
+//               transform from the camera to the model.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(TransformState) CullTraverserData::
+get_modelview_transform(const CullTraverser *trav) const {
+  return trav->get_world_transform()->compose(_net_transform);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullTraverserData::get_internal_transform
+//       Access: Published
+//  Description: Returns the internal transform: the modelview
+//               transform in the GSG's internal coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(TransformState) CullTraverserData::
+get_internal_transform(const CullTraverser *trav) const {
+  return trav->get_scene()->get_cs_world_transform()->compose(_net_transform);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullTraverserData::get_net_transform
 //     Function: CullTraverserData::get_net_transform
 //       Access: Published
 //       Access: Published

+ 0 - 11
panda/src/pgraph/cullTraverserData.cxx

@@ -28,17 +28,6 @@
 #include "renderState.h"
 #include "renderState.h"
 
 
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CullTraverserData::get_modelview_transform
-//       Access: Published
-//  Description: Returns the modelview transform: the relative
-//               transform from the camera to the model.
-////////////////////////////////////////////////////////////////////
-CPT(TransformState) CullTraverserData::
-get_modelview_transform(const CullTraverser *trav) const {
-  return trav->get_world_transform()->compose(_net_transform);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullTraverserData::apply_transform_and_state
 //     Function: CullTraverserData::apply_transform_and_state
 //       Access: Published
 //       Access: Published

+ 8 - 5
panda/src/pgraph/cullTraverserData.h

@@ -50,8 +50,8 @@ public:
                            GeometricBoundingVolume *view_frustum,
                            GeometricBoundingVolume *view_frustum,
                            Thread *current_thread);
                            Thread *current_thread);
   INLINE CullTraverserData(const CullTraverserData &copy);
   INLINE CullTraverserData(const CullTraverserData &copy);
-  INLINE void operator = (const CullTraverserData &copy); 
-  INLINE CullTraverserData(const CullTraverserData &parent, 
+  INLINE void operator = (const CullTraverserData &copy);
+  INLINE CullTraverserData(const CullTraverserData &parent,
                            PandaNode *child);
                            PandaNode *child);
   INLINE ~CullTraverserData();
   INLINE ~CullTraverserData();
 
 
@@ -63,15 +63,16 @@ public:
   INLINE const PandaNodePipelineReader *node_reader() const;
   INLINE const PandaNodePipelineReader *node_reader() const;
 
 
 PUBLISHED:
 PUBLISHED:
-  CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const;
+  INLINE CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const;
+  INLINE CPT(TransformState) get_internal_transform(const CullTraverser *trav) const;
   INLINE const TransformState *get_net_transform(const CullTraverser *trav) const;
   INLINE const TransformState *get_net_transform(const CullTraverser *trav) const;
 
 
   INLINE bool is_in_view(const DrawMask &camera_mask);
   INLINE bool is_in_view(const DrawMask &camera_mask);
   INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const;
   INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const;
 
 
   void apply_transform_and_state(CullTraverser *trav);
   void apply_transform_and_state(CullTraverser *trav);
-  void apply_transform_and_state(CullTraverser *trav, 
-                                 CPT(TransformState) node_transform, 
+  void apply_transform_and_state(CullTraverser *trav,
+                                 CPT(TransformState) node_transform,
                                  CPT(RenderState) node_state,
                                  CPT(RenderState) node_state,
                                  CPT(RenderEffects) node_effects,
                                  CPT(RenderEffects) node_effects,
                                  const RenderAttrib *off_clip_planes);
                                  const RenderAttrib *off_clip_planes);
@@ -91,6 +92,8 @@ private:
   static CPT(RenderState) get_fake_view_frustum_cull_state();
   static CPT(RenderState) get_fake_view_frustum_cull_state();
 };
 };
 
 
+#include "cullTraverser.h"
+
 #include "cullTraverserData.I"
 #include "cullTraverserData.I"
 
 
 #endif
 #endif

+ 0 - 30
panda/src/pgraph/cullableObject.I

@@ -34,35 +34,9 @@ CullableObject() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CullableObject::
 INLINE CullableObject::
 CullableObject(const Geom *geom, const RenderState *state,
 CullableObject(const Geom *geom, const RenderState *state,
-               const TransformState *net_transform,
-               const TransformState *modelview_transform,
-               SceneSetup *scene_setup) :
-  _geom(geom),
-  _state(state),
-  _net_transform(net_transform),
-  _modelview_transform(modelview_transform),
-  _internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform))
-{
-#ifdef DO_MEMORY_USAGE
-  MemoryUsage::update_type(this, get_class_type());
-#endif
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CullableObject::Constructor
-//       Access: Public
-//  Description: Creates a CullableObject based the indicated geom,
-//               with the indicated render state and transform.
-////////////////////////////////////////////////////////////////////
-INLINE CullableObject::
-CullableObject(const Geom *geom, const RenderState *state,
-               const TransformState *net_transform,
-               const TransformState *modelview_transform,
                const TransformState *internal_transform) :
                const TransformState *internal_transform) :
   _geom(geom),
   _geom(geom),
   _state(state),
   _state(state),
-  _net_transform(net_transform),
-  _modelview_transform(modelview_transform),
   _internal_transform(internal_transform)
   _internal_transform(internal_transform)
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -81,8 +55,6 @@ CullableObject(const CullableObject &copy) :
   _munger(copy._munger),
   _munger(copy._munger),
   _munged_data(copy._munged_data),
   _munged_data(copy._munged_data),
   _state(copy._state),
   _state(copy._state),
-  _net_transform(copy._net_transform),
-  _modelview_transform(copy._modelview_transform),
   _internal_transform(copy._internal_transform)
   _internal_transform(copy._internal_transform)
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -101,8 +73,6 @@ operator = (const CullableObject &copy) {
   _munger = copy._munger;
   _munger = copy._munger;
   _munged_data = copy._munged_data;
   _munged_data = copy._munged_data;
   _state = copy._state;
   _state = copy._state;
-  _net_transform = copy._net_transform;
-  _modelview_transform = copy._modelview_transform;
   _internal_transform = copy._internal_transform;
   _internal_transform = copy._internal_transform;
   _draw_callback = copy._draw_callback;
   _draw_callback = copy._draw_callback;
 }
 }

+ 19 - 17
panda/src/pgraph/cullableObject.cxx

@@ -79,7 +79,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
 
 
       geom_rendering = geom_reader.get_geom_rendering();
       geom_rendering = geom_reader.get_geom_rendering();
       geom_rendering = _state->get_geom_rendering(geom_rendering);
       geom_rendering = _state->get_geom_rendering(geom_rendering);
-      geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering);
+      geom_rendering = _internal_transform->get_geom_rendering(geom_rendering);
 
 
       if (geom_rendering & Geom::GR_point_bits) {
       if (geom_rendering & Geom::GR_point_bits) {
         if (geom_reader.get_primitive_type() != Geom::PT_points) {
         if (geom_reader.get_primitive_type() != Geom::PT_points) {
@@ -237,7 +237,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
     }
     }
   }
   }
 
 
-  PN_stdfloat point_size = 1.0f;
+  PN_stdfloat point_size = 1;
   bool perspective = false;
   bool perspective = false;
   const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
   const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
   if (render_mode != (RenderModeAttrib *)NULL) {
   if (render_mode != (RenderModeAttrib *)NULL) {
@@ -309,11 +309,15 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
     }
     }
   }
   }
 
 
-  const LMatrix4 &modelview = _modelview_transform->get_mat();
+  CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
+  LMatrix4 internal = _internal_transform->get_mat();
+  PN_stdfloat scale = _internal_transform->get_scale()[1];
 
 
   SceneSetup *scene = traverser->get_scene();
   SceneSetup *scene = traverser->get_scene();
   const Lens *lens = scene->get_lens();
   const Lens *lens = scene->get_lens();
-  const LMatrix4 &projection = lens->get_projection_mat();
+  LMatrix4 projection =
+    LMatrix4::convert_mat(internal_cs, lens->get_coordinate_system()) *
+                                       lens->get_projection_mat();
 
 
   int viewport_width = scene->get_viewport_width();
   int viewport_width = scene->get_viewport_width();
   int viewport_height = scene->get_viewport_height();
   int viewport_height = scene->get_viewport_height();
@@ -324,10 +328,10 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
   if (perspective) {
   if (perspective) {
     height_projection =
     height_projection =
       LMatrix4::convert_mat(CS_yup_right, lens->get_coordinate_system()) *
       LMatrix4::convert_mat(CS_yup_right, lens->get_coordinate_system()) *
-      projection;
+                                          lens->get_projection_mat();
   }
   }
 
 
-  LMatrix4 render_transform = modelview * projection;
+  LMatrix4 render_transform = internal * projection;
   LMatrix4 inv_render_transform;
   LMatrix4 inv_render_transform;
   inv_render_transform.invert_from(render_transform);
   inv_render_transform.invert_from(render_transform);
 
 
@@ -357,15 +361,16 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
     int vi = 0;
     int vi = 0;
     while (!vertex.is_at_end()) {
     while (!vertex.is_at_end()) {
       // Get the point in eye-space coordinates.
       // Get the point in eye-space coordinates.
-      LPoint3 eye = modelview.xform_point(vertex.get_data3());
+      LPoint3 eye = internal.xform_point(vertex.get_data3());
+      PN_stdfloat dist = gsg->compute_distance_to(eye);
       points[vi]._eye = eye;
       points[vi]._eye = eye;
-      points[vi]._dist = gsg->compute_distance_to(points[vi]._eye);
+      points[vi]._dist = dist;
 
 
       // The point in clip coordinates.
       // The point in clip coordinates.
       LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
       LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
 
 
       if (has_size) {
       if (has_size) {
-        point_size = size.get_data1f();
+        point_size = size.get_data1();
       }
       }
 
 
       PN_stdfloat scale_y = point_size;
       PN_stdfloat scale_y = point_size;
@@ -374,7 +379,6 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
         // height in 3-d units.  To arrange that, we need to figure out
         // height in 3-d units.  To arrange that, we need to figure out
         // the appropriate scaling factor based on the current viewport
         // the appropriate scaling factor based on the current viewport
         // and projection matrix.
         // and projection matrix.
-        PN_stdfloat scale = _modelview_transform->get_scale()[1];
         LVector3 height(0.0f, point_size * scale, scale);
         LVector3 height(0.0f, point_size * scale, scale);
         height = height * height_projection;
         height = height * height_projection;
         scale_y = height[1] * viewport_height;
         scale_y = height[1] * viewport_height;
@@ -382,7 +386,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
         // We should then divide the radius by the distance from the
         // We should then divide the radius by the distance from the
         // camera plane, to emulate the glPointParameters() behavior.
         // camera plane, to emulate the glPointParameters() behavior.
         if (!lens->is_orthographic()) {
         if (!lens->is_orthographic()) {
-          scale_y /= gsg->compute_distance_to(eye);
+          scale_y /= dist;
         }
         }
       }
       }
 
 
@@ -392,7 +396,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
 
 
       PN_stdfloat scale_x = scale_y;
       PN_stdfloat scale_x = scale_y;
       if (has_aspect_ratio) {
       if (has_aspect_ratio) {
-        scale_x *= aspect_ratio.get_data1f();
+        scale_x *= aspect_ratio.get_data1();
       }
       }
 
 
       // Define the first two corners based on the scales in X and Y.
       // Define the first two corners based on the scales in X and Y.
@@ -401,7 +405,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
 
 
       if (has_rotate) {
       if (has_rotate) {
         // If we have a rotate factor, apply it to those two corners.
         // If we have a rotate factor, apply it to those two corners.
-        PN_stdfloat r = rotate.get_data1f();
+        PN_stdfloat r = rotate.get_data1();
         LMatrix3 mat = LMatrix3::rotate_mat(r);
         LMatrix3 mat = LMatrix3::rotate_mat(r);
         c0 = c0 * mat;
         c0 = c0 * mat;
         c1 = c1 * mat;
         c1 = c1 * mat;
@@ -474,11 +478,9 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
   }
   }
 
 
   // Determine the format we should use to store the indices.
   // Determine the format we should use to store the indices.
+  // Don't choose NT_uint8, as Direct3D 9 doesn't support it.
   const GeomVertexArrayFormat *new_prim_format = NULL;
   const GeomVertexArrayFormat *new_prim_format = NULL;
-  if (new_verts < 0xff) {
-    new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint8);
-
-  } else if (new_verts < 0xffff) {
+  if (new_verts < 0xffff) {
     new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16);
     new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16);
 
 
   } else {
   } else {

+ 0 - 8
panda/src/pgraph/cullableObject.h

@@ -50,12 +50,6 @@ class EXPCL_PANDA_PGRAPH CullableObject
 public:
 public:
   INLINE CullableObject();
   INLINE CullableObject();
   INLINE CullableObject(const Geom *geom, const RenderState *state,
   INLINE CullableObject(const Geom *geom, const RenderState *state,
-                        const TransformState *net_transform,
-                        const TransformState *modelview_transform,
-                        SceneSetup *scene_setup);
-  INLINE CullableObject(const Geom *geom, const RenderState *state,
-                        const TransformState *net_transform,
-                        const TransformState *modelview_transform,
                         const TransformState *internal_transform);
                         const TransformState *internal_transform);
 
 
   INLINE CullableObject(const CullableObject &copy);
   INLINE CullableObject(const CullableObject &copy);
@@ -82,8 +76,6 @@ public:
   PT(GeomMunger) _munger;
   PT(GeomMunger) _munger;
   CPT(GeomVertexData) _munged_data;
   CPT(GeomVertexData) _munged_data;
   CPT(RenderState) _state;
   CPT(RenderState) _state;
-  CPT(TransformState) _net_transform;
-  CPT(TransformState) _modelview_transform;
   CPT(TransformState) _internal_transform;
   CPT(TransformState) _internal_transform;
   PT(CallbackObject) _draw_callback;
   PT(CallbackObject) _draw_callback;
 
 

+ 2 - 5
panda/src/pgraph/geomNode.cxx

@@ -562,9 +562,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
   Geoms geoms = get_geoms(trav->get_current_thread());
   Geoms geoms = get_geoms(trav->get_current_thread());
   int num_geoms = geoms.get_num_geoms();
   int num_geoms = geoms.get_num_geoms();
   trav->_geoms_pcollector.add_level(num_geoms);
   trav->_geoms_pcollector.add_level(num_geoms);
-  CPT(TransformState) net_transform = data.get_net_transform(trav);
-  CPT(TransformState) modelview_transform = data.get_modelview_transform(trav);
-  CPT(TransformState) internal_transform = trav->get_scene()->get_cs_transform()->compose(modelview_transform);
+  CPT(TransformState) internal_transform = data.get_internal_transform(trav);
 
 
   for (int i = 0; i < num_geoms; i++) {
   for (int i = 0; i < num_geoms; i++) {
     const Geom *geom = geoms.get_geom(i);
     const Geom *geom = geoms.get_geom(i);
@@ -611,8 +609,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
     }
     }
 
 
     CullableObject *object =
     CullableObject *object =
-      new CullableObject(geom, state, net_transform,
-                         modelview_transform, internal_transform);
+      new CullableObject(geom, state, internal_transform);
     trav->get_cull_handler()->record_object(object, trav);
     trav->get_cull_handler()->record_object(object, trav);
   }
   }
 }
 }

+ 1 - 0
panda/src/pgraph/geomNode.h

@@ -73,6 +73,7 @@ PUBLISHED:
   INLINE CPT(Geom) get_geom(int n) const;
   INLINE CPT(Geom) get_geom(int n) const;
   MAKE_SEQ(get_geoms, get_num_geoms, get_geom);
   MAKE_SEQ(get_geoms, get_num_geoms, get_geom);
   INLINE PT(Geom) modify_geom(int n);
   INLINE PT(Geom) modify_geom(int n);
+  MAKE_SEQ(modify_geoms, get_num_geoms, modify_geom);
   INLINE const RenderState *get_geom_state(int n) const;
   INLINE const RenderState *get_geom_state(int n) const;
   MAKE_SEQ(get_geom_states, get_num_geoms, get_geom_state);
   MAKE_SEQ(get_geom_states, get_num_geoms, get_geom_state);
   INLINE void set_geom_state(int n, const RenderState *state);
   INLINE void set_geom_state(int n, const RenderState *state);

+ 27 - 0
panda/src/pgraph/nodePath.I

@@ -109,6 +109,33 @@ operator = (const NodePath &copy) {
   _error_type = copy._error_type;
   _error_type = copy._error_type;
 }
 }
 
 
+#ifdef USE_MOVE_SEMANTICS
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::Move Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NodePath::
+NodePath(NodePath &&from) NOEXCEPT :
+  _head(move(from._head)),
+  _backup_key(from._backup_key),
+  _error_type(from._error_type)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::Move Assignment Operator
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void NodePath::
+operator = (NodePath &&from) NOEXCEPT {
+  _head = move(from._head);
+  _backup_key = from._backup_key;
+  _error_type = from._error_type;
+}
+#endif  // USE_MOVE_SEMANTICS
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::not_found named constructor
 //     Function: NodePath::not_found named constructor
 //       Access: Published, Static
 //       Access: Published, Static

+ 5 - 0
panda/src/pgraph/nodePath.h

@@ -180,6 +180,11 @@ PUBLISHED:
   INLINE NodePath(const NodePath &copy);
   INLINE NodePath(const NodePath &copy);
   INLINE void operator = (const NodePath &copy);
   INLINE void operator = (const NodePath &copy);
 
 
+#ifdef USE_MOVE_SEMANTICS
+  INLINE NodePath(NodePath &&from) NOEXCEPT;
+  INLINE void operator = (NodePath &&from) NOEXCEPT;
+#endif
+
   EXTENSION(NodePath __copy__() const);
   EXTENSION(NodePath __copy__() const);
   EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
   EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
   EXTENSION(PyObject *__reduce__(PyObject *self) const);
   EXTENSION(PyObject *__reduce__(PyObject *self) const);

+ 6 - 10
panda/src/pgraph/occluderNode.cxx

@@ -164,20 +164,16 @@ bool OccluderNode::
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
   // Normally, an OccluderNode is invisible.  But if someone shows it,
   // Normally, an OccluderNode is invisible.  But if someone shows it,
   // we will draw a visualization, a checkerboard-textured polygon.
   // we will draw a visualization, a checkerboard-textured polygon.
-  CullableObject *occluder_viz = 
-    new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), 
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+  CullableObject *occluder_viz =
+    new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data),
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(occluder_viz, trav);
   trav->get_cull_handler()->record_object(occluder_viz, trav);
 
 
   // Also get the frame.
   // Also get the frame.
   nassertr(_frame_viz != (Geom *)NULL, false);
   nassertr(_frame_viz != (Geom *)NULL, false);
-  CullableObject *frame_viz = 
-    new CullableObject(_frame_viz, get_frame_viz_state(trav, data), 
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+  CullableObject *frame_viz =
+    new CullableObject(_frame_viz, get_frame_viz_state(trav, data),
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(frame_viz, trav);
   trav->get_cull_handler()->record_object(frame_viz, trav);
 
 
   // Now carry on to render our child nodes.
   // Now carry on to render our child nodes.

+ 6 - 8
panda/src/pgraph/planeNode.cxx

@@ -99,7 +99,7 @@ PlaneNode(const PlaneNode &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PlaneNode::output
 //     Function: PlaneNode::output
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PlaneNode::
 void PlaneNode::
 output(ostream &out) const {
 output(ostream &out) const {
@@ -166,11 +166,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
   // Normally, a PlaneNode is invisible.  But if someone shows it, we
   // Normally, a PlaneNode is invisible.  But if someone shows it, we
   // will draw a visualization, a nice yellow wireframe.
   // will draw a visualization, a nice yellow wireframe.
 
 
-  CullableObject *plane_viz = 
-    new CullableObject(get_viz(trav, data), data._state, 
-                       data.get_net_transform(trav),
-                       data.get_modelview_transform(trav),
-                       trav->get_scene());
+  CullableObject *plane_viz =
+    new CullableObject(get_viz(trav, data), data._state,
+                       data.get_internal_transform(trav));
   trav->get_cull_handler()->record_object(plane_viz, trav);
   trav->get_cull_handler()->record_object(plane_viz, trav);
 
 
   // Now carry on to render our child nodes.
   // Now carry on to render our child nodes.
@@ -219,7 +217,7 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
 PT(Geom) PlaneNode::
 PT(Geom) PlaneNode::
 get_viz(CullTraverser *trav, CullTraverserData &data) {
 get_viz(CullTraverser *trav, CullTraverserData &data) {
   CDLockedReader cdata(_cycler);
   CDLockedReader cdata(_cycler);
-  
+
   // Figure out whether we are looking at the front or the back of the
   // Figure out whether we are looking at the front or the back of the
   // plane.
   // plane.
   const Lens *lens = trav->get_scene()->get_lens();
   const Lens *lens = trav->get_scene()->get_lens();
@@ -273,7 +271,7 @@ get_viz(CullTraverser *trav, CullTraverserData &data) {
   static const int num_segs = 10;
   static const int num_segs = 10;
   a *= cdataw->_viz_scale / (num_segs * 2);
   a *= cdataw->_viz_scale / (num_segs * 2);
   b *= cdataw->_viz_scale / (num_segs * 2);
   b *= cdataw->_viz_scale / (num_segs * 2);
-  
+
   for (int x = -num_segs; x <= num_segs; ++x) {
   for (int x = -num_segs; x <= num_segs; ++x) {
     vertex.add_data3(plane.project(a * x - b * num_segs));
     vertex.add_data3(plane.project(a * x - b * num_segs));
     vertex.add_data3(plane.project(a * x + b * num_segs));
     vertex.add_data3(plane.project(a * x + b * num_segs));

+ 25 - 0
panda/src/pgraph/sceneSetup.I

@@ -28,6 +28,7 @@ SceneSetup() {
   _camera_transform = TransformState::make_identity();
   _camera_transform = TransformState::make_identity();
   _world_transform = TransformState::make_identity();
   _world_transform = TransformState::make_identity();
   _cs_transform = TransformState::make_identity();
   _cs_transform = TransformState::make_identity();
+  _cs_world_transform = TransformState::make_identity();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -316,3 +317,27 @@ INLINE const TransformState *SceneSetup::
 get_cs_transform() const {
 get_cs_transform() const {
   return _cs_transform;
   return _cs_transform;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: SceneSetup::set_cs_world_transform
+//       Access: Published
+//  Description: Specifies the position from the starting node
+//               relative to the camera, in the GSG's internal
+//               coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE void SceneSetup::
+set_cs_world_transform(const TransformState *cs_world_transform) {
+  _cs_world_transform = cs_world_transform;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SceneSetup::get_cs_world_transform
+//       Access: Published
+//  Description: Returns the position from the starting node
+//               relative to the camera, in the GSG's internal
+//               coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE const TransformState *SceneSetup::
+get_cs_world_transform() const {
+  return _cs_world_transform;
+}

+ 4 - 0
panda/src/pgraph/sceneSetup.h

@@ -74,6 +74,9 @@ PUBLISHED:
   INLINE void set_cs_transform(const TransformState *cs_transform);
   INLINE void set_cs_transform(const TransformState *cs_transform);
   INLINE const TransformState *get_cs_transform() const;
   INLINE const TransformState *get_cs_transform() const;
 
 
+  INLINE void set_cs_world_transform(const TransformState *cs_world_transform);
+  INLINE const TransformState *get_cs_world_transform() const;
+
 private:
 private:
   DisplayRegion *_display_region;
   DisplayRegion *_display_region;
   int _viewport_width;
   int _viewport_width;
@@ -87,6 +90,7 @@ private:
   CPT(TransformState) _camera_transform;
   CPT(TransformState) _camera_transform;
   CPT(TransformState) _world_transform;
   CPT(TransformState) _world_transform;
   CPT(TransformState) _cs_transform;
   CPT(TransformState) _cs_transform;
+  CPT(TransformState) _cs_world_transform;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 3 - 5
panda/src/pgraphnodes/callbackNode.cxx

@@ -149,7 +149,7 @@ void CallbackNode::
 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
   if (pgraph_cat.is_spam()) {
   if (pgraph_cat.is_spam()) {
     pgraph_cat.spam()
     pgraph_cat.spam()
-      << "Found " << *this << " in state " << *data._state 
+      << "Found " << *this << " in state " << *data._state
       << " draw_mask = " << data._draw_mask << "\n";
       << " draw_mask = " << data._draw_mask << "\n";
   }
   }
 
 
@@ -158,11 +158,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
   // pass any Geoms, however.
   // pass any Geoms, however.
   CallbackObject *cbobj = get_draw_callback();
   CallbackObject *cbobj = get_draw_callback();
   if (cbobj != (CallbackObject *)NULL) {
   if (cbobj != (CallbackObject *)NULL) {
-    CullableObject *object = 
+    CullableObject *object =
       new CullableObject(NULL, data._state,
       new CullableObject(NULL, data._state,
-                         data.get_net_transform(trav),
-                         data.get_modelview_transform(trav),
-                         trav->get_scene());
+                         data.get_internal_transform(trav));
     object->set_draw_callback(cbobj);
     object->set_draw_callback(cbobj);
     trav->get_cull_handler()->record_object(object, trav);
     trav->get_cull_handler()->record_object(object, trav);
   }
   }

+ 2 - 4
panda/src/pgraphnodes/computeNode.cxx

@@ -105,7 +105,7 @@ void ComputeNode::
 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
   if (pgraph_cat.is_spam()) {
   if (pgraph_cat.is_spam()) {
     pgraph_cat.spam()
     pgraph_cat.spam()
-      << "Found " << *this << " in state " << *data._state 
+      << "Found " << *this << " in state " << *data._state
       << " draw_mask = " << data._draw_mask << "\n";
       << " draw_mask = " << data._draw_mask << "\n";
   }
   }
 
 
@@ -114,9 +114,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
   // any Geoms, however.
   // any Geoms, however.
   CullableObject *object =
   CullableObject *object =
     new CullableObject(NULL, data._state,
     new CullableObject(NULL, data._state,
-                         data.get_net_transform(trav),
-                         data.get_modelview_transform(trav),
-                         trav->get_scene());
+                       data.get_internal_transform(trav));
   object->set_draw_callback(_dispatcher);
   object->set_draw_callback(_dispatcher);
   trav->get_cull_handler()->record_object(object, trav);
   trav->get_cull_handler()->record_object(object, trav);
 }
 }

+ 2 - 4
panda/src/pgraphnodes/nodeCullCallbackData.cxx

@@ -55,11 +55,9 @@ upcall() {
     // to pass any Geoms, however.
     // to pass any Geoms, however.
     CallbackObject *cbobj = cbnode->get_draw_callback();
     CallbackObject *cbobj = cbnode->get_draw_callback();
     if (cbobj != (CallbackObject *)NULL) {
     if (cbobj != (CallbackObject *)NULL) {
-      CullableObject *object = 
+      CullableObject *object =
         new CullableObject(NULL, _data._state,
         new CullableObject(NULL, _data._state,
-                           _data.get_net_transform(_trav),
-                           _data.get_modelview_transform(_trav),
-                           _trav->get_scene());
+                           _data.get_internal_transform(_trav));
       object->set_draw_callback(cbobj);
       object->set_draw_callback(cbobj);
       _trav->get_cull_handler()->record_object(object, _trav);
       _trav->get_cull_handler()->record_object(object, _trav);
     }
     }

+ 4 - 5
panda/src/rocket/rocketRenderInterface.cxx

@@ -123,14 +123,13 @@ render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vect
       << *state << ", translation (" << offset << ")\n";
       << *state << ", translation (" << offset << ")\n";
   }
   }
 
 
-  CPT(TransformState) net_transform, modelview_transform;
-  net_transform = _net_transform->compose(TransformState::make_pos(offset));
-  modelview_transform = _trav->get_world_transform()->compose(net_transform);
+  CPT(TransformState) internal_transform =
+    _trav->get_scene()->get_cs_world_transform()->compose(
+      _net_transform->compose(TransformState::make_pos(offset)));
 
 
   CullableObject *object =
   CullableObject *object =
     new CullableObject(geom, _net_state->compose(state),
     new CullableObject(geom, _net_state->compose(state),
-                       net_transform, modelview_transform,
-                       _trav->get_scene());
+                       internal_transform);
   _trav->get_cull_handler()->record_object(object, _trav);
   _trav->get_cull_handler()->record_object(object, _trav);
 }
 }
 
 

+ 50 - 52
panda/src/speedtree/speedTreeNode.cxx

@@ -332,7 +332,7 @@ add_instances_from(const SpeedTreeNode *other) {
     const InstanceList &other_instance_list = other->get_instance_list(ti);
     const InstanceList &other_instance_list = other->get_instance_list(ti);
     const STTree *tree = other_instance_list.get_tree();
     const STTree *tree = other_instance_list.get_tree();
     InstanceList &this_instance_list = add_tree(tree);
     InstanceList &this_instance_list = add_tree(tree);
-    
+
     int num_instances = other_instance_list.get_num_instances();
     int num_instances = other_instance_list.get_num_instances();
     for (int i = 0; i < num_instances; ++i) {
     for (int i = 0; i < num_instances; ++i) {
       STTransform other_trans = other_instance_list.get_instance(i);
       STTransform other_trans = other_instance_list.get_instance(i);
@@ -356,7 +356,7 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform)
     const InstanceList &other_instance_list = other->get_instance_list(ti);
     const InstanceList &other_instance_list = other->get_instance_list(ti);
     const STTree *tree = other_instance_list.get_tree();
     const STTree *tree = other_instance_list.get_tree();
     InstanceList &this_instance_list = add_tree(tree);
     InstanceList &this_instance_list = add_tree(tree);
-    
+
     int num_instances = other_instance_list.get_num_instances();
     int num_instances = other_instance_list.get_num_instances();
     for (int i = 0; i < num_instances; ++i) {
     for (int i = 0; i < num_instances; ++i) {
       CPT(TransformState) other_trans = other_instance_list.get_instance(i);
       CPT(TransformState) other_trans = other_instance_list.get_instance(i);
@@ -388,8 +388,8 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform)
 //               slope_min and slope_max are ignored.
 //               slope_min and slope_max are ignored.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SpeedTreeNode::
 void SpeedTreeNode::
-add_random_instances(const STTree *tree, int quantity, 
-                     PN_stdfloat x_min, PN_stdfloat x_max, 
+add_random_instances(const STTree *tree, int quantity,
+                     PN_stdfloat x_min, PN_stdfloat x_max,
                      PN_stdfloat y_min, PN_stdfloat y_max,
                      PN_stdfloat y_min, PN_stdfloat y_max,
                      PN_stdfloat scale_min, PN_stdfloat scale_max,
                      PN_stdfloat scale_min, PN_stdfloat scale_max,
                      PN_stdfloat height_min, PN_stdfloat height_max,
                      PN_stdfloat height_min, PN_stdfloat height_max,
@@ -417,7 +417,7 @@ add_random_instances(const STTree *tree, int quantity,
         }
         }
       }
       }
       transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]);
       transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]);
-      
+
     } else {
     } else {
       // No terrain; just pick a random height.
       // No terrain; just pick a random height.
       transform._pos[2] = randomizer.random_real(height_max - height_min) + height_min;
       transform._pos[2] = randomizer.random_real(height_max - height_min) + height_min;
@@ -484,7 +484,7 @@ add_from_stf(const Filename &stf_filename, const LoaderOptions &options) {
 //               NULL, the default global Loader is used instead.
 //               NULL, the default global Loader is used instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool SpeedTreeNode::
 bool SpeedTreeNode::
-add_from_stf(istream &in, const Filename &pathname, 
+add_from_stf(istream &in, const Filename &pathname,
              const LoaderOptions &options, Loader *loader) {
              const LoaderOptions &options, Loader *loader) {
   if (loader == NULL) {
   if (loader == NULL) {
     loader = Loader::get_global_ptr();
     loader = Loader::get_global_ptr();
@@ -701,7 +701,7 @@ reload_config() {
   int num_shadow_maps = speedtree_cascading_shadow_splits.get_num_words();
   int num_shadow_maps = speedtree_cascading_shadow_splits.get_num_words();
   if (num_shadow_maps > SpeedTree::c_nMaxNumShadowMaps) {
   if (num_shadow_maps > SpeedTree::c_nMaxNumShadowMaps) {
     speedtree_cat.warning()
     speedtree_cat.warning()
-      << "SpeedTree is current compiled to support a maximum of " 
+      << "SpeedTree is current compiled to support a maximum of "
       << SpeedTree::c_nMaxNumShadowMaps << " shadow maps.\n";
       << SpeedTree::c_nMaxNumShadowMaps << " shadow maps.\n";
     num_shadow_maps = SpeedTree::c_nMaxNumShadowMaps;
     num_shadow_maps = SpeedTree::c_nMaxNumShadowMaps;
   }
   }
@@ -747,7 +747,7 @@ reload_config() {
   _forest_render.SetRenderInfo(render_info);
   _forest_render.SetRenderInfo(render_info);
 
 
   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
-  _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, 
+  _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
                           speedtree_max_num_visible_cells);
                           speedtree_max_num_visible_cells);
   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
 
 
@@ -787,12 +787,12 @@ authorize(const string &license) {
         SpeedTree::CCore::Authorize(speedtree_license.c_str());
         SpeedTree::CCore::Authorize(speedtree_license.c_str());
       }
       }
     }
     }
-                                                             
+
     _authorized = SpeedTree::CCore::IsAuthorized();
     _authorized = SpeedTree::CCore::IsAuthorized();
 
 
     SpeedTree::CCore::SetTextureFlip(true);
     SpeedTree::CCore::SetTextureFlip(true);
   }
   }
-  
+
   return _authorized;
   return _authorized;
 }
 }
 
 
@@ -821,7 +821,7 @@ SpeedTreeNode(const SpeedTreeNode &copy) :
 
 
   // No way to copy these parameters, so we just re-assign them.
   // No way to copy these parameters, so we just re-assign them.
   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
-  _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, 
+  _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
                           speedtree_max_num_visible_cells);
                           speedtree_max_num_visible_cells);
   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
 
 
@@ -848,7 +848,7 @@ SpeedTreeNode(const SpeedTreeNode &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::Destructor
 //     Function: SpeedTreeNode::Destructor
 //       Access: Published, Virtual
 //       Access: Published, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 SpeedTreeNode::
 SpeedTreeNode::
 ~SpeedTreeNode() {
 ~SpeedTreeNode() {
@@ -980,7 +980,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
   ClockObject *clock = ClockObject::get_global_clock();
   ClockObject *clock = ClockObject::get_global_clock();
   _forest_render.SetGlobalTime(clock->get_frame_time() + _time_delta + _global_time_delta);
   _forest_render.SetGlobalTime(clock->get_frame_time() + _time_delta + _global_time_delta);
   _forest_render.AdvanceGlobalWind();
   _forest_render.AdvanceGlobalWind();
-  
+
   // Compute the modelview and camera transforms, to pass to the
   // Compute the modelview and camera transforms, to pass to the
   // SpeedTree CView structure.
   // SpeedTree CView structure.
   CPT(TransformState) orig_modelview = data.get_modelview_transform(trav);
   CPT(TransformState) orig_modelview = data.get_modelview_transform(trav);
@@ -989,11 +989,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
   LMatrix4f modelview_mat = LCAST(float, modelview->get_mat());
   LMatrix4f modelview_mat = LCAST(float, modelview->get_mat());
   const LPoint3 &camera_pos = camera_transform->get_pos();
   const LPoint3 &camera_pos = camera_transform->get_pos();
   const Lens *lens = trav->get_scene()->get_lens();
   const Lens *lens = trav->get_scene()->get_lens();
-  
+
   LMatrix4f projection_mat =
   LMatrix4f projection_mat =
     LCAST(float, LMatrix4::convert_mat(gsg->get_internal_coordinate_system(), lens->get_coordinate_system()) *
     LCAST(float, LMatrix4::convert_mat(gsg->get_internal_coordinate_system(), lens->get_coordinate_system()) *
           lens->get_projection_mat());
           lens->get_projection_mat());
-  
+
   _view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]),
   _view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]),
             SpeedTree::Mat4x4(projection_mat.get_data()),
             SpeedTree::Mat4x4(projection_mat.get_data()),
             SpeedTree::Mat4x4(modelview_mat.get_data()),
             SpeedTree::Mat4x4(modelview_mat.get_data()),
@@ -1041,7 +1041,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       }
       }
     }
     }
   }
   }
-    
+
   if (dlight != (DirectionalLight *)NULL) {
   if (dlight != (DirectionalLight *)NULL) {
     CPT(TransformState) transform = dlight_np.get_transform(trav->get_scene()->get_scene_root().get_parent());
     CPT(TransformState) transform = dlight_np.get_transform(trav->get_scene()->get_scene_root().get_parent());
     LVector3 dir = dlight->get_direction() * transform->get_mat();
     LVector3 dir = dlight->get_direction() * transform->get_mat();
@@ -1118,11 +1118,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
     // We create a CullableObject that has an explicit draw_callback
     // We create a CullableObject that has an explicit draw_callback
     // into this node, so that we can make the appropriate calls into
     // into this node, so that we can make the appropriate calls into
     // SpeedTree to render the forest during the actual draw.
     // SpeedTree to render the forest during the actual draw.
-    CullableObject *object = 
+    CullableObject *object =
       new CullableObject(NULL, data._state,
       new CullableObject(NULL, data._state,
-                         TransformState::make_identity(),
-                         TransformState::make_identity(),
-                         trav->get_scene());
+                         TransformState::make_identity());
     object->set_draw_callback(new DrawCallback(this));
     object->set_draw_callback(new DrawCallback(this));
     trav->get_cull_handler()->record_object(object, trav);
     trav->get_cull_handler()->record_object(object, trav);
   }
   }
@@ -1208,7 +1206,7 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::write
 //     Function: SpeedTreeNode::write
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SpeedTreeNode::
 void SpeedTreeNode::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
@@ -1219,7 +1217,7 @@ write(ostream &out, int indent_level) const {
   Trees::const_iterator ti;
   Trees::const_iterator ti;
   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
     InstanceList *instance_list = (*ti);
     InstanceList *instance_list = (*ti);
-    indent(out, indent_level + 2) 
+    indent(out, indent_level + 2)
       << *instance_list << "\n";
       << *instance_list << "\n";
   }
   }
   */
   */
@@ -1254,7 +1252,7 @@ set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode eMode) const {
   SpeedTree::CRenderState::SetBlending(false);
   SpeedTree::CRenderState::SetBlending(false);
   SpeedTree::CRenderState::SetAlphaTesting(false);
   SpeedTree::CRenderState::SetAlphaTesting(false);
   SpeedTree::CRenderState::SetAlphaToCoverage(false);
   SpeedTree::CRenderState::SetAlphaToCoverage(false);
-  
+
   switch (eMode) {
   switch (eMode) {
   case SpeedTree::TRANS_TEXTURE_ALPHA_TESTING:
   case SpeedTree::TRANS_TEXTURE_ALPHA_TESTING:
     SpeedTree::CRenderState::SetAlphaTesting(true);
     SpeedTree::CRenderState::SetAlphaTesting(true);
@@ -1291,7 +1289,7 @@ init_node() {
     return;
     return;
   }
   }
 
 
-  _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS, 
+  _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS,
                          speedtree_max_num_visible_cells);
                          speedtree_max_num_visible_cells);
 
 
   _forest_render.SetCullCellSize(speedtree_cull_cell_size);
   _forest_render.SetCullCellSize(speedtree_cull_cell_size);
@@ -1354,7 +1352,7 @@ repopulate() {
       write_error(speedtree_cat.warning());
       write_error(speedtree_cat.warning());
     }
     }
   }
   }
-  
+
   _forest_render.GetPopulationStats(_population_stats);
   _forest_render.GetPopulationStats(_population_stats);
   print_forest_stats(_population_stats);
   print_forest_stats(_population_stats);
 
 
@@ -1379,8 +1377,8 @@ repopulate() {
   }
   }
 
 
   _visible_trees.Reserve(_forest_render.GetBaseTrees(),
   _visible_trees.Reserve(_forest_render.GetBaseTrees(),
-                         _forest_render.GetBaseTrees().size(), 
-                         speedtree_max_num_visible_cells, 
+                         _forest_render.GetBaseTrees().size(),
+                         speedtree_max_num_visible_cells,
                          max_instances_by_cell,
                          max_instances_by_cell,
                          speedtree_horizontal_billboards);
                          speedtree_horizontal_billboards);
 }
 }
@@ -1401,8 +1399,8 @@ update_terrain_cells() {
   PN_stdfloat cell_size = _terrain_render.GetCellSize();
   PN_stdfloat cell_size = _terrain_render.GetCellSize();
 
 
   // A temporary vertex data object for populating terrain.
   // A temporary vertex data object for populating terrain.
-  PT(GeomVertexData) vertex_data = 
-    new GeomVertexData("terrain", _terrain->get_vertex_format(), 
+  PT(GeomVertexData) vertex_data =
+    new GeomVertexData("terrain", _terrain->get_vertex_format(),
                        GeomEnums::UH_static);
                        GeomEnums::UH_static);
   int num_vertices = num_tile_res * num_tile_res;
   int num_vertices = num_tile_res * num_tile_res;
   vertex_data->set_num_rows(num_vertices);
   vertex_data->set_num_rows(num_vertices);
@@ -1428,7 +1426,7 @@ update_terrain_cells() {
     nassertv(vbo->NumVertices() == num_tile_res * num_tile_res);
     nassertv(vbo->NumVertices() == num_tile_res * num_tile_res);
     nassertv(vbo->NumVertices() * vbo->VertexSize() == handle->get_data_size_bytes());
     nassertv(vbo->NumVertices() * vbo->VertexSize() == handle->get_data_size_bytes());
     vbo->OverwriteVertices(data_pointer, num_vertices, 0);
     vbo->OverwriteVertices(data_pointer, num_vertices, 0);
-  }    
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1501,12 +1499,12 @@ draw_callback(CallbackData *data) {
       << "Couldn't set view parameters\n";
       << "Couldn't set view parameters\n";
     write_error(speedtree_cat.warning());
     write_error(speedtree_cat.warning());
   }
   }
-  
+
   if (has_terrain()) {
   if (has_terrain()) {
     PStatTimer timer1(_draw_speedtree_terrain_pcollector);
     PStatTimer timer1(_draw_speedtree_terrain_pcollector);
     // Is this needed for terrain?
     // Is this needed for terrain?
     _terrain_render.UploadShaderConstants
     _terrain_render.UploadShaderConstants
-      (&_forest_render, _light_dir, 
+      (&_forest_render, _light_dir,
        _forest_render.GetRenderInfo().m_sLightMaterial);
        _forest_render.GetRenderInfo().m_sLightMaterial);
 
 
     // set terrain render states
     // set terrain render states
@@ -1515,14 +1513,14 @@ draw_callback(CallbackData *data) {
     // render actual terrain
     // render actual terrain
     bool terrain = _terrain_render.Render
     bool terrain = _terrain_render.Render
       (&_forest_render, _visible_terrain, SpeedTree::RENDER_PASS_STANDARD,
       (&_forest_render, _visible_terrain, SpeedTree::RENDER_PASS_STANDARD,
-       _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial, 
+       _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial,
        &_forest_render.GetRenderStats());
        &_forest_render.GetRenderStats());
 
 
     if (!terrain) {
     if (!terrain) {
       speedtree_cat.warning()
       speedtree_cat.warning()
         << "Failed to render terrain\n";
         << "Failed to render terrain\n";
       write_error(speedtree_cat.warning());
       write_error(speedtree_cat.warning());
-      
+
       // Clear the terrain so we don't keep spamming error messages.
       // Clear the terrain so we don't keep spamming error messages.
       _terrain = NULL;
       _terrain = NULL;
     }
     }
@@ -1537,7 +1535,7 @@ draw_callback(CallbackData *data) {
     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_BLENDING;
     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_BLENDING;
     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_NOTHING;
     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_NOTHING;
     set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode(mode));
     set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode(mode));
-    
+
     bool branches = _forest_render.RenderBranches(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
     bool branches = _forest_render.RenderBranches(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
     bool fronds = _forest_render.RenderFronds(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
     bool fronds = _forest_render.RenderFronds(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
     bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
     bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
@@ -1548,7 +1546,7 @@ draw_callback(CallbackData *data) {
     // disabled; but the billboards appear to have been rendered
     // disabled; but the billboards appear to have been rendered
     // successfully.  Weird.  Just removing this test from the
     // successfully.  Weird.  Just removing this test from the
     // condition.
     // condition.
-    
+
     if (!branches || !fronds || !leaf_meshes || !leaf_cards /* || !billboards */) {
     if (!branches || !fronds || !leaf_meshes || !leaf_cards /* || !billboards */) {
       speedtree_cat.warning()
       speedtree_cat.warning()
         << "Failed to render forest completely: "
         << "Failed to render forest completely: "
@@ -1592,27 +1590,27 @@ render_forest_into_shadow_maps() {
   for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
   for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
     const SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
     const SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
     const SpeedTree::SForestCullResults &light_cull = _shadow_infos[smi]._light_cull;
     const SpeedTree::SForestCullResults &light_cull = _shadow_infos[smi]._light_cull;
-    
+
     if (_forest_render.BeginShadowMap(smi, light_view)) {
     if (_forest_render.BeginShadowMap(smi, light_view)) {
       success &= _forest_render.UploadViewShaderParameters(light_view);
       success &= _forest_render.UploadViewShaderParameters(light_view);
-      
+
       // branch geometry can be rendered with backfacing triangle
       // branch geometry can be rendered with backfacing triangle
       // removed, so a closer tolerance can be used
       // removed, so a closer tolerance can be used
       SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f);
       SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f);
-      
+
       success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW);
       success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW);
-      
+
       // the remaining geometry types cannot be backface culled, so we
       // the remaining geometry types cannot be backface culled, so we
       // need a much more aggressive offset
       // need a much more aggressive offset
       SpeedTree::CRenderState::SetPolygonOffset(10.0f, 1.0f);
       SpeedTree::CRenderState::SetPolygonOffset(10.0f, 1.0f);
-      
+
       success &= _forest_render.RenderFronds(light_cull, SpeedTree::RENDER_PASS_SHADOW);
       success &= _forest_render.RenderFronds(light_cull, SpeedTree::RENDER_PASS_SHADOW);
       success &= _forest_render.RenderLeafMeshes(light_cull, SpeedTree::RENDER_PASS_SHADOW);
       success &= _forest_render.RenderLeafMeshes(light_cull, SpeedTree::RENDER_PASS_SHADOW);
       success &= _forest_render.RenderLeafCards(light_cull, SpeedTree::RENDER_PASS_SHADOW, light_view);
       success &= _forest_render.RenderLeafCards(light_cull, SpeedTree::RENDER_PASS_SHADOW, light_view);
-      
+
       // We don't bother to render billboard geometry into the shadow
       // We don't bother to render billboard geometry into the shadow
       // map(s).
       // map(s).
-      
+
       success &= _forest_render.EndShadowMap(smi);
       success &= _forest_render.EndShadowMap(smi);
     }
     }
   }
   }
@@ -1640,7 +1638,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
     // This is the first time we have entered the draw callback since
     // This is the first time we have entered the draw callback since
     // creating any SpeedTreeNode.  Now we have an opportunity to do
     // creating any SpeedTreeNode.  Now we have an opportunity to do
     // any initial setup that requires a graphics context.
     // any initial setup that requires a graphics context.
-    
+
 #ifdef SPEEDTREE_OPENGL
 #ifdef SPEEDTREE_OPENGL
     // For OpenGL, we have to ensure GLEW has been initialized.
     // For OpenGL, we have to ensure GLEW has been initialized.
     // (SpeedTree uses it, though Panda doesn't.)
     // (SpeedTree uses it, though Panda doesn't.)
@@ -1684,7 +1682,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
       if (instances.empty()) {
       if (instances.empty()) {
         continue;
         continue;
       }
       }
-      
+
       int max_instances = 2;
       int max_instances = 2;
       SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
       SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
       si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree());
       si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree());
@@ -1708,7 +1706,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
 #endif
 #endif
       }
       }
 
 
-      if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(), 
+      if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(),
                                            max_instances, speedtree_horizontal_billboards,
                                            max_instances, speedtree_horizontal_billboards,
                                            os_textures_dir.c_str())) {
                                            os_textures_dir.c_str())) {
         if (speedtree_cat.is_debug()) {
         if (speedtree_cat.is_debug()) {
@@ -1735,7 +1733,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
 
 
     if (has_terrain()) {
     if (has_terrain()) {
       // Now initialize the terrain.
       // Now initialize the terrain.
-      if (!_terrain_render.Init(speedtree_terrain_num_lods, 
+      if (!_terrain_render.Init(speedtree_terrain_num_lods,
                                 speedtree_terrain_resolution,
                                 speedtree_terrain_resolution,
                                 speedtree_terrain_cell_size,
                                 speedtree_terrain_cell_size,
                                 _terrain->get_st_vertex_format())) {
                                 _terrain->get_st_vertex_format())) {
@@ -1780,9 +1778,9 @@ cull_forest() {
       SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull;
       SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull;
 
 
       _forest_render.ComputeLightView
       _forest_render.ComputeLightView
-        (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi, 
+        (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi,
          light_view, 0.0f);
          light_view, 0.0f);
-      
+
       light_view.SetLodRefPoint(_view.GetCameraPos());
       light_view.SetLodRefPoint(_view.GetCameraPos());
       _forest_render.CullAndComputeLOD(light_view, light_cull, false);
       _forest_render.CullAndComputeLOD(light_view, light_cull, false);
     }
     }
@@ -1793,7 +1791,7 @@ cull_forest() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::print_forest_stats
 //     Function: SpeedTreeNode::print_forest_stats
 //       Access: Private
 //       Access: Private
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SpeedTreeNode::
 void SpeedTreeNode::
 print_forest_stats(const SpeedTree::CForest::SPopulationStats &forest_stats) const {
 print_forest_stats(const SpeedTree::CForest::SPopulationStats &forest_stats) const {
@@ -1894,7 +1892,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::InstanceList::output
 //     Function: SpeedTreeNode::InstanceList::output
 //       Access: Published
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SpeedTreeNode::InstanceList::
 void SpeedTreeNode::InstanceList::
 output(ostream &out) const {
 output(ostream &out) const {
@@ -1904,7 +1902,7 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::InstanceList::write
 //     Function: SpeedTreeNode::InstanceList::write
 //       Access: Published
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SpeedTreeNode::InstanceList::
 void SpeedTreeNode::InstanceList::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {