Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/cullTraverserData.cxx

Go to the documentation of this file.
00001 // Filename: cullTraverserData.cxx
00002 // Created by:  drose (06Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "cullTraverserData.h"
00020 #include "cullTraverser.h"
00021 #include "config_pgraph.h"
00022 #include "pandaNode.h"
00023 #include "colorAttrib.h"
00024 #include "textureAttrib.h"
00025 #include "renderModeAttrib.h"
00026 #include "billboardEffect.h"
00027 #include "compassEffect.h"
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: CullTraverserData::apply_specific_transform
00031 //       Access: Public
00032 //  Description: Applies the indicated transform and state changes
00033 //               (e.g. as extracted from a node) onto the current
00034 //               data.  This also evaluates billboards, etc.
00035 ////////////////////////////////////////////////////////////////////
00036 void CullTraverserData::
00037 apply_transform_and_state(CullTraverser *trav, 
00038                           CPT(TransformState) node_transform, 
00039                           CPT(RenderState) node_state,
00040                           CPT(RenderEffects) node_effects) {
00041   // First, compute the _net_transform, because we need it for the
00042   // compass and billboard effects.
00043   _net_transform = _net_transform->compose(node_transform);
00044 
00045   const CompassEffect *compass = node_effects->get_compass();
00046   if (compass != (const CompassEffect *)NULL) {
00047     CPT(TransformState) compass_transform = 
00048       compass->do_compass(_net_transform, node_transform);
00049     _net_transform = _net_transform->compose(compass_transform);
00050     node_transform = node_transform->compose(compass_transform);
00051   }
00052 
00053   const BillboardEffect *billboard = node_effects->get_billboard();
00054   if (billboard != (const BillboardEffect *)NULL) {
00055     CPT(TransformState) billboard_transform = 
00056       billboard->do_billboard(_net_transform, trav->get_camera_transform());
00057     _net_transform = _net_transform->compose(billboard_transform);
00058     node_transform = node_transform->compose(billboard_transform);
00059   }
00060     
00061   if (!node_transform->is_identity()) {
00062     _render_transform = _render_transform->compose(node_transform);
00063 
00064     if ((_view_frustum != (GeometricBoundingVolume *)NULL) ||
00065         (_guard_band != (GeometricBoundingVolume *)NULL)) {
00066       // We need to move the viewing frustums into the node's
00067       // coordinate space by applying the node's inverse transform.
00068       if (node_transform->is_singular()) {
00069         // But we can't invert a singular transform!  Instead of
00070         // trying, we'll just give up on frustum culling from this
00071         // point down.
00072         _view_frustum = (GeometricBoundingVolume *)NULL;
00073         _guard_band = (GeometricBoundingVolume *)NULL;
00074 
00075       } else {
00076         CPT(TransformState) inv_transform = 
00077           node_transform->invert_compose(TransformState::make_identity());
00078 
00079         // Copy the bounding volumes for the frustums so we can
00080         // transform them.
00081         if (_view_frustum != (GeometricBoundingVolume *)NULL) {
00082           _view_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
00083           _view_frustum->xform(inv_transform->get_mat());
00084         }
00085         
00086         if (_guard_band != (GeometricBoundingVolume *)NULL) {
00087           _guard_band = DCAST(GeometricBoundingVolume, _guard_band->make_copy());
00088           _guard_band->xform(inv_transform->get_mat());
00089         }
00090       }
00091     }
00092   }
00093 
00094   _state = _state->compose(node_state);
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: CullTraverserData::is_in_view_impl
00099 //       Access: Private
00100 //  Description: The private implementation of is_in_view().
00101 ////////////////////////////////////////////////////////////////////
00102 bool CullTraverserData::
00103 is_in_view_impl() {
00104   // By the time we get here, we know we have a viewing frustum.
00105   nassertr(_view_frustum != (GeometricBoundingVolume *)NULL, true);
00106 
00107   const BoundingVolume &node_volume = node()->get_bound();
00108   nassertr(node_volume.is_of_type(GeometricBoundingVolume::get_class_type()), false);
00109   const GeometricBoundingVolume *node_gbv =
00110     DCAST(GeometricBoundingVolume, &node_volume);
00111 
00112   int result = _view_frustum->contains(node_gbv);
00113   if (result == BoundingVolume::IF_no_intersection) {
00114     // No intersection at all.  Cull.
00115     if (!fake_view_frustum_cull) {
00116       return false;
00117     }
00118 
00119     // If we have fake view-frustum culling enabled, instead of
00120     // actually culling an object we simply force it to be drawn in
00121     // red wireframe.
00122     _view_frustum = (GeometricBoundingVolume *)NULL;
00123     CPT(RenderState) fake_state = get_fake_view_frustum_cull_state();
00124     _state = _state->compose(fake_state);
00125     
00126   } else if ((result & BoundingVolume::IF_all) != 0) {
00127     // The node and its descendants are completely enclosed within
00128     // the frustum.  No need to cull further.
00129     _view_frustum = (GeometricBoundingVolume *)NULL;
00130 
00131   } else {
00132     if (node()->is_final()) {
00133       // The bounding volume is partially, but not completely,
00134       // within the viewing frustum.  Normally we'd keep testing
00135       // child bounding volumes as we continue down.  But this node
00136       // has the "final" flag, so the user is claiming that there is
00137       // some important reason we should consider everything visible
00138       // at this point.  So be it.
00139       _view_frustum = (GeometricBoundingVolume *)NULL;
00140     }
00141   }
00142 
00143   return true;
00144 }
00145 
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: CullTraverserData::get_fake_view_frustum_cull_state
00149 //       Access: Private, Static
00150 //  Description: Returns a RenderState for rendering stuff in red
00151 //               wireframe, strictly for the fake_view_frustum_cull
00152 //               effect.
00153 ////////////////////////////////////////////////////////////////////
00154 CPT(RenderState) CullTraverserData::
00155 get_fake_view_frustum_cull_state() {
00156   // Once someone asks for this pointer, we hold its reference count
00157   // and never free it.
00158   static CPT(RenderState) state = (const RenderState *)NULL;
00159   if (state == (const RenderState *)NULL) {
00160     state = RenderState::make
00161       (ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)),
00162        TextureAttrib::make_off(),
00163        RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
00164        RenderState::get_max_priority());
00165   }
00166   return state;
00167 }
00168 

Generated on Fri May 2 00:41:30 2003 for Panda by doxygen1.3