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

panda/src/pgraph/findApproxLevelEntry.cxx

Go to the documentation of this file.
00001 // Filename: findApproxLevelEntry.cxx
00002 // Created by:  drose (13Mar02)
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 "findApproxLevelEntry.h"
00020 #include "nodePathCollection.h"
00021 #include "pandaNode.h"
00022 
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: FindApproxLevelEntry::output
00026 //       Access: Public
00027 //  Description: Formats the entry for meaningful output.  For
00028 //               debugging only.
00029 ////////////////////////////////////////////////////////////////////
00030 void FindApproxLevelEntry::
00031 output(ostream &out) const {
00032   out << "(" << _node_path << "):";
00033   if (is_solution(0)) {
00034     out << " solution!";
00035   } else {
00036     out << "(";
00037     _approx_path.output_component(out, _i);
00038     out << ")," << _i;
00039   }
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: FindApproxLevelEntry::consider_node
00044 //       Access: Public
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 void FindApproxLevelEntry::
00048 consider_node(NodePathCollection &result, FindApproxLevel &next_level,
00049               int max_matches, int increment) const {
00050   nassertv(_i + increment < _approx_path.get_num_components());
00051 
00052   if (_approx_path.is_component_match_many(_i + increment)) {
00053     // Match any number, zero or more, levels of nodes.  This is the
00054     // tricky case that requires this whole nutty breadth-first thing.
00055 
00056     // This means we must reconsider our own entry with the next path
00057     // entry, before we consider the next entry--this supports
00058     // matching zero levels of nodes.
00059 
00060     // We used to make a temporary copy of our own record, and then
00061     // increment _i on that copy, but we can't do that nowadays
00062     // because the WorkingNodePath object stores a pointer to each
00063     // previous generation, which means we can't use any temporary
00064     // FindApproxLevelEntry objects.  Instead, we pass around the
00065     // increment parameter, which increments _i on the fly.
00066 
00067     if (is_solution(increment + 1)) {
00068       // Does this now represent a solution?
00069       result.add_path(_node_path.get_node_path());
00070       if (max_matches > 0 && result.get_num_paths() >= max_matches) { 
00071         return;
00072       }
00073     } else {
00074       consider_node(result, next_level, max_matches, increment + 1);
00075     }
00076   }
00077 
00078   PandaNode *this_node = _node_path.node();
00079   nassertv(this_node != (PandaNode *)NULL);
00080 
00081   bool stashed_only = next_is_stashed(increment);
00082 
00083   if (!stashed_only) {
00084     // Check the normal list of children.
00085     int num_children = this_node->get_num_children();
00086     for (int i = 0; i < num_children; i++) {
00087       PandaNode *child_node = this_node->get_child(i);
00088       
00089       consider_next_step(result, child_node, next_level, max_matches, increment);
00090       if (max_matches > 0 && result.get_num_paths() >= max_matches) {
00091         return;
00092       }
00093     }
00094   }
00095 
00096   if (_approx_path.return_stashed() || stashed_only) {
00097     // Also check the stashed list.
00098     int num_stashed = this_node->get_num_stashed();
00099     for (int i = 0; i < num_stashed; i++) {
00100       PandaNode *stashed_node = this_node->get_stashed(i);
00101       
00102       consider_next_step(result, stashed_node, next_level, max_matches, increment);
00103       if (max_matches > 0 && result.get_num_paths() >= max_matches) {
00104         return;
00105       }
00106     }
00107   }
00108 }
00109 
00110 ////////////////////////////////////////////////////////////////////
00111 //     Function: FindApproxLevelEntry::consider_next_step
00112 //       Access: Public
00113 //  Description: Compares the indicated child node (which is assumed
00114 //               to be a child of _node_path) with the next component
00115 //               of the path.  If it matches, generates whatever
00116 //               additional entries are appropriate and stores them in
00117 //               next_level.
00118 //
00119 //               If a complete solution is found, stores it in result.
00120 ////////////////////////////////////////////////////////////////////
00121 void FindApproxLevelEntry::
00122 consider_next_step(NodePathCollection &result, PandaNode *child_node,
00123                    FindApproxLevel &next_level, int max_matches,
00124                    int increment) const {
00125   if (!_approx_path.return_hidden() &&
00126       child_node->get_draw_mask().is_zero()) {
00127     // If the approx path does not allow us to return hidden nodes,
00128     // and this node has indeed been completely hidden, then stop
00129     // here.
00130     return;
00131   }
00132 
00133   nassertv(_i + increment < _approx_path.get_num_components());
00134 
00135   if (_approx_path.is_component_match_many(_i + increment)) {
00136     // Match any number, zero or more, levels of nodes.  This is the
00137     // tricky case that requires this whole nutty breadth-first thing.
00138 
00139     // And now we just add the next entry without incrementing its
00140     // path entry.
00141 
00142     FindApproxLevelEntry next(*this, increment);
00143     next._node_path = WorkingNodePath(_node_path, child_node);
00144     next_level.add_entry(next);
00145 
00146   } else {
00147     if (_approx_path.matches_component(_i + increment, child_node)) {
00148       // That matched, and it consumes one path entry.
00149       FindApproxLevelEntry next(*this, increment);
00150       next._i++;
00151       next._node_path = WorkingNodePath(_node_path, child_node);
00152       next_level.add_entry(next);
00153     }
00154   }
00155 }

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