00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00064
00065
00066
00067 SpeedTreeNode::
00068 SpeedTreeNode(const string &name) :
00069 PandaNode(name),
00070 #ifdef ST_DELETE_FOREST_HACK
00071
00072
00073
00074 _forest_render(*(new SpeedTree::CForestRender)),
00075 #endif
00076 _time_delta(0.0)
00077 {
00078 init_node();
00079
00080
00081
00082
00083
00084
00085
00086 Filename shaders_dir = speedtree_shaders_dir;
00087
00088
00089
00090 Filename token_filename = "Branch.hlsl";
00091 if (!Filename(shaders_dir, token_filename).exists()) {
00092
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
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
00126 reload_config();
00127 }
00128
00129
00130
00131
00132
00133
00134
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
00150
00151
00152
00153
00154
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
00165
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
00187
00188
00189
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
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
00219
00220
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
00243
00244
00245
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
00256
00257
00258
00259
00260
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
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
00278
00279
00280
00281
00282
00283 SpeedTreeNode::InstanceList &SpeedTreeNode::
00284 modify_instance_list(const STTree *tree) {
00285 return add_tree(tree);
00286 }
00287
00288
00289
00290
00291
00292
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
00307
00308
00309
00310
00311
00312
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
00323
00324
00325
00326
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
00346
00347
00348
00349
00350
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
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
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
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
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
00431
00432
00433
00434
00435
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
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
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
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
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
00512 srt_filename.resolve_filename(search);
00513
00514
00515
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
00532
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
00542
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
00555 in >> ws;
00556
00557 if (!in.eof()) {
00558
00559
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
00569 return true;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
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
00597
00598
00599
00600
00601
00602
00603
00604
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
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;
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
00655
00656
00657
00658
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
00691
00692
00693
00694
00695
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
00759
00760
00761
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
00771
00772
00773
00774
00775
00776
00777
00778
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
00801
00802
00803
00804 SpeedTreeNode::
00805 SpeedTreeNode(const SpeedTreeNode ©) :
00806 PandaNode(copy),
00807 _os_shaders_dir(copy._os_shaders_dir),
00808 _shadow_infos(copy._shadow_infos),
00809 #ifdef ST_DELETE_FOREST_HACK
00810
00811
00812
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
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
00850
00851
00852
00853 SpeedTreeNode::
00854 ~SpeedTreeNode() {
00855 remove_all_trees();
00856
00857 _forest_render.ClearInstances();
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 PandaNode *SpeedTreeNode::
00869 make_copy() const {
00870 return new SpeedTreeNode(*this);
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
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
00893
00894 SpeedTreeNode *gother = DCAST(SpeedTreeNode, other);
00895
00896
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
00913
00914
00915
00916
00917
00918
00919
00920
00921
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
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
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
00985
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
01003 const RenderState *state = data._state;
01004
01005
01006
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
01016
01017
01018
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
01031 DirectionalLight *light_obj = DCAST(DirectionalLight, light.node());
01032 if (dlight == NULL || light_obj->get_priority() > dlight->get_priority()) {
01033
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
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
01054
01055
01056 _light_dir = SpeedTree::Vec3(0.0, 0.0, -1.0);
01057
01058
01059
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
01082
01083
01084
01085 cull_forest();
01086 }
01087
01088
01089 return true;
01090 }
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 bool SpeedTreeNode::
01103 is_renderable() const {
01104 return true;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 void SpeedTreeNode::
01116 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
01117 if (_is_valid) {
01118
01119
01120
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
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
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
01156
01157
01158
01159
01160
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
01194
01195
01196
01197
01198
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
01210
01211
01212
01213 void SpeedTreeNode::
01214 write(ostream &out, int indent_level) const {
01215 PandaNode::write(out, indent_level);
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 }
01227
01228
01229
01230
01231
01232
01233
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
01246
01247
01248
01249
01250 void SpeedTreeNode::
01251 set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode eMode) const {
01252
01253
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
01270 break;
01271 }
01272 }
01273
01274
01275
01276
01277
01278
01279
01280 void SpeedTreeNode::
01281 init_node() {
01282 PandaNode::set_cull_callback();
01283
01284 _is_valid = false;
01285 _needs_repopulate = false;
01286
01287
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
01300
01301
01302 _is_valid = true;
01303 }
01304
01305
01306
01307
01308
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
01329
01330
01331
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
01344
01345
01346
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
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
01390
01391
01392
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
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
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
01436
01437
01438
01439
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
01468
01469
01470
01471
01472
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
01485 SpeedTree::CRenderState::SetAlphaFunction(SpeedTree::ALPHAFUNC_GREATER, 0.0f);
01486
01487
01488 _forest_render.StartRender();
01489
01490 if (_forest_render.ShadowsAreEnabled()) {
01491
01492
01493
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
01508 _terrain_render.UploadShaderConstants
01509 (&_forest_render, _light_dir,
01510 _forest_render.GetRenderInfo().m_sLightMaterial);
01511
01512
01513 set_transparent_texture_mode(SpeedTree::TRANS_TEXTURE_NOTHING);
01514
01515
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
01527 _terrain = NULL;
01528 }
01529 }
01530
01531 {
01532
01533 PStatTimer timer1(_draw_speedtree_trees_pcollector);
01534
01535
01536 SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_ALPHA_TO_COVERAGE;
01537
01538
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
01548
01549
01550
01551
01552 if (!branches || !fronds || !leaf_meshes || !leaf_cards ) {
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
01567
01568 geom_cbdata->set_lost_state(true);
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578 void SpeedTreeNode::
01579 render_forest_into_shadow_maps() {
01580 bool success = true;
01581
01582
01583 SpeedTree::CRenderState::SetMultisampling(false);
01584 SpeedTree::CRenderState::SetAlphaToCoverage(false);
01585
01586 #if defined(SPEEDTREE_OPENGL)
01587
01588
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
01600
01601 SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f);
01602
01603 success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW);
01604
01605
01606
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
01614
01615
01616 success &= _forest_render.EndShadowMap(smi);
01617 }
01618 }
01619
01620
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
01631
01632
01633
01634
01635
01636
01637 void SpeedTreeNode::
01638 setup_for_render(GraphicsStateGuardian *gsg) {
01639 if (!_done_first_init) {
01640
01641
01642
01643
01644 #ifdef SPEEDTREE_OPENGL
01645
01646
01647 GLenum err = glewInit();
01648 if (err != GLEW_OK) {
01649 speedtree_cat.error()
01650 << "GLEW initialization failed: %s\n", glewGetErrorString(err);
01651
01652 _is_valid = false;
01653 return;
01654 }
01655
01656
01657
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
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
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
01696 string os_textures_dir;
01697 if (!speedtree_textures_dir.empty()) {
01698 os_textures_dir = speedtree_textures_dir.get_value().to_os_specific();
01699
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
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
01732
01733
01734 _forest_render.UpdateTreeCellExtents();
01735
01736 if (has_terrain()) {
01737
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
01749
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
01761
01762
01763
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
01795
01796
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
01819
01820
01821
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
01830
01831
01832
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
01849
01850
01851
01852
01853
01854
01855 TypedWritable *SpeedTreeNode::
01856 make_from_bam(const FactoryParams ¶ms) {
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
01869
01870
01871
01872
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
01885 delete instance_list;
01886 } else {
01887 _trees.push_back(instance_list);
01888 }
01889 }
01890
01891 _trees.sort();
01892 }
01893
01894
01895
01896
01897
01898
01899 void SpeedTreeNode::InstanceList::
01900 output(ostream &out) const {
01901 out << *_tree << ": " << _instances.size() << " instances";
01902 }
01903
01904
01905
01906
01907
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
01922
01923
01924
01925
01926 void SpeedTreeNode::InstanceList::
01927 write_datagram(BamWriter *manager, Datagram &dg) {
01928
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
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
01954
01955
01956
01957
01958
01959 void SpeedTreeNode::InstanceList::
01960 fillin(DatagramIterator &scan, BamReader *manager) {
01961
01962 string srt_filename = scan.get_string();
01963
01964
01965
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
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
01992
01993
01994
01995
01996
01997
01998 void SpeedTreeNode::DrawCallback::
01999 do_callback(CallbackData *data) {
02000 _node->draw_callback(data);
02001 }