Panda3D
 All Classes Functions Variables Enumerations
speedTreeNode.cxx
00001 // Filename: speedTreeNode.cxx
00002 // Created by:  drose (13Mar09)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandabase.h"
00016 #include "speedTreeNode.h"
00017 #include "stBasicTerrain.h"
00018 #include "virtualFileSystem.h"
00019 #include "config_util.h"
00020 #include "cullTraverser.h"
00021 #include "cullableObject.h"
00022 #include "cullHandler.h"
00023 #include "omniBoundingVolume.h"
00024 #include "boundingSphere.h"
00025 #include "boundingBox.h"
00026 #include "clockObject.h"
00027 #include "geomDrawCallbackData.h"
00028 #include "graphicsStateGuardian.h"
00029 #include "textureAttrib.h"
00030 #include "lightAttrib.h"
00031 #include "directionalLight.h"
00032 #include "ambientLight.h"
00033 #include "loader.h"
00034 #include "deg_2_rad.h"
00035 #include "sceneGraphReducer.h"
00036 #include "pStatTimer.h"
00037 
00038 #ifdef SPEEDTREE_OPENGL
00039 #include "glew/glew.h"
00040 #endif  // SPEEDTREE_OPENGL
00041 
00042 #ifdef SPEEDTREE_DIRECTX9
00043 #include "dxGraphicsStateGuardian9.h"
00044 #endif
00045 
00046 double SpeedTreeNode::_global_time_delta = 0.0;
00047 bool SpeedTreeNode::_authorized;
00048 bool SpeedTreeNode::_done_first_init;
00049 TypeHandle SpeedTreeNode::_type_handle;
00050 TypeHandle SpeedTreeNode::DrawCallback::_type_handle;
00051 
00052 PStatCollector SpeedTreeNode::_cull_speedtree_pcollector("Cull:SpeedTree");
00053 PStatCollector SpeedTreeNode::_cull_speedtree_shadows_pcollector("Cull:SpeedTree:Shadows");
00054 PStatCollector SpeedTreeNode::_cull_speedtree_trees_pcollector("Cull:SpeedTree:Trees");
00055 PStatCollector SpeedTreeNode::_cull_speedtree_terrain_pcollector("Cull:SpeedTree:Terrain");
00056 PStatCollector SpeedTreeNode::_draw_speedtree_pcollector("Draw:SpeedTree");
00057 PStatCollector SpeedTreeNode::_draw_speedtree_shadows_pcollector("Draw:SpeedTree:Shadows");
00058 PStatCollector SpeedTreeNode::_draw_speedtree_trees_pcollector("Draw:SpeedTree:Trees");
00059 PStatCollector SpeedTreeNode::_draw_speedtree_terrain_pcollector("Draw:SpeedTree:Terrain");
00060 PStatCollector SpeedTreeNode::_draw_speedtree_terrain_update_pcollector("Draw:SpeedTree:Terrain:Update");
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: SpeedTreeNode::Constructor
00064 //       Access: Published
00065 //  Description:
00066 ////////////////////////////////////////////////////////////////////
00067 SpeedTreeNode::
00068 SpeedTreeNode(const string &name) :
00069   PandaNode(name),
00070 #ifdef ST_DELETE_FOREST_HACK
00071   // Early versions of SpeedTree don't destruct unused CForestRender
00072   // objects correctly.  To avoid crashes, we have to leak these
00073   // things.
00074   _forest_render(*(new SpeedTree::CForestRender)),
00075 #endif
00076   _time_delta(0.0)
00077 {
00078   init_node();
00079   // For now, set an infinite bounding volume.  Maybe in the future
00080   // we'll change this to match whatever set of trees we're holding,
00081   // though it probably doesn't really matter too much.
00082   //set_internal_bounds(new OmniBoundingVolume);
00083   //  set_internal_bounds(new BoundingSphere(LPoint3::zero(), 10.0f));
00084 
00085   // Intialize the render params.  First, get the shader directory.
00086   Filename shaders_dir = speedtree_shaders_dir;
00087 
00088   // We expect the shader directory to contain at least this one token
00089   // filename (to prove it's the right directory).
00090   Filename token_filename = "Branch.hlsl";
00091   if (!Filename(shaders_dir, token_filename).exists()) {
00092     // If that shader directory doesn't work, look along the model-path.
00093     if (token_filename.resolve_filename(get_model_path())) {
00094       shaders_dir = token_filename.get_dirname();
00095     } else {
00096       if (!shaders_dir.is_directory()) {
00097         speedtree_cat.warning()
00098           << "speedtree-shaders-dir is set to " << shaders_dir
00099           << ", which doesn't exist.\n";
00100       } else {
00101         speedtree_cat.warning()
00102           << "speedtree-shaders-dir is set to " << shaders_dir
00103           << ", which exists but doesn't contain " <<  token_filename
00104           << ".\n";
00105       }
00106     }
00107   }
00108 
00109   _os_shaders_dir = shaders_dir.to_os_specific();
00110   // Ensure the path ends with a terminal slash; SpeedTree requires this.
00111 #if defined(WIN32) || defined(WIN64)
00112   if (!_os_shaders_dir.empty() && _os_shaders_dir[_os_shaders_dir.length() - 1] != '\\') {
00113     _os_shaders_dir += "\\";
00114   }
00115 #else
00116   if (!_os_shaders_dir.empty() && _os_shaders_dir[_os_shaders_dir.length() - 1] != '/') {
00117     _os_shaders_dir += "/";
00118   }
00119 #endif
00120 
00121   SpeedTree::SForestRenderInfo render_info;
00122   render_info.m_strShaderPath = _os_shaders_dir.c_str();
00123   _forest_render.SetRenderInfo(render_info);
00124 
00125   // Now apply the rest of the config settings.
00126   reload_config();
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: SpeedTreeNode::count_total_instances
00131 //       Access: Published
00132 //  Description: Returns the total number of trees that will be
00133 //               rendered by this node, counting all instances of all
00134 //               trees.
00135 ////////////////////////////////////////////////////////////////////
00136 int SpeedTreeNode::
00137 count_total_instances() const {
00138   int total_instances = 0;
00139   Trees::const_iterator ti;
00140   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
00141     InstanceList *instance_list = (*ti);
00142     total_instances += instance_list->get_num_instances();
00143   }
00144 
00145   return total_instances;
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: SpeedTreeNode::add_tree
00150 //       Access: Published
00151 //  Description: Adds a new tree for rendering.  Returns the
00152 //               InstanceList which can be used to add to the
00153 //               instances for this tree.  If the tree has previously
00154 //               been added, returns the existing InstanceList.
00155 ////////////////////////////////////////////////////////////////////
00156 SpeedTreeNode::InstanceList &SpeedTreeNode::
00157 add_tree(const STTree *tree) {
00158   nassertr(is_valid(), *(InstanceList *)NULL);
00159   nassertr(tree->is_valid(), *(InstanceList *)NULL);
00160 
00161   InstanceList ilist(tree);
00162   Trees::iterator ti = _trees.find(&ilist);
00163   if (ti == _trees.end()) {
00164     // This is the first time that this particular tree has been
00165     // added.
00166     InstanceList *instance_list = new InstanceList(tree);
00167     pair<Trees::iterator, bool> result = _trees.insert(instance_list);
00168     ti = result.first;
00169     bool inserted = result.second;
00170     nassertr(inserted, *(*ti));
00171 
00172     if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->get_tree())) {
00173       speedtree_cat.warning()
00174         << "Failed to register tree " << tree->get_fullpath() << "\n";
00175       write_error(speedtree_cat.warning());
00176     }
00177   }
00178 
00179   _needs_repopulate = true;
00180   mark_internal_bounds_stale();
00181   InstanceList *instance_list = (*ti);
00182   return *instance_list;
00183 }
00184 
00185 ////////////////////////////////////////////////////////////////////
00186 //     Function: SpeedTreeNode::remove_tree
00187 //       Access: Published
00188 //  Description: Removes all instances of the indicated tree.  Returns
00189 //               the number of instances removed.
00190 ////////////////////////////////////////////////////////////////////
00191 int SpeedTreeNode::
00192 remove_tree(const STTree *tree) {
00193   InstanceList ilist(tree);
00194   Trees::iterator ti = _trees.find(&ilist);
00195   if (ti == _trees.end()) {
00196     // The tree was not already present.
00197     return 0;
00198   }
00199 
00200   if (!_forest_render.UnregisterTree(tree->get_tree())) {
00201     speedtree_cat.warning()
00202       << "Failed to unregister tree " << tree->get_fullpath() << "\n";
00203     write_error(speedtree_cat.warning());
00204   }
00205 
00206   _needs_repopulate = true;
00207   mark_internal_bounds_stale();
00208 
00209   InstanceList *instance_list = (*ti);
00210   int num_removed = instance_list->get_num_instances();
00211   _trees.erase(ti);
00212   delete instance_list;
00213 
00214   return num_removed;
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: SpeedTreeNode::remove_all_trees
00219 //       Access: Published
00220 //  Description: Removes all instances of all trees from the node.
00221 ////////////////////////////////////////////////////////////////////
00222 void SpeedTreeNode::
00223 remove_all_trees() {
00224   Trees::iterator ti;
00225   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
00226     InstanceList *instance_list = (*ti);
00227     const STTree *tree = instance_list->get_tree();
00228     if (!_forest_render.UnregisterTree(tree->get_tree())) {
00229       speedtree_cat.warning()
00230         << "Failed to unregister tree " << tree->get_fullpath() << "\n";
00231       write_error(speedtree_cat.warning());
00232     }
00233     delete instance_list;
00234   }
00235 
00236   _trees.clear();
00237   _needs_repopulate = true;
00238   mark_internal_bounds_stale();
00239 }
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: SpeedTreeNode::has_instance_list
00243 //       Access: Published
00244 //  Description: Returns true if the indicated tree has any instances
00245 //               within this node, false otherwise.
00246 ////////////////////////////////////////////////////////////////////
00247 bool SpeedTreeNode::
00248 has_instance_list(const STTree *tree) const {
00249   InstanceList ilist(tree);
00250   Trees::const_iterator ti = _trees.find(&ilist);
00251   return (ti != _trees.end());
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: SpeedTreeNode::get_instance_list
00256 //       Access: Published
00257 //  Description: Returns a list of transforms that corresponds to the
00258 //               instances at which the indicated tree appears.  You
00259 //               should ensure that has_instance_list() returns true
00260 //               before calling this method.
00261 ////////////////////////////////////////////////////////////////////
00262 const SpeedTreeNode::InstanceList &SpeedTreeNode::
00263 get_instance_list(const STTree *tree) const {
00264   InstanceList ilist(tree);
00265   Trees::const_iterator ti = _trees.find(&ilist);
00266   if (ti == _trees.end()) {
00267     // The tree was not already present.
00268     static InstanceList empty_list((STTree *)NULL);
00269     return empty_list;
00270   }
00271 
00272   InstanceList *instance_list = (*ti);
00273   return *instance_list;
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: SpeedTreeNode::modify_instance_list
00278 //       Access: Published
00279 //  Description: Returns a modifiable list of transforms that
00280 //               corresponds to the instances of this tree.  This is
00281 //               equivalent to add_tree().
00282 ////////////////////////////////////////////////////////////////////
00283 SpeedTreeNode::InstanceList &SpeedTreeNode::
00284 modify_instance_list(const STTree *tree) {
00285   return add_tree(tree);
00286 }
00287 
00288 ////////////////////////////////////////////////////////////////////
00289 //     Function: SpeedTreeNode::add_instance
00290 //       Access: Published
00291 //  Description: Adds a new instance of the indicated tree at the
00292 //               indicated transform.
00293 ////////////////////////////////////////////////////////////////////
00294 void SpeedTreeNode::
00295 add_instance(const STTree *tree, const STTransform &transform) {
00296   if (speedtree_follow_terrain && has_terrain()) {
00297     STTransform new_transform = transform;
00298     new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
00299     add_tree(tree).add_instance(new_transform);
00300   } else {
00301     add_tree(tree).add_instance(transform);
00302   }
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: SpeedTreeNode::add_instances
00307 //       Access: Published
00308 //  Description: Walks the scene graph beginning at root, looking for
00309 //               nested SpeedTreeNodes.  For each SpeedTreeNode found,
00310 //               adds all of the instances defined within that
00311 //               SpeedTreeNode as instances of this node, after
00312 //               applying the indicated scene-graph transform.
00313 ////////////////////////////////////////////////////////////////////
00314 void SpeedTreeNode::
00315 add_instances(const NodePath &root, const TransformState *transform) {
00316   nassertv(!root.is_empty());
00317   r_add_instances(root.node(), transform->compose(root.get_transform()),
00318                   Thread::get_current_thread());
00319 }
00320 
00321 ////////////////////////////////////////////////////////////////////
00322 //     Function: SpeedTreeNode::add_instances_from
00323 //       Access: Published
00324 //  Description: Adds all of the instances defined within the
00325 //               indicated SpeedTreeNode as instances of this node.
00326 //               Does not recurse to children.
00327 ////////////////////////////////////////////////////////////////////
00328 void SpeedTreeNode::
00329 add_instances_from(const SpeedTreeNode *other) {
00330   int num_trees = other->get_num_trees();
00331   for (int ti = 0; ti < num_trees; ++ti) {
00332     const InstanceList &other_instance_list = other->get_instance_list(ti);
00333     const STTree *tree = other_instance_list.get_tree();
00334     InstanceList &this_instance_list = add_tree(tree);
00335     
00336     int num_instances = other_instance_list.get_num_instances();
00337     for (int i = 0; i < num_instances; ++i) {
00338       STTransform other_trans = other_instance_list.get_instance(i);
00339       this_instance_list.add_instance(other_trans);
00340     }
00341   }
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: SpeedTreeNode::add_instances_from
00346 //       Access: Published
00347 //  Description: Adds all of the instances defined within the
00348 //               indicated SpeedTreeNode as instances of this node,
00349 //               after applying the indicated scene-graph transform.
00350 //               Does not recurse to children.
00351 ////////////////////////////////////////////////////////////////////
00352 void SpeedTreeNode::
00353 add_instances_from(const SpeedTreeNode *other, const TransformState *transform) {
00354   int num_trees = other->get_num_trees();
00355   for (int ti = 0; ti < num_trees; ++ti) {
00356     const InstanceList &other_instance_list = other->get_instance_list(ti);
00357     const STTree *tree = other_instance_list.get_tree();
00358     InstanceList &this_instance_list = add_tree(tree);
00359     
00360     int num_instances = other_instance_list.get_num_instances();
00361     for (int i = 0; i < num_instances; ++i) {
00362       CPT(TransformState) other_trans = other_instance_list.get_instance(i);
00363       CPT(TransformState) new_trans = transform->compose(other_trans);
00364 
00365       if (speedtree_follow_terrain && has_terrain()) {
00366         STTransform new_transform = new_trans;
00367         new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
00368         this_instance_list.add_instance(new_transform);
00369 
00370       } else {
00371         this_instance_list.add_instance(new_trans.p());
00372       }
00373     }
00374   }
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: SpeedTreeNode::add_random_instances
00379 //       Access: Published
00380 //  Description: Creates a number of random instances of the indicated
00381 //               true, within the indicated range.  If a terrain is
00382 //               present, height_min and height_max restrict trees to
00383 //               the (x, y) positions that fall within the indicated
00384 //               terrain, and slope_min and slope_max restrict trees
00385 //               to the (x, y) positions that have a matching slope.
00386 //               If a terrain is not present, height_min and
00387 //               height_max specify a random range of Z heights, and
00388 //               slope_min and slope_max are ignored.
00389 ////////////////////////////////////////////////////////////////////
00390 void SpeedTreeNode::
00391 add_random_instances(const STTree *tree, int quantity, 
00392                      PN_stdfloat x_min, PN_stdfloat x_max, 
00393                      PN_stdfloat y_min, PN_stdfloat y_max,
00394                      PN_stdfloat scale_min, PN_stdfloat scale_max,
00395                      PN_stdfloat height_min, PN_stdfloat height_max,
00396                      PN_stdfloat slope_min, PN_stdfloat slope_max,
00397                      Randomizer &randomizer) {
00398   InstanceList &instance_list = add_tree(tree);
00399   _needs_repopulate = true;
00400 
00401   for (int i = 0; i < quantity; ++i) {
00402     STTransform transform;
00403     transform._pos[0] = randomizer.random_real(x_max - x_min) + x_min;
00404     transform._pos[1] = randomizer.random_real(y_max - y_min) + y_min;
00405     transform._rotate = randomizer.random_real(360.0);
00406     transform._scale = randomizer.random_real(scale_max - scale_min) + scale_min;
00407 
00408     if (has_terrain()) {
00409       // Spin till we find a valid match with terrain.
00410       int repeat_count = speedtree_max_random_try_count;
00411       while (!_terrain->placement_is_acceptable(transform._pos[0], transform._pos[1], height_min, height_max, slope_min, slope_max)) {
00412         transform._pos[0] = randomizer.random_real(x_max - x_min) + x_min;
00413         transform._pos[1] = randomizer.random_real(y_max - y_min) + y_min;
00414         if (--repeat_count == 0) {
00415           nassert_raise("Exceeded speedtree-max-random-try-count; bad placement parameters?");
00416           return;
00417         }
00418       }
00419       transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]);
00420       
00421     } else {
00422       // No terrain; just pick a random height.
00423       transform._pos[2] = randomizer.random_real(height_max - height_min) + height_min;
00424     }
00425     instance_list.add_instance(transform);
00426   }
00427 }
00428 
00429 ////////////////////////////////////////////////////////////////////
00430 //     Function: SpeedTreeNode::add_from_stf
00431 //       Access: Published
00432 //  Description: Opens and reads the named STF (SpeedTree Forest)
00433 //               file, and adds the SRT files named within as
00434 //               instances of this node.  Returns true on success,
00435 //               false on failure.
00436 ////////////////////////////////////////////////////////////////////
00437 bool SpeedTreeNode::
00438 add_from_stf(const Filename &stf_filename, const LoaderOptions &options) {
00439   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00440 
00441   Filename fullpath = Filename::text_filename(stf_filename);
00442   vfs->resolve_filename(fullpath, get_model_path());
00443 
00444   if (!vfs->exists(fullpath)) {
00445     speedtree_cat.warning()
00446       << "Couldn't find " << stf_filename << "\n";
00447     return false;
00448   }
00449 
00450   PT(VirtualFile) file = vfs->get_file(fullpath);
00451   if (file == (VirtualFile *)NULL) {
00452     // No such file.
00453     speedtree_cat.error()
00454       << "Could not find " << stf_filename << "\n";
00455     return false;
00456   }
00457 
00458   if (speedtree_cat.is_debug()) {
00459     speedtree_cat.debug()
00460       << "Reading STF file " << fullpath << "\n";
00461   }
00462 
00463   istream *in = file->open_read_file(true);
00464   bool success = add_from_stf(*in, fullpath, options);
00465   vfs->close_read_file(in);
00466 
00467   return success;
00468 }
00469 
00470 ////////////////////////////////////////////////////////////////////
00471 //     Function: SpeedTreeNode::add_from_stf
00472 //       Access: Published
00473 //  Description: Reads text data from the indicated stream, which is
00474 //               understood to represent the named STF (SpeedTree
00475 //               Forest) file, and adds the SRT files named within as
00476 //               instances of this node.  Returns true on success,
00477 //               false on failure.
00478 //
00479 //               The pathname is used for reference only; if nonempty,
00480 //               it provides a search directory for named SRT files.
00481 //
00482 //               The Loader and LoaderOptions, if provided, are used
00483 //               to load the SRT files.  If the Loader pointer is
00484 //               NULL, the default global Loader is used instead.
00485 ////////////////////////////////////////////////////////////////////
00486 bool SpeedTreeNode::
00487 add_from_stf(istream &in, const Filename &pathname, 
00488              const LoaderOptions &options, Loader *loader) {
00489   if (loader == NULL) {
00490     loader = Loader::get_global_ptr();
00491   }
00492   string os_filename;
00493 
00494   Filename dirname = pathname.get_dirname();
00495   dirname.make_absolute();
00496   DSearchPath search;
00497   search.append_directory(dirname);
00498 
00499   typedef pmap<Filename, CPT(STTree) > AlreadyLoaded;
00500   AlreadyLoaded already_loaded;
00501 
00502   // The STF file format doesn't allow for spaces in the SRT filename.
00503   in >> os_filename;
00504   while (in && !in.eof()) {
00505     CPT(STTree) tree;
00506     Filename srt_filename = Filename::from_os_specific(os_filename);
00507     AlreadyLoaded::iterator ai = already_loaded.find(srt_filename);
00508     if (ai != already_loaded.end()) {
00509       tree = (*ai).second;
00510     } else {
00511       // Resolve the SRT filename relative to the STF file first.
00512       srt_filename.resolve_filename(search);
00513 
00514       // Now load up the SRT file using the Panda loader (which will
00515       // also search the model-path if necessary).
00516       PT(PandaNode) srt_root = loader->load_sync(srt_filename);
00517 
00518       if (srt_root != NULL) {
00519         NodePath srt(srt_root);
00520         NodePath srt_np = srt.find("**/+SpeedTreeNode");
00521         if (!srt_np.is_empty()) {
00522           SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node());
00523           if (srt_node->get_num_trees() >= 1) {
00524             tree = srt_node->get_tree(0);
00525           }
00526         }
00527       }
00528       already_loaded[srt_filename] = tree;
00529     }
00530 
00531     // Now we've loaded the SRT data, so apply it the appropriate
00532     // number of times to the locations specified.
00533     int num_instances;
00534     in >> num_instances;
00535     for (int ni = 0; ni < num_instances && in && !in.eof(); ++ni) {
00536       LPoint3 pos;
00537       PN_stdfloat rotate, scale;
00538       in >> pos[0] >> pos[1] >> pos[2] >> rotate >> scale;
00539 
00540       if (!speedtree_5_2_stf) {
00541         // 5.1 or earlier stf files also included these additional
00542         // values, which we will ignore:
00543         PN_stdfloat height_min, height_max, slope_min, slope_max;
00544         in >> height_min >> height_max >> slope_min >> slope_max;
00545       }
00546 
00547       if (tree != NULL) {
00548         add_instance(tree, STTransform(pos, rad_2_deg(rotate), scale));
00549       }
00550     }
00551     in >> os_filename;
00552   }
00553 
00554   // Consume any whitespace at the end of the file.
00555   in >> ws;
00556 
00557   if (!in.eof()) {
00558     // If we didn't read all the way to end-of-file, there was an
00559     // error.
00560     in.clear();
00561     string text;
00562     in >> text;
00563     speedtree_cat.error()
00564       << "Unexpected text in " << pathname << " at \"" << text << "\"\n";
00565     return false;
00566   }
00567 
00568   // Return true if we successfully read all the way to end-of-file.
00569   return true;
00570 }
00571 
00572 ////////////////////////////////////////////////////////////////////
00573 //     Function: SpeedTreeNode::setup_terrain
00574 //       Access: Published
00575 //  Description: A convenience function to set up terrain geometry by
00576 //               reading a terrain.txt file as defined by SpeedTree.
00577 //               This file names the various map files that define the
00578 //               terrain, as well as defining parameters size as its
00579 //               size and color.
00580 //
00581 //               This method implicitly creates a STBasicTerrain
00582 //               object and passes it to set_terrain().
00583 ////////////////////////////////////////////////////////////////////
00584 bool SpeedTreeNode::
00585 setup_terrain(const Filename &terrain_file) {
00586   PT(STBasicTerrain) terrain = new STBasicTerrain;
00587   if (terrain->setup_terrain(terrain_file)) {
00588     set_terrain(terrain);
00589     return true;
00590   }
00591 
00592   return false;
00593 }
00594 
00595 ////////////////////////////////////////////////////////////////////
00596 //     Function: SpeedTreeNode::set_terrain
00597 //       Access: Published
00598 //  Description: Associated a terrain with the node.  If the terrain
00599 //               has not already been loaded prior to this call,
00600 //               load_data() will be called immediately.
00601 //
00602 //               The terrain will be rendered using SpeedTree
00603 //               callbacks, and trees may be repositioned with a call
00604 //               to snap_to_terrain().
00605 ////////////////////////////////////////////////////////////////////
00606 void SpeedTreeNode::
00607 set_terrain(STTerrain *terrain) {
00608   _terrain = NULL;
00609   _needs_repopulate = true;
00610 
00611   if (terrain == (STTerrain *)NULL) {
00612     return;
00613   }
00614 
00615   if (!terrain->is_valid()) {
00616     // If the terrain was not already loaded, load it immediately.
00617     terrain->load_data();
00618   }
00619 
00620   nassertv(terrain->is_valid());
00621   nassertv(terrain->get_num_splat_layers() == SpeedTree::c_nNumTerrainSplatLayers);
00622   _terrain = terrain;
00623 
00624   _terrain_render.SetShaderLoader(_forest_render.GetShaderLoader());
00625 
00626   SpeedTree::STerrainRenderInfo trender_info;
00627   trender_info.m_strShaderPath = _os_shaders_dir.c_str();
00628 
00629   string os_specific = terrain->get_normal_map().to_os_specific();
00630   trender_info.m_strNormalMap = os_specific.c_str();
00631   os_specific = terrain->get_splat_map().to_os_specific();
00632   trender_info.m_strSplatMap = os_specific.c_str();
00633 
00634   for (int i = 0; i < SpeedTree::c_nNumTerrainSplatLayers; ++i) {
00635     os_specific = terrain->get_splat_layer(i).to_os_specific();
00636     trender_info.m_astrSplatLayers[i] = os_specific.c_str();
00637     trender_info.m_afSplatTileValues[i] = terrain->get_splat_layer_tiling(i);
00638   }
00639 
00640   trender_info.m_fNormalMapBlueScale = 1.0f;
00641   trender_info.m_bShadowsEnabled = false; // what does this do?
00642   trender_info.m_bZPrePass = false;
00643 
00644   _terrain_render.SetRenderInfo(trender_info);
00645 
00646   _terrain_render.SetHeightHints(terrain->get_min_height(), terrain->get_max_height());
00647 
00648   if (speedtree_follow_terrain) {
00649     snap_to_terrain();
00650   }
00651 }
00652 
00653 ////////////////////////////////////////////////////////////////////
00654 //     Function: SpeedTreeNode::snap_to_terrain
00655 //       Access: Published
00656 //  Description: Adjusts all the trees in this node so that their Z
00657 //               position matches the height of the terrain at their
00658 //               X, Y position.
00659 ////////////////////////////////////////////////////////////////////
00660 void SpeedTreeNode::
00661 snap_to_terrain() {
00662   Trees::iterator ti;
00663   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
00664     InstanceList *instance_list = (*ti);
00665 
00666     int num_instances = instance_list->get_num_instances();
00667     if (_terrain != (STTerrain *)NULL) {
00668       for (int i = 0; i < num_instances; ++i) {
00669         STTransform trans = instance_list->get_instance(i);
00670         LPoint3 pos = trans.get_pos();
00671         pos[2] = _terrain->get_height(pos[0], pos[1]);
00672         trans.set_pos(pos);
00673         instance_list->set_instance(i, trans);
00674       }
00675     } else {
00676       for (int i = 0; i < num_instances; ++i) {
00677         STTransform trans = instance_list->get_instance(i);
00678         LPoint3 pos = trans.get_pos();
00679         pos[2] = 0.0f;
00680         trans.set_pos(pos);
00681         instance_list->set_instance(i, trans);
00682       }
00683     }
00684   }
00685 
00686   _needs_repopulate = true;
00687 }
00688 
00689 ////////////////////////////////////////////////////////////////////
00690 //     Function: SpeedTreeNode::reload_config
00691 //       Access: Published
00692 //  Description: Re-reads the current setting of all of the relevant
00693 //               config variables and applies them to this node.  This
00694 //               can be called after changing config settings, to make
00695 //               them apply to this particular node.
00696 ////////////////////////////////////////////////////////////////////
00697 void SpeedTreeNode::
00698 reload_config() {
00699 
00700   _shadow_infos.clear();
00701   int num_shadow_maps = speedtree_cascading_shadow_splits.get_num_words();
00702   if (num_shadow_maps > SpeedTree::c_nMaxNumShadowMaps) {
00703     speedtree_cat.warning()
00704       << "SpeedTree is current compiled to support a maximum of " 
00705       << SpeedTree::c_nMaxNumShadowMaps << " shadow maps.\n";
00706     num_shadow_maps = SpeedTree::c_nMaxNumShadowMaps;
00707   }
00708   _shadow_infos.insert(_shadow_infos.begin(), num_shadow_maps, ShadowInfo());
00709   for (int smi = 0; smi < num_shadow_maps; ++smi) {
00710     _shadow_infos[smi]._shadow_split = speedtree_cascading_shadow_splits[smi];
00711   }
00712 
00713   SpeedTree::SForestRenderInfo render_info = _forest_render.GetRenderInfo();
00714 
00715   render_info.m_nMaxAnisotropy = speedtree_max_anisotropy;
00716   render_info.m_bHorizontalBillboards = speedtree_horizontal_billboards;
00717   render_info.m_fAlphaTestScalar = speedtree_alpha_test_scalar;
00718   render_info.m_bZPrePass = speedtree_z_pre_pass;
00719   render_info.m_nMaxBillboardImagesByBase = speedtree_max_billboard_images_by_base;
00720   render_info.m_fVisibility = speedtree_visibility;
00721   render_info.m_fGlobalLightScalar = speedtree_global_light_scalar;
00722   render_info.m_sLightMaterial.m_vSpecular = SpeedTree::Vec4(speedtree_specular_color[0], speedtree_specular_color[1], speedtree_specular_color[2], 1.0f);
00723   render_info.m_sLightMaterial.m_vEmissive = SpeedTree::Vec4(speedtree_emissive_color[0], speedtree_emissive_color[1], speedtree_emissive_color[2], 1.0f);
00724   render_info.m_bSpecularLighting = speedtree_specular_lighting;
00725   render_info.m_bTransmissionLighting = speedtree_transmission_lighting;
00726   render_info.m_bDetailLayer = speedtree_detail_layer;
00727   render_info.m_bDetailNormalMapping = speedtree_detail_normal_mapping;
00728   render_info.m_bAmbientContrast = speedtree_ambient_contrast;
00729   render_info.m_fTransmissionScalar = speedtree_transmission_scalar;
00730   render_info.m_fFogStartDistance = speedtree_fog_distance[0];
00731   render_info.m_fFogEndDistance = speedtree_fog_distance[1];
00732   render_info.m_vFogColor = SpeedTree::Vec3(speedtree_fog_color[0], speedtree_fog_color[1], speedtree_fog_color[2]);
00733   render_info.m_vSkyColor = SpeedTree::Vec3(speedtree_sky_color[0], speedtree_sky_color[1], speedtree_sky_color[2]);
00734   render_info.m_fSkyFogMin = speedtree_sky_fog[0];
00735   render_info.m_fSkyFogMax = speedtree_sky_fog[1];
00736   render_info.m_vSunColor = SpeedTree::Vec3(speedtree_sun_color[0], speedtree_sun_color[1], speedtree_sun_color[2]);
00737   render_info.m_fSunSize = speedtree_sun_size;
00738   render_info.m_fSunSpreadExponent = speedtree_sun_spread_exponent;
00739   render_info.m_fSunFogBloom = speedtree_sun_fog_bloom;
00740   render_info.m_nNumShadowMaps = num_shadow_maps;
00741   render_info.m_nShadowMapResolution = speedtree_shadow_map_resolution;
00742   render_info.m_bSmoothShadows = speedtree_smooth_shadows;
00743   render_info.m_bShowShadowSplitsOnTerrain = speedtree_show_shadow_splits_on_terrain;
00744   render_info.m_bWindEnabled = speedtree_wind_enabled;
00745   render_info.m_bFrondRippling = speedtree_frond_rippling;
00746 
00747   _forest_render.SetRenderInfo(render_info);
00748 
00749   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
00750   _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, 
00751                           speedtree_max_num_visible_cells);
00752   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
00753 
00754   _needs_repopulate = true;
00755 }
00756 
00757 ////////////////////////////////////////////////////////////////////
00758 //     Function: SpeedTreeNode::set_wind
00759 //       Access: Published
00760 //  Description: Specifies the overall wind strength and direction.
00761 //               Gusts are controlled internally.
00762 ////////////////////////////////////////////////////////////////////
00763 void SpeedTreeNode::
00764 set_wind(double strength, const LVector3 &direction) {
00765   _forest_render.SetGlobalWindStrength(strength);
00766   _forest_render.SetGlobalWindDirection(SpeedTree::Vec3(direction[0], direction[1], direction[2]));
00767 }
00768 
00769 ////////////////////////////////////////////////////////////////////
00770 //     Function: SpeedTreeNode::authorize
00771 //       Access: Published, Static
00772 //  Description: Make this call to initialized the SpeedTree API and
00773 //               verify the license.  If an empty string is passed for
00774 //               the license, the config variable speedtree-license is
00775 //               consulted.  Returns true on success, false on
00776 //               failure.  If this call is not made explicitly, it
00777 //               will be made implicitly the first time a
00778 //               SpeedTreeNode is created.
00779 ////////////////////////////////////////////////////////////////////
00780 bool SpeedTreeNode::
00781 authorize(const string &license) {
00782   if (!_authorized) {
00783     if (!license.empty()) {
00784       SpeedTree::CCore::Authorize(license.c_str());
00785     } else {
00786       if (!speedtree_license.empty()) {
00787         SpeedTree::CCore::Authorize(speedtree_license.c_str());
00788       }
00789     }
00790                                                              
00791     _authorized = SpeedTree::CCore::IsAuthorized();
00792 
00793     SpeedTree::CCore::SetTextureFlip(true);
00794   }
00795   
00796   return _authorized;
00797 }
00798 
00799 ////////////////////////////////////////////////////////////////////
00800 //     Function: SpeedTreeNode::Copy Constructor
00801 //       Access: Protected
00802 //  Description:
00803 ////////////////////////////////////////////////////////////////////
00804 SpeedTreeNode::
00805 SpeedTreeNode(const SpeedTreeNode &copy) :
00806   PandaNode(copy),
00807   _os_shaders_dir(copy._os_shaders_dir),
00808   _shadow_infos(copy._shadow_infos),
00809 #ifdef ST_DELETE_FOREST_HACK
00810   // Early versions of SpeedTree don't destruct unused CForestRender
00811   // objects correctly.  To avoid crashes, we have to leak these
00812   // things.
00813   _forest_render(*(new SpeedTree::CForestRender)),
00814 #endif
00815   _time_delta(copy._time_delta)
00816 {
00817   init_node();
00818 
00819   _forest_render.SetRenderInfo(copy._forest_render.GetRenderInfo());
00820   _terrain_render.SetRenderInfo(copy._terrain_render.GetRenderInfo());
00821 
00822   // No way to copy these parameters, so we just re-assign them.
00823   _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
00824   _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, 
00825                           speedtree_max_num_visible_cells);
00826   _visible_terrain.Reserve(speedtree_max_num_visible_cells);
00827 
00828   Trees::const_iterator ti;
00829   for (ti = copy._trees.begin(); ti != copy._trees.end(); ++ti) {
00830     InstanceList *instance_list = (*ti);
00831     const STTree *tree = instance_list->get_tree();
00832     if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->get_tree())) {
00833       speedtree_cat.warning()
00834         << "Failed to register tree " << tree->get_fullpath() << "\n";
00835       write_error(speedtree_cat.warning());
00836     }
00837 
00838     _trees.push_back(new InstanceList(*instance_list));
00839   }
00840   _trees.sort();
00841 
00842   set_terrain(copy._terrain);
00843 
00844   _needs_repopulate = true;
00845   mark_internal_bounds_stale();
00846 }
00847 
00848 ////////////////////////////////////////////////////////////////////
00849 //     Function: SpeedTreeNode::Destructor
00850 //       Access: Published, Virtual
00851 //  Description: 
00852 ////////////////////////////////////////////////////////////////////
00853 SpeedTreeNode::
00854 ~SpeedTreeNode() {
00855   remove_all_trees();
00856   // Help reduce memory waste from ST_DELETE_FOREST_HACK.
00857   _forest_render.ClearInstances();
00858 }
00859 
00860 ////////////////////////////////////////////////////////////////////
00861 //     Function: SpeedTreeNode::make_copy
00862 //       Access: Public, Virtual
00863 //  Description: Returns a newly-allocated Node that is a shallow copy
00864 //               of this one.  It will be a different Node pointer,
00865 //               but its internal data may or may not be shared with
00866 //               that of the original Node.
00867 ////////////////////////////////////////////////////////////////////
00868 PandaNode *SpeedTreeNode::
00869 make_copy() const {
00870   return new SpeedTreeNode(*this);
00871 }
00872 
00873 ////////////////////////////////////////////////////////////////////
00874 //     Function: SpeedTreeNode::combine_with
00875 //       Access: Public, Virtual
00876 //  Description: Collapses this node with the other node, if possible,
00877 //               and returns a pointer to the combined node, or NULL
00878 //               if the two nodes cannot safely be combined.
00879 //
00880 //               The return value may be this, other, or a new node
00881 //               altogether.
00882 //
00883 //               This function is called from GraphReducer::flatten(),
00884 //               and need not deal with children; its job is just to
00885 //               decide whether to collapse the two nodes and what the
00886 //               collapsed node should look like.
00887 ////////////////////////////////////////////////////////////////////
00888 PandaNode *SpeedTreeNode::
00889 combine_with(PandaNode *other) {
00890   if (is_exact_type(get_class_type()) &&
00891       other->is_exact_type(get_class_type())) {
00892     // Two SpeedTreeNodes can combine by moving trees from one to the
00893     // other, similar to the way GeomNodes combine.
00894     SpeedTreeNode *gother = DCAST(SpeedTreeNode, other);
00895 
00896     // But, not if they both have a terrain set.
00897     if (has_terrain() && gother->has_terrain()) {
00898       return NULL;
00899 
00900     } else if (gother->has_terrain()) {
00901       set_terrain(gother->get_terrain());
00902     }
00903 
00904     add_instances_from(gother);
00905     return this;
00906   }
00907 
00908   return PandaNode::combine_with(other);
00909 }
00910 
00911 ////////////////////////////////////////////////////////////////////
00912 //     Function: SpeedTreeNode::apply_attribs_to_vertices
00913 //       Access: Public, Virtual
00914 //  Description: Applies whatever attributes are specified in the
00915 //               AccumulatedAttribs object (and by the attrib_types
00916 //               bitmask) to the vertices on this node, if
00917 //               appropriate.  If this node uses geom arrays like a
00918 //               GeomNode, the supplied GeomTransformer may be used to
00919 //               unify shared arrays across multiple different nodes.
00920 //
00921 //               This is a generalization of xform().
00922 ////////////////////////////////////////////////////////////////////
00923 void SpeedTreeNode::
00924 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00925                           GeomTransformer &transformer) {
00926   if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00927     STTransform xform = attribs._transform;
00928     Trees::iterator ti;
00929     for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
00930       InstanceList *instance_list = (*ti);
00931       STInstances &instances = instance_list->_instances;
00932       STInstances::iterator sti;
00933       for (sti = instances.begin(); sti != instances.end(); ++sti) {
00934         STTransform orig_transform = *sti;
00935         (*sti) = orig_transform * xform;
00936       }
00937     }
00938   }
00939   mark_internal_bounds_stale();
00940 }
00941 
00942 ////////////////////////////////////////////////////////////////////
00943 //     Function: SpeedTreeNode::cull_callback
00944 //       Access: Public, Virtual
00945 //  Description: This function will be called during the cull
00946 //               traversal to perform any additional operations that
00947 //               should be performed at cull time.  This may include
00948 //               additional manipulation of render state or additional
00949 //               visible/invisible decisions, or any other arbitrary
00950 //               operation.
00951 //
00952 //               Note that this function will *not* be called unless
00953 //               set_cull_callback() is called in the constructor of
00954 //               the derived class.  It is necessary to call
00955 //               set_cull_callback() to indicated that we require
00956 //               cull_callback() to be called.
00957 //
00958 //               By the time this function is called, the node has
00959 //               already passed the bounding-volume test for the
00960 //               viewing frustum, and the node's transform and state
00961 //               have already been applied to the indicated
00962 //               CullTraverserData object.
00963 //
00964 //               The return value is true if this node should be
00965 //               visible, or false if it should be culled.
00966 ////////////////////////////////////////////////////////////////////
00967 bool SpeedTreeNode::
00968 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00969   if (!_is_valid) {
00970     return false;
00971   }
00972   PStatTimer timer(_cull_speedtree_pcollector);
00973 
00974   GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, trav->get_gsg());
00975   nassertr(gsg != (GraphicsStateGuardian *)NULL, true);
00976   if (!validate_api(gsg)) {
00977     return false;
00978   }
00979 
00980   ClockObject *clock = ClockObject::get_global_clock();
00981   _forest_render.SetGlobalTime(clock->get_frame_time() + _time_delta + _global_time_delta);
00982   _forest_render.AdvanceGlobalWind();
00983   
00984   // Compute the modelview and camera transforms, to pass to the
00985   // SpeedTree CView structure.
00986   CPT(TransformState) orig_modelview = data.get_modelview_transform(trav);
00987   CPT(TransformState) modelview = gsg->get_cs_transform()->compose(orig_modelview);
00988   CPT(TransformState) camera_transform = modelview->invert_compose(TransformState::make_identity());
00989   LMatrix4f modelview_mat = LCAST(float, modelview->get_mat());
00990   const LPoint3 &camera_pos = camera_transform->get_pos();
00991   const Lens *lens = trav->get_scene()->get_lens();
00992   
00993   LMatrix4f projection_mat =
00994     LCAST(float, LMatrix4::convert_mat(gsg->get_internal_coordinate_system(), lens->get_coordinate_system()) *
00995           lens->get_projection_mat());
00996   
00997   _view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]),
00998             SpeedTree::Mat4x4(projection_mat.get_data()),
00999             SpeedTree::Mat4x4(modelview_mat.get_data()),
01000             lens->get_near(), lens->get_far());
01001 
01002   // Convert the render state to SpeedTree's input.
01003   const RenderState *state = data._state;
01004 
01005   // Check texture state.  If all textures are disabled, then we ask
01006   // SpeedTree to disable textures.
01007   bool show_textures = true;
01008   const TextureAttrib *ta = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()));
01009   if (ta != (TextureAttrib *)NULL) {
01010     show_textures = !ta->has_all_off();
01011   }
01012   _forest_render.EnableTexturing(show_textures);
01013   _terrain_render.EnableTexturing(show_textures);
01014 
01015   // Check lighting state.  SpeedTree only supports a single
01016   // directional light; we look for a directional light in the
01017   // lighting state and pass its direction and color to SpeedTree.  We
01018   // also accumulate the ambient light colors.
01019   LColor ambient_color(0.0f, 0.0f, 0.0f, 0.0f);
01020   DirectionalLight *dlight = NULL;
01021   NodePath dlight_np;
01022   LColor diffuse_color;
01023 
01024   int diffuse_priority = 0;
01025   const LightAttrib *la = DCAST(LightAttrib, state->get_attrib(LightAttrib::get_class_slot()));
01026   if (la != (LightAttrib *)NULL) {
01027     for (int i = 0; i < la->get_num_on_lights(); ++i) {
01028       NodePath light = la->get_on_light(i);
01029       if (!light.is_empty() && light.node()->is_of_type(DirectionalLight::get_class_type())) {
01030         // A directional light.
01031         DirectionalLight *light_obj = DCAST(DirectionalLight, light.node());
01032         if (dlight == NULL || light_obj->get_priority() > dlight->get_priority()) {
01033           // Here's the most important directional light.
01034           dlight = light_obj;
01035           dlight_np = light;
01036         }
01037       } else if (!light.is_empty() && light.node()->is_of_type(AmbientLight::get_class_type())) {
01038         // An ambient light.  We keep the color only.
01039         AmbientLight *light_obj = DCAST(AmbientLight, light.node());
01040         ambient_color += light_obj->get_color();
01041       }
01042     }
01043   }
01044     
01045   if (dlight != (DirectionalLight *)NULL) {
01046     CPT(TransformState) transform = dlight_np.get_transform(trav->get_scene()->get_scene_root().get_parent());
01047     LVector3 dir = dlight->get_direction() * transform->get_mat();
01048     dir.normalize();
01049     _light_dir = SpeedTree::Vec3(dir[0], dir[1], dir[2]);
01050     diffuse_color = dlight->get_color();
01051 
01052   } else {
01053     // No light.  But there's no way to turn off lighting in
01054     // SpeedTree.  In lieu of this, we just shine a light from
01055     // above.
01056     _light_dir = SpeedTree::Vec3(0.0, 0.0, -1.0);
01057 
01058     // Also, we set ambient and diffuse colors to the same full-white
01059     // value.
01060     ambient_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01061     diffuse_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01062   }
01063 
01064   SpeedTree::SForestRenderInfo render_info = _forest_render.GetRenderInfo();
01065   render_info.m_sLightMaterial.m_vAmbient = SpeedTree::Vec4(ambient_color[0], ambient_color[1], ambient_color[2], 1.0f);
01066   render_info.m_sLightMaterial.m_vDiffuse = SpeedTree::Vec4(diffuse_color[0], diffuse_color[1], diffuse_color[2], 1.0f);
01067   _forest_render.SetRenderInfo(render_info);
01068 
01069   _forest_render.SetLightDir(_light_dir);
01070 
01071   SpeedTree::st_float32 updated_splits[SpeedTree::c_nMaxNumShadowMaps];
01072   memset(updated_splits, 0, sizeof(updated_splits));
01073   for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
01074     updated_splits[smi] = _shadow_infos[smi]._shadow_split;
01075   };
01076 
01077   _forest_render.SetCascadedShadowMapDistances(updated_splits, lens->get_far());
01078   _forest_render.SetShadowFadePercentage(speedtree_shadow_fade);
01079 
01080   if (!_needs_repopulate) {
01081     // Don't bother culling now unless we're correctly fully
01082     // populated.  (Culling won't be accurate unless the forest has
01083     // been populated, but we have to be in the draw traversal to
01084     // populate.)
01085     cull_forest();
01086   }
01087 
01088   // Recurse onto the node's children.
01089   return true;
01090 }
01091 
01092 ////////////////////////////////////////////////////////////////////
01093 //     Function: SpeedTreeNode::is_renderable
01094 //       Access: Public, Virtual
01095 //  Description: Returns true if there is some value to visiting this
01096 //               particular node during the cull traversal for any
01097 //               camera, false otherwise.  This will be used to
01098 //               optimize the result of get_net_draw_show_mask(), so
01099 //               that any subtrees that contain only nodes for which
01100 //               is_renderable() is false need not be visited.
01101 ////////////////////////////////////////////////////////////////////
01102 bool SpeedTreeNode::
01103 is_renderable() const {
01104   return true;
01105 }
01106 
01107 ////////////////////////////////////////////////////////////////////
01108 //     Function: SpeedTreeNode::add_for_draw
01109 //       Access: Public, Virtual
01110 //  Description: Adds the node's contents to the CullResult we are
01111 //               building up during the cull traversal, so that it
01112 //               will be drawn at render time.  For most nodes other
01113 //               than GeomNodes, this is a do-nothing operation.
01114 ////////////////////////////////////////////////////////////////////
01115 void SpeedTreeNode::
01116 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
01117   if (_is_valid) {
01118     // We create a CullableObject that has an explicit draw_callback
01119     // into this node, so that we can make the appropriate calls into
01120     // SpeedTree to render the forest during the actual draw.
01121     CullableObject *object = 
01122       new CullableObject(NULL, data._state,
01123                          TransformState::make_identity(),
01124                          TransformState::make_identity(),
01125                          trav->get_gsg());
01126     object->set_draw_callback(new DrawCallback(this));
01127     trav->get_cull_handler()->record_object(object, trav);
01128   }
01129 }
01130 
01131 ////////////////////////////////////////////////////////////////////
01132 //     Function: SpeedTreeNode::prepare_scene
01133 //       Access: Published
01134 //  Description: Walks through the scene graph beginning at this node,
01135 //               and does whatever initialization is required to
01136 //               render the scene properly with the indicated GSG.  It
01137 //               is not strictly necessary to call this, since the GSG
01138 //               will initialize itself when the scene is rendered,
01139 //               but this may take some of the overhead away from that
01140 //               process.
01141 //
01142 //               In particular, this will ensure that textures within
01143 //               the scene are loaded in texture memory, and display
01144 //               lists are built up from static geometry.
01145 ////////////////////////////////////////////////////////////////////
01146 void SpeedTreeNode::
01147 prepare_scene(GraphicsStateGuardianBase *gsgbase, const RenderState *) {
01148   GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase);
01149   if (validate_api(gsg)) {
01150     setup_for_render(gsg);
01151   }
01152 }
01153 
01154 ////////////////////////////////////////////////////////////////////
01155 //     Function: SpeedTreeNode::compute_internal_bounds
01156 //       Access: Protected, Virtual
01157 //  Description: Returns a newly-allocated BoundingVolume that
01158 //               represents the internal contents of the node.  Should
01159 //               be overridden by PandaNode classes that contain
01160 //               something internally.
01161 ////////////////////////////////////////////////////////////////////
01162 void SpeedTreeNode::
01163 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
01164                         int &internal_vertices,
01165                         int pipeline_stage,
01166                         Thread *current_thread) const {
01167   internal_vertices = 0;
01168 
01169   SpeedTree::CExtents extents;
01170   Trees::const_iterator ti;
01171   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01172     InstanceList *instance_list = (*ti);
01173     const STTree *tree = instance_list->get_tree();
01174 
01175     const STInstances &st_instances = instance_list->_instances;
01176     STInstances::const_iterator ii;
01177     for (ii = st_instances.begin(); ii != st_instances.end(); ++ii) {
01178       SpeedTree::CExtents tree_extents = tree->get_tree()->GetExtents();
01179       tree_extents.Rotate((*ii).GetRotationAngle());
01180       tree_extents.Scale((*ii).GetScale());
01181       tree_extents.Translate((*ii).GetPos());
01182       extents.ExpandAround(tree_extents);
01183     }
01184   }
01185 
01186   const SpeedTree::Vec3 &emin = extents.Min();
01187   const SpeedTree::Vec3 &emax = extents.Max();
01188   internal_bounds = new BoundingBox(LPoint3(emin[0], emin[1], emin[2]),
01189                                     LPoint3(emax[0], emax[1], emax[2]));
01190 }
01191 
01192 ////////////////////////////////////////////////////////////////////
01193 //     Function: SpeedTreeNode::output
01194 //       Access: Public, Virtual
01195 //  Description: Writes a brief description of the node to the
01196 //               indicated output stream.  This is invoked by the <<
01197 //               operator.  It may be overridden in derived classes to
01198 //               include some information relevant to the class.
01199 ////////////////////////////////////////////////////////////////////
01200 void SpeedTreeNode::
01201 output(ostream &out) const {
01202   PandaNode::output(out);
01203   out
01204     << " (" << get_num_trees() << " unique trees with "
01205     << count_total_instances() << " total instances)";
01206 }
01207 
01208 ////////////////////////////////////////////////////////////////////
01209 //     Function: SpeedTreeNode::write
01210 //       Access: Public, Virtual
01211 //  Description: 
01212 ////////////////////////////////////////////////////////////////////
01213 void SpeedTreeNode::
01214 write(ostream &out, int indent_level) const {
01215   PandaNode::write(out, indent_level);
01216 
01217   // This makes NodePath.ls() too confusing.
01218   /*
01219   Trees::const_iterator ti;
01220   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01221     InstanceList *instance_list = (*ti);
01222     indent(out, indent_level + 2) 
01223       << *instance_list << "\n";
01224   }
01225   */
01226 }
01227 
01228 
01229 ////////////////////////////////////////////////////////////////////
01230 //     Function: SpeedTreeNode::write_error
01231 //       Access: Public, Static
01232 //  Description: Writes the current SpeedTree error message to the
01233 //               indicated stream.
01234 ////////////////////////////////////////////////////////////////////
01235 void SpeedTreeNode::
01236 write_error(ostream &out) {
01237   const char *error = SpeedTree::CCore::GetError();
01238   if (error != (const char *)NULL) {
01239     out << error;
01240   }
01241   out << "\n";
01242 }
01243 
01244 ////////////////////////////////////////////////////////////////////
01245 //     Function: SpeedTreeNode::set_transparent_texture_mode
01246 //       Access: Protected
01247 //  Description: Uses SpeedTree::CRenderState to set the indicated
01248 //               transparency mode.
01249 ////////////////////////////////////////////////////////////////////
01250 void SpeedTreeNode::
01251 set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode eMode) const {
01252   // turn all modes off (no telling what render state the client
01253   // application might be in before this call)
01254   SpeedTree::CRenderState::SetBlending(false);
01255   SpeedTree::CRenderState::SetAlphaTesting(false);
01256   SpeedTree::CRenderState::SetAlphaToCoverage(false);
01257   
01258   switch (eMode) {
01259   case SpeedTree::TRANS_TEXTURE_ALPHA_TESTING:
01260     SpeedTree::CRenderState::SetAlphaTesting(true);
01261     break;
01262   case SpeedTree::TRANS_TEXTURE_ALPHA_TO_COVERAGE:
01263     SpeedTree::CRenderState::SetAlphaToCoverage(true);
01264     break;
01265   case SpeedTree::TRANS_TEXTURE_BLENDING:
01266     SpeedTree::CRenderState::SetBlending(true);
01267     break;
01268   default:
01269     // intentionally do nothing (TRANS_TEXTURE_NOTHING)
01270     break;
01271   }
01272 }
01273 
01274 ////////////////////////////////////////////////////////////////////
01275 //     Function: SpeedTreeNode::init_node
01276 //       Access: Private
01277 //  Description: Called from the constructor to initialize some
01278 //               internal values.
01279 ////////////////////////////////////////////////////////////////////
01280 void SpeedTreeNode::
01281 init_node() {
01282   PandaNode::set_cull_callback();
01283 
01284   _is_valid = false;
01285   _needs_repopulate = false;
01286 
01287   // Ensure we have a license.
01288   if (!authorize()) {
01289     speedtree_cat.warning()
01290       << "SpeedTree license not available.\n";
01291     return;
01292   }
01293 
01294   _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS, 
01295                          speedtree_max_num_visible_cells);
01296 
01297   _forest_render.SetCullCellSize(speedtree_cull_cell_size);
01298 
01299   // Doesn't appear to be necessary to call this explicitly.
01300   //_forest_render.EnableWind(true);
01301 
01302   _is_valid = true;
01303 }
01304 
01305 ////////////////////////////////////////////////////////////////////
01306 //     Function: SpeedTreeNode::r_add_instances
01307 //       Access: Private
01308 //  Description: The recursive implementation of add_instances().
01309 ////////////////////////////////////////////////////////////////////
01310 void SpeedTreeNode::
01311 r_add_instances(PandaNode *node, const TransformState *transform,
01312                 Thread *current_thread) {
01313   if (node->is_of_type(SpeedTreeNode::get_class_type()) && node != this) {
01314     SpeedTreeNode *other = DCAST(SpeedTreeNode, node);
01315     add_instances_from(other, transform);
01316   }
01317 
01318   Children children = node->get_children(current_thread);
01319   for (int i = 0; i < children.get_num_children(); i++) {
01320     PandaNode *child = children.get_child(i);
01321     CPT(TransformState) child_transform = transform->compose(child->get_transform());
01322     r_add_instances(child, child_transform, current_thread);
01323   }
01324 }
01325 
01326 
01327 ////////////////////////////////////////////////////////////////////
01328 //     Function: SpeedTreeNode::repopulate
01329 //       Access: Private
01330 //  Description: Rebuilds the internal structures as necessary for
01331 //               rendering.
01332 ////////////////////////////////////////////////////////////////////
01333 void SpeedTreeNode::
01334 repopulate() {
01335   _forest_render.ClearInstances();
01336 
01337   Trees::iterator ti;
01338   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01339     InstanceList *instance_list = (*ti);
01340     const STTree *tree = instance_list->get_tree();
01341     const STInstances &instances = instance_list->_instances;
01342     if (instances.empty()) {
01343       // There are no instances, so don't bother.  (This shouldn't
01344       // happen often, because we remove trees from the SpeedTreeNode
01345       // when their instance list goes empty, though it's possible if
01346       // the user has explicitly removed all of the instances.)
01347       continue;
01348     }
01349 
01350     if (!_forest_render.AddInstances(tree->get_tree(), &instances[0], instances.size())) {
01351       speedtree_cat.warning()
01352         << "Failed to add " << instances.size()
01353         << " instances for " << *tree << "\n";
01354       write_error(speedtree_cat.warning());
01355     }
01356   }
01357   
01358   _forest_render.GetPopulationStats(_population_stats);
01359   print_forest_stats(_population_stats);
01360 
01361   // setup billboard caps based on instances-per-cell stats
01362   int max_instances_by_cell = 1;
01363   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01364     InstanceList *instance_list = (*ti);
01365     const STTree *tree = instance_list->get_tree();
01366     const STInstances &instances = instance_list->_instances;
01367     if (instances.empty()) {
01368       continue;
01369     }
01370 
01371     int max_instances = 1;
01372     SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
01373     si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree());
01374     if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) {
01375       max_instances = max(max_instances, (int)si->second);
01376     }
01377 
01378     max_instances_by_cell = max(max_instances_by_cell, max_instances);
01379   }
01380 
01381   _visible_trees.Reserve(_forest_render.GetBaseTrees(),
01382                          _forest_render.GetBaseTrees().size(), 
01383                          speedtree_max_num_visible_cells, 
01384                          max_instances_by_cell,
01385                          speedtree_horizontal_billboards);
01386 }
01387 
01388 ////////////////////////////////////////////////////////////////////
01389 //     Function: SpeedTreeNode::update_terrain_cells
01390 //       Access: Private
01391 //  Description: Called once a frame to load vertex data for
01392 //               newly-visible terrain cells.
01393 ////////////////////////////////////////////////////////////////////
01394 void SpeedTreeNode::
01395 update_terrain_cells() {
01396   nassertv(has_terrain());
01397 
01398   SpeedTree::TTerrainCellArray &cells = _visible_terrain.m_aCellsToUpdate;
01399 
01400   int num_tile_res = _terrain_render.GetMaxTileRes();
01401   PN_stdfloat cell_size = _terrain_render.GetCellSize();
01402 
01403   // A temporary vertex data object for populating terrain.
01404   PT(GeomVertexData) vertex_data = 
01405     new GeomVertexData("terrain", _terrain->get_vertex_format(), 
01406                        GeomEnums::UH_static);
01407   int num_vertices = num_tile_res * num_tile_res;
01408   vertex_data->set_num_rows(num_vertices);
01409   size_t num_bytes = vertex_data->get_array(0)->get_data_size_bytes();
01410 
01411   int num_cells = (int)cells.size();
01412   for (int ci = 0; ci < num_cells; ++ci) {
01413     SpeedTree::CTerrainCell *cell = cells[ci];
01414     nassertv(cell != NULL && cell->GetVbo() != NULL);
01415     int cell_yi = cell->Row();
01416     int cell_xi = cell->Col();
01417     //cerr << "populating cell " << cell_xi << " " << cell_yi << "\n";
01418 
01419     _terrain->fill_vertices(vertex_data,
01420                             cell_xi * cell_size, cell_yi * cell_size,
01421                             cell_size, num_tile_res);
01422 
01423     const GeomVertexArrayData *array_data = vertex_data->get_array(0);
01424     CPT(GeomVertexArrayDataHandle) handle = array_data->get_handle();
01425     const unsigned char *data_pointer = handle->get_read_pointer(true);
01426     SpeedTree::CGeometryBuffer *vbo = (SpeedTree::CGeometryBuffer *)cell->GetVbo();
01427 
01428     nassertv(vbo->NumVertices() == num_tile_res * num_tile_res);
01429     nassertv(vbo->NumVertices() * vbo->VertexSize() == handle->get_data_size_bytes());
01430     vbo->OverwriteVertices(data_pointer, num_vertices, 0);
01431   }    
01432 }
01433 
01434 ////////////////////////////////////////////////////////////////////
01435 //     Function: SpeedTreeNode::validate_api
01436 //       Access: Private
01437 //  Description: Returns true if the indicated GSG shares the
01438 //               appropriate API for this SpeedTreeNode, false
01439 //               otherwise.
01440 ////////////////////////////////////////////////////////////////////
01441 bool SpeedTreeNode::
01442 validate_api(GraphicsStateGuardian *gsg) {
01443   GraphicsPipe *pipe = gsg->get_pipe();
01444   nassertr(pipe != (GraphicsPipe *)NULL, true);
01445 
01446 #if defined(SPEEDTREE_OPENGL)
01447   static const string compiled_api = "OpenGL";
01448 #elif defined(SPEEDTREE_DIRECTX9)
01449   static const string compiled_api = "DirectX9";
01450 #else
01451   #error Unexpected graphics API.
01452 #endif
01453 
01454   if (pipe->get_interface_name() != compiled_api) {
01455     speedtree_cat.error()
01456       << "SpeedTree is compiled for " << compiled_api
01457       << ", cannot render with " << pipe->get_interface_name()
01458       << "\n";
01459     _is_valid = false;
01460     return false;
01461   }
01462 
01463   return true;
01464 }
01465 
01466 ////////////////////////////////////////////////////////////////////
01467 //     Function: SpeedTreeNode::draw_callback
01468 //       Access: Private
01469 //  Description: Called when the node is visited during the draw
01470 //               traversal, by virtue of our DrawCallback construct.
01471 //               This makes the calls into SpeedTree to perform the
01472 //               actual rendering.
01473 ////////////////////////////////////////////////////////////////////
01474 void SpeedTreeNode::
01475 draw_callback(CallbackData *data) {
01476   PStatTimer timer(_draw_speedtree_pcollector);
01477   GeomDrawCallbackData *geom_cbdata;
01478   DCAST_INTO_V(geom_cbdata, data);
01479 
01480   GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, geom_cbdata->get_gsg());
01481 
01482   setup_for_render(gsg);
01483 
01484   // Set some initial state requirements.
01485   SpeedTree::CRenderState::SetAlphaFunction(SpeedTree::ALPHAFUNC_GREATER, 0.0f);
01486 
01487   // start the forest render
01488   _forest_render.StartRender();
01489 
01490   if (_forest_render.ShadowsAreEnabled()) {
01491     // Update the shadow maps.  TODO: consider updating these only
01492     // every once in a while, instead of every frame, as a simple
01493     // optimization.
01494     PStatTimer timer(_draw_speedtree_shadows_pcollector);
01495     render_forest_into_shadow_maps();
01496     _forest_render.ClearBoundTextures( );
01497   }
01498 
01499   if (!_forest_render.UploadViewShaderParameters(_view)) {
01500     speedtree_cat.warning()
01501       << "Couldn't set view parameters\n";
01502     write_error(speedtree_cat.warning());
01503   }
01504   
01505   if (has_terrain()) {
01506     PStatTimer timer1(_draw_speedtree_terrain_pcollector);
01507     // Is this needed for terrain?
01508     _terrain_render.UploadShaderConstants
01509       (&_forest_render, _light_dir, 
01510        _forest_render.GetRenderInfo().m_sLightMaterial);
01511 
01512     // set terrain render states
01513     set_transparent_texture_mode(SpeedTree::TRANS_TEXTURE_NOTHING);
01514 
01515     // render actual terrain
01516     bool terrain = _terrain_render.Render
01517       (&_forest_render, _visible_terrain, SpeedTree::RENDER_PASS_STANDARD,
01518        _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial, 
01519        &_forest_render.GetRenderStats());
01520 
01521     if (!terrain) {
01522       speedtree_cat.warning()
01523         << "Failed to render terrain\n";
01524       write_error(speedtree_cat.warning());
01525       
01526       // Clear the terrain so we don't keep spamming error messages.
01527       _terrain = NULL;
01528     }
01529   }
01530 
01531   {
01532     // Now draw the actual trees.
01533     PStatTimer timer1(_draw_speedtree_trees_pcollector);
01534 
01535     //  SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_ALPHA_TESTING;
01536     SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_ALPHA_TO_COVERAGE;
01537     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_BLENDING;
01538     //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_NOTHING;
01539     set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode(mode));
01540     
01541     bool branches = _forest_render.RenderBranches(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
01542     bool fronds = _forest_render.RenderFronds(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
01543     bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
01544     bool leaf_cards = _forest_render.RenderLeafCards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
01545     bool billboards = _forest_render.RenderBillboards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
01546 
01547     // Sometimes billboards comes back false, particularly if wind is
01548     // disabled; but the billboards appear to have been rendered
01549     // successfully.  Weird.  Just removing this test from the
01550     // condition.
01551     
01552     if (!branches || !fronds || !leaf_meshes || !leaf_cards /* || !billboards */) {
01553       speedtree_cat.warning()
01554         << "Failed to render forest completely: "
01555         << branches << " " << fronds << " " << leaf_meshes << " " << leaf_cards << " " << billboards << "\n";
01556       write_error(speedtree_cat.warning());
01557     }
01558   }
01559 
01560   _forest_render.EndRender();
01561 
01562   if (_forest_render.ShadowsAreEnabled() && speedtree_show_overlays) {
01563     _forest_render.RenderOverlays();
01564   }
01565 
01566   // SpeedTree leaves the graphics state indeterminate.  Make sure
01567   // Panda doesn't rely on anything in the state.
01568   geom_cbdata->set_lost_state(true);
01569 }
01570 
01571 
01572 ////////////////////////////////////////////////////////////////////
01573 //     Function: SpeedTreeNode::render_forest_into_shadow_maps
01574 //       Access: Private
01575 //  Description: Renders the forest from the point of view of the
01576 //               light, to fill up the shadow map(s).
01577 ////////////////////////////////////////////////////////////////////
01578 void SpeedTreeNode::
01579 render_forest_into_shadow_maps() {
01580   bool success = true;
01581 
01582   // d3d10 allows A2C on render targets, so make sure to turn it off
01583   SpeedTree::CRenderState::SetMultisampling(false);
01584   SpeedTree::CRenderState::SetAlphaToCoverage(false);
01585 
01586 #if defined(SPEEDTREE_OPENGL)
01587   // Ensure the viewport is not constrained.  SpeedTree doesn't expect
01588   // that.
01589   glDisable(GL_SCISSOR_TEST);
01590 #endif
01591 
01592   for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
01593     const SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
01594     const SpeedTree::SForestCullResults &light_cull = _shadow_infos[smi]._light_cull;
01595     
01596     if (_forest_render.BeginShadowMap(smi, light_view)) {
01597       success &= _forest_render.UploadViewShaderParameters(light_view);
01598       
01599       // branch geometry can be rendered with backfacing triangle
01600       // removed, so a closer tolerance can be used
01601       SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f);
01602       
01603       success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW);
01604       
01605       // the remaining geometry types cannot be backface culled, so we
01606       // need a much more aggressive offset
01607       SpeedTree::CRenderState::SetPolygonOffset(10.0f, 1.0f);
01608       
01609       success &= _forest_render.RenderFronds(light_cull, SpeedTree::RENDER_PASS_SHADOW);
01610       success &= _forest_render.RenderLeafMeshes(light_cull, SpeedTree::RENDER_PASS_SHADOW);
01611       success &= _forest_render.RenderLeafCards(light_cull, SpeedTree::RENDER_PASS_SHADOW, light_view);
01612       
01613       // We don't bother to render billboard geometry into the shadow
01614       // map(s).
01615       
01616       success &= _forest_render.EndShadowMap(smi);
01617     }
01618   }
01619 
01620   //  SpeedTree::CRenderState::SetMultisampling(m_sUserSettings.m_nSampleCount > 0);
01621 
01622   if (!success) {
01623     speedtree_cat.warning()
01624       << "Failed to render shadow maps\n";
01625     write_error(speedtree_cat.warning());
01626   }
01627 }
01628 
01629 ////////////////////////////////////////////////////////////////////
01630 //     Function: SpeedTreeNode::setup_for_render
01631 //       Access: Private
01632 //  Description: Does whatever calls are necessary to set up the
01633 //               forest for rendering--create vbuffers, load shaders,
01634 //               and whatnot.  Primarily, this is the calls to
01635 //               InitTreeGraphics and the like.
01636 ////////////////////////////////////////////////////////////////////
01637 void SpeedTreeNode::
01638 setup_for_render(GraphicsStateGuardian *gsg) {
01639   if (!_done_first_init) {
01640     // This is the first time we have entered the draw callback since
01641     // creating any SpeedTreeNode.  Now we have an opportunity to do
01642     // any initial setup that requires a graphics context.
01643     
01644 #ifdef SPEEDTREE_OPENGL
01645     // For OpenGL, we have to ensure GLEW has been initialized.
01646     // (SpeedTree uses it, though Panda doesn't.)
01647     GLenum err = glewInit();
01648     if (err != GLEW_OK) {
01649       speedtree_cat.error()
01650         << "GLEW initialization failed: %s\n", glewGetErrorString(err);
01651       // Can't proceed without GLEW.
01652       _is_valid = false;
01653       return;
01654     }
01655 
01656     // Insist that OpenGL 2.0 is available as the SpeedTree renderer
01657     // requires it.
01658     if (!GLEW_VERSION_2_0) {
01659       speedtree_cat.error()
01660         << "The SpeedTree OpenGL implementation requires OpenGL 2.0 or better to run; this system has version " << glGetString(GL_VERSION) << "\n";
01661       _is_valid = false;
01662       return;
01663     }
01664 #endif  // SPEEDTREE_OPENGL
01665 
01666     _done_first_init = true;
01667   }
01668 
01669 #ifdef SPEEDTREE_DIRECTX9
01670   // In DirectX, we have to tell SpeedTree our device pointer.
01671   DXGraphicsStateGuardian9 *dxgsg = DCAST(DXGraphicsStateGuardian9, gsg);
01672   SpeedTree::DX9::SetDevice(dxgsg->_screen->_d3d_device);
01673 #endif  // SPEEDTREE_DIRECTX9
01674 
01675   if (_needs_repopulate) {
01676     repopulate();
01677 
01678     // Now init per-tree graphics
01679     Trees::const_iterator ti;
01680     for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01681       InstanceList *instance_list = (*ti);
01682       const STTree *tree = instance_list->get_tree();
01683       const STInstances &instances = instance_list->_instances;
01684       if (instances.empty()) {
01685         continue;
01686       }
01687       
01688       int max_instances = 2;
01689       SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
01690       si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree());
01691       if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) {
01692         max_instances = max(max_instances, (int)si->second);
01693       }
01694 
01695       // Get the speedtree-textures-dir to pass for initialization.
01696       string os_textures_dir;
01697       if (!speedtree_textures_dir.empty()) {
01698         os_textures_dir = speedtree_textures_dir.get_value().to_os_specific();
01699         // Ensure the path ends with a terminal slash; SpeedTree requires this.
01700 #if defined(WIN32) || defined(WIN64)
01701         if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '\\') {
01702           os_textures_dir += "\\";
01703         }
01704 #else
01705         if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '/') {
01706           os_textures_dir += "/";
01707         }
01708 #endif
01709       }
01710 
01711       if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(), 
01712                                            max_instances, speedtree_horizontal_billboards,
01713                                            os_textures_dir.c_str())) {
01714         if (speedtree_cat.is_debug()) {
01715           speedtree_cat.debug()
01716             << "Failed to init tree graphics for " << *tree << "\n";
01717           write_error(speedtree_cat.debug());
01718         }
01719       }
01720     }
01721 
01722     // Init overall graphics
01723     if (!_forest_render.InitGraphics(false)) {
01724       speedtree_cat.warning()
01725         << "Failed to init graphics\n";
01726       write_error(speedtree_cat.warning());
01727       _is_valid = false;
01728       return;
01729     }
01730 
01731     // This call apparently must be made at draw time, not earlier,
01732     // because it might attempt to create OpenGL index buffers and
01733     // such.
01734     _forest_render.UpdateTreeCellExtents();
01735 
01736     if (has_terrain()) {
01737       // Now initialize the terrain.
01738       if (!_terrain_render.Init(speedtree_terrain_num_lods, 
01739                                 speedtree_terrain_resolution,
01740                                 speedtree_terrain_cell_size,
01741                                 _terrain->get_st_vertex_format())) {
01742         speedtree_cat.warning()
01743           << "Failed to init terrain\n";
01744         write_error(speedtree_cat.warning());
01745       }
01746     }
01747 
01748     // If we needed to repopulate, it means we didn't cull in the cull
01749     // traversal.  Do it now.
01750     cull_forest();
01751     _needs_repopulate = false;
01752   }
01753   if (has_terrain()) {
01754     PStatTimer timer1(_draw_speedtree_terrain_update_pcollector);
01755     update_terrain_cells();
01756   }
01757 }
01758 
01759 ////////////////////////////////////////////////////////////////////
01760 //     Function: SpeedTreeNode::cull_forest
01761 //       Access: Private
01762 //  Description: Calls the SpeedTree methods to perform the needed
01763 //               cull calculations.
01764 ////////////////////////////////////////////////////////////////////
01765 void SpeedTreeNode::
01766 cull_forest() {
01767   {
01768     PStatTimer timer1(_cull_speedtree_trees_pcollector);
01769     _forest_render.CullAndComputeLOD(_view, _visible_trees);
01770   }
01771   if (has_terrain()) {
01772     PStatTimer timer1(_cull_speedtree_terrain_pcollector);
01773     _terrain_render.CullAndComputeLOD(_view, _visible_terrain);
01774   }
01775 
01776   if (_forest_render.ShadowsAreEnabled()) {
01777     PStatTimer timer1(_cull_speedtree_shadows_pcollector);
01778     for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
01779       SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
01780       SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull;
01781 
01782       _forest_render.ComputeLightView
01783         (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi, 
01784          light_view, 0.0f);
01785       
01786       light_view.SetLodRefPoint(_view.GetCameraPos());
01787       _forest_render.CullAndComputeLOD(light_view, light_cull, false);
01788     }
01789   }
01790 }
01791 
01792 
01793 ////////////////////////////////////////////////////////////////////
01794 //     Function: SpeedTreeNode::print_forest_stats
01795 //       Access: Private
01796 //  Description: 
01797 ////////////////////////////////////////////////////////////////////
01798 void SpeedTreeNode::
01799 print_forest_stats(const SpeedTree::CForest::SPopulationStats &forest_stats) const {
01800   fprintf(stderr, "\n                Forest Population Statistics\n");
01801   fprintf(stderr, "   ---------------------------------------------------\n");
01802   fprintf(stderr, "                    # of tree cull cells: %d\n", forest_stats.m_nNumCells);
01803   fprintf(stderr, "                  # of unique base trees: %d\n", forest_stats.m_nNumBaseTrees);
01804   fprintf(stderr, "                    total # of instances: %d\n", forest_stats.m_nNumInstances);
01805   fprintf(stderr, "         average # of instances per base: %g\n", forest_stats.m_fAverageNumInstancesPerBase);
01806   fprintf(stderr, "  max # of billboards/instances per cell: %d\n", forest_stats.m_nMaxNumBillboardsPerCell);
01807   fprintf(stderr, "    max # of instances per cell per base:\n");
01808   SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator i;
01809   for (i = forest_stats.m_mMaxNumInstancesPerCellPerBase.begin( ); i != forest_stats.m_mMaxNumInstancesPerCellPerBase.end( ); ++i) {
01810     fprintf(stderr, "        %35s: %4d\n", SpeedTree::CFixedString(i->first->GetFilename( )).NoPath( ).c_str( ), i->second);
01811   }
01812   fprintf(stderr, "            average # instances per cell: %g\n", forest_stats.m_fAverageInstancesPerCell);
01813   fprintf(stderr, "               max # of billboard images: %d\n", forest_stats.m_nMaxNumBillboardImages);
01814   fprintf(stderr, "\n");
01815 }
01816 
01817 ////////////////////////////////////////////////////////////////////
01818 //     Function: SpeedTreeNode::register_with_read_factory
01819 //       Access: Public, Static
01820 //  Description: Tells the BamReader how to create objects of type
01821 //               SpeedTreeNode.
01822 ////////////////////////////////////////////////////////////////////
01823 void SpeedTreeNode::
01824 register_with_read_factory() {
01825   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01826 }
01827 
01828 ////////////////////////////////////////////////////////////////////
01829 //     Function: SpeedTreeNode::write_datagram
01830 //       Access: Public, Virtual
01831 //  Description: Writes the contents of this object to the datagram
01832 //               for shipping out to a Bam file.
01833 ////////////////////////////////////////////////////////////////////
01834 void SpeedTreeNode::
01835 write_datagram(BamWriter *manager, Datagram &dg) {
01836   PandaNode::write_datagram(manager, dg);
01837 
01838   int num_trees = _trees.size();
01839   dg.add_uint32(num_trees);
01840   Trees::const_iterator ti;
01841   for (ti = _trees.begin(); ti != _trees.end(); ++ti) {
01842     InstanceList *instance_list = (*ti);
01843     instance_list->write_datagram(manager, dg);
01844   }
01845 }
01846 
01847 ////////////////////////////////////////////////////////////////////
01848 //     Function: SpeedTreeNode::make_from_bam
01849 //       Access: Protected, Static
01850 //  Description: This function is called by the BamReader's factory
01851 //               when a new object of type SpeedTreeNode is encountered
01852 //               in the Bam file.  It should create the SpeedTreeNode
01853 //               and extract its information from the file.
01854 ////////////////////////////////////////////////////////////////////
01855 TypedWritable *SpeedTreeNode::
01856 make_from_bam(const FactoryParams &params) {
01857   SpeedTreeNode *node = new SpeedTreeNode("");
01858   DatagramIterator scan;
01859   BamReader *manager;
01860 
01861   parse_params(params, scan, manager);
01862   node->fillin(scan, manager);
01863 
01864   return node;
01865 }
01866 
01867 ////////////////////////////////////////////////////////////////////
01868 //     Function: SpeedTreeNode::fillin
01869 //       Access: Protected
01870 //  Description: This internal function is called by make_from_bam to
01871 //               read in all of the relevant data from the BamFile for
01872 //               the new SpeedTreeNode.
01873 ////////////////////////////////////////////////////////////////////
01874 void SpeedTreeNode::
01875 fillin(DatagramIterator &scan, BamReader *manager) {
01876   PandaNode::fillin(scan, manager);
01877 
01878   int num_trees = scan.get_uint32();
01879   _trees.reserve(num_trees);
01880   for (int i = 0; i < num_trees; i++) {
01881     InstanceList *instance_list = new InstanceList(NULL);
01882     instance_list->fillin(scan, manager);
01883     if (instance_list->get_tree() == (STTree *)NULL) {
01884       // The tree wasn't successfully loaded.  Don't keep it.
01885       delete instance_list;
01886     } else {
01887       _trees.push_back(instance_list);
01888     }
01889   }
01890 
01891   _trees.sort();
01892 }
01893 
01894 ////////////////////////////////////////////////////////////////////
01895 //     Function: SpeedTreeNode::InstanceList::output
01896 //       Access: Published
01897 //  Description: 
01898 ////////////////////////////////////////////////////////////////////
01899 void SpeedTreeNode::InstanceList::
01900 output(ostream &out) const {
01901   out << *_tree << ": " << _instances.size() << " instances";
01902 }
01903 
01904 ////////////////////////////////////////////////////////////////////
01905 //     Function: SpeedTreeNode::InstanceList::write
01906 //       Access: Published
01907 //  Description: 
01908 ////////////////////////////////////////////////////////////////////
01909 void SpeedTreeNode::InstanceList::
01910 write(ostream &out, int indent_level) const {
01911   indent(out, indent_level)
01912     << *_tree << ": " << _instances.size() << " instances.\n";
01913   STInstances::const_iterator ii;
01914   for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
01915     indent(out, indent_level + 2)
01916       << STTransform(*ii) << "\n";
01917   }
01918 }
01919 
01920 ////////////////////////////////////////////////////////////////////
01921 //     Function: SpeedTreeNode::InstanceList::write_datagram
01922 //       Access: Public
01923 //  Description: Writes the contents of this object to the datagram
01924 //               for shipping out to a Bam file.
01925 ////////////////////////////////////////////////////////////////////
01926 void SpeedTreeNode::InstanceList::
01927 write_datagram(BamWriter *manager, Datagram &dg) {
01928   // Compute the relative pathname to the SRT file.
01929   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
01930 
01931   bool has_bam_dir = !manager->get_filename().empty();
01932   Filename bam_dir = manager->get_filename().get_dirname();
01933   Filename srt_filename = _tree->get_fullpath();
01934 
01935   bam_dir.make_absolute(vfs->get_cwd());
01936   if (!has_bam_dir || !srt_filename.make_relative_to(bam_dir, true)) {
01937     srt_filename.find_on_searchpath(get_model_path());
01938   }
01939 
01940   dg.add_string(srt_filename);
01941 
01942   // Now record the instances.
01943   int num_instances = _instances.size();
01944   dg.add_uint32(num_instances);
01945   STInstances::const_iterator ii;
01946   for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
01947     STTransform transform = (*ii);
01948     transform.write_datagram(manager, dg);
01949   }
01950 }
01951 
01952 ////////////////////////////////////////////////////////////////////
01953 //     Function: SpeedTreeNode::InstanceList::fillin
01954 //       Access: Public
01955 //  Description: This internal function is called by make_from_bam to
01956 //               read in all of the relevant data from the BamFile for
01957 //               the new SpeedTreeNode.
01958 ////////////////////////////////////////////////////////////////////
01959 void SpeedTreeNode::InstanceList::
01960 fillin(DatagramIterator &scan, BamReader *manager) {
01961   // Get the relative pathname to the SRT file.
01962   string srt_filename = scan.get_string();
01963 
01964   // Now load up the SRT file using the Panda loader (which will
01965   // also search the model-path if necessary).
01966   Loader *loader = Loader::get_global_ptr();
01967   PT(PandaNode) srt_root = loader->load_sync(srt_filename);
01968 
01969   if (srt_root != NULL) {
01970     NodePath srt(srt_root);
01971     NodePath srt_np = srt.find("**/+SpeedTreeNode");
01972     if (!srt_np.is_empty()) {
01973       SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node());
01974       if (srt_node->get_num_trees() >= 1) {
01975         _tree = (STTree *)srt_node->get_tree(0);
01976       }
01977     }
01978   }
01979 
01980   // Now read the instances.
01981   int num_instances = scan.get_uint32();
01982   _instances.reserve(num_instances);
01983   for (int i = 0; i < num_instances; i++) {
01984     STTransform transform;
01985     transform.fillin(scan, manager);
01986     _instances.push_back(transform);
01987   }
01988 }
01989 
01990 ////////////////////////////////////////////////////////////////////
01991 //     Function: SpeedTreeNode::DrawCallback::do_callback
01992 //       Access: Public, Virtual
01993 //  Description: This method called when the callback is triggered; it
01994 //               *replaces* the original function.  To continue
01995 //               performing the original function, you must call
01996 //               cbdata->upcall() during the callback.
01997 ////////////////////////////////////////////////////////////////////
01998 void SpeedTreeNode::DrawCallback::
01999 do_callback(CallbackData *data) {
02000   _node->draw_callback(data);
02001 }
 All Classes Functions Variables Enumerations