37 #ifdef SPEEDTREE_OPENGL 38 #include <glew/glew.h> 39 #endif // SPEEDTREE_OPENGL 41 #ifdef SPEEDTREE_DIRECTX9 49 double SpeedTreeNode::_global_time_delta = 0.0;
50 bool SpeedTreeNode::_authorized;
51 bool SpeedTreeNode::_done_first_init;
53 TypeHandle SpeedTreeNode::DrawCallback::_type_handle;
55 PStatCollector SpeedTreeNode::_cull_speedtree_pcollector(
"Cull:SpeedTree");
56 PStatCollector SpeedTreeNode::_cull_speedtree_shadows_pcollector(
"Cull:SpeedTree:Shadows");
57 PStatCollector SpeedTreeNode::_cull_speedtree_trees_pcollector(
"Cull:SpeedTree:Trees");
58 PStatCollector SpeedTreeNode::_cull_speedtree_terrain_pcollector(
"Cull:SpeedTree:Terrain");
59 PStatCollector SpeedTreeNode::_draw_speedtree_pcollector(
"Draw:SpeedTree");
60 PStatCollector SpeedTreeNode::_draw_speedtree_shadows_pcollector(
"Draw:SpeedTree:Shadows");
61 PStatCollector SpeedTreeNode::_draw_speedtree_trees_pcollector(
"Draw:SpeedTree:Trees");
62 PStatCollector SpeedTreeNode::_draw_speedtree_terrain_pcollector(
"Draw:SpeedTree:Terrain");
63 PStatCollector SpeedTreeNode::_draw_speedtree_terrain_update_pcollector(
"Draw:SpeedTree:Terrain:Update");
69 SpeedTreeNode(
const string &name) :
71 #ifdef ST_DELETE_FOREST_HACK
74 _forest_render(*(new SpeedTree::CForestRender)),
86 Filename shaders_dir = speedtree_shaders_dir;
90 Filename token_filename =
"Branch.hlsl";
91 if (!
Filename(shaders_dir, token_filename).exists()) {
97 speedtree_cat.warning()
98 <<
"speedtree-shaders-dir is set to " << shaders_dir
99 <<
", which doesn't exist.\n";
101 speedtree_cat.warning()
102 <<
"speedtree-shaders-dir is set to " << shaders_dir
103 <<
", which exists but doesn't contain " << token_filename
111 #if defined(WIN32) || defined(WIN64) 112 if (!_os_shaders_dir.empty() && _os_shaders_dir[_os_shaders_dir.length() - 1] !=
'\\') {
113 _os_shaders_dir +=
"\\";
116 if (!_os_shaders_dir.empty() && _os_shaders_dir[_os_shaders_dir.length() - 1] !=
'/') {
117 _os_shaders_dir +=
"/";
121 SpeedTree::SForestRenderInfo render_info;
122 render_info.m_strShaderPath = _os_shaders_dir.c_str();
123 _forest_render.SetRenderInfo(render_info);
135 int total_instances = 0;
136 Trees::const_iterator ti;
137 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
142 return total_instances;
158 Trees::iterator ti = _trees.find(&ilist);
159 if (ti == _trees.
end()) {
162 std::pair<Trees::iterator, bool> result = _trees.insert(instance_list);
164 bool inserted = result.second;
165 nassertr(inserted, *(*ti));
167 if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->
get_tree())) {
168 speedtree_cat.warning()
169 <<
"Failed to register tree " << tree->
get_fullpath() <<
"\n";
174 _needs_repopulate =
true;
175 mark_internal_bounds_stale();
177 return *instance_list;
187 Trees::iterator ti = _trees.find(&ilist);
188 if (ti == _trees.
end()) {
193 if (!_forest_render.UnregisterTree(tree->
get_tree())) {
194 speedtree_cat.warning()
195 <<
"Failed to unregister tree " << tree->
get_fullpath() <<
"\n";
199 _needs_repopulate =
true;
200 mark_internal_bounds_stale();
205 delete instance_list;
216 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
219 if (!_forest_render.UnregisterTree(tree->
get_tree())) {
220 speedtree_cat.warning()
221 <<
"Failed to unregister tree " << tree->
get_fullpath() <<
"\n";
224 delete instance_list;
228 _needs_repopulate =
true;
229 mark_internal_bounds_stale();
239 Trees::const_iterator ti = _trees.find(&ilist);
240 return (ti != _trees.
end());
250 InstanceList ilist(tree);
251 Trees::const_iterator ti = _trees.find(&ilist);
252 if (ti == _trees.
end()) {
254 static InstanceList empty_list(
nullptr);
258 InstanceList *instance_list = (*ti);
259 return *instance_list;
278 new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
295 Thread::get_current_thread());
305 for (
int ti = 0; ti < num_trees; ++ti) {
311 for (
int i = 0; i < num_instances; ++i) {
326 for (
int ti = 0; ti < num_trees; ++ti) {
332 for (
int i = 0; i < num_instances; ++i) {
338 new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
359 PN_stdfloat x_min, PN_stdfloat x_max,
360 PN_stdfloat y_min, PN_stdfloat y_max,
361 PN_stdfloat scale_min, PN_stdfloat scale_max,
362 PN_stdfloat height_min, PN_stdfloat height_max,
363 PN_stdfloat slope_min, PN_stdfloat slope_max,
366 _needs_repopulate =
true;
368 for (
int i = 0; i < quantity; ++i) {
370 transform._pos[0] = randomizer.
random_real(x_max - x_min) + x_min;
371 transform._pos[1] = randomizer.
random_real(y_max - y_min) + y_min;
373 transform._scale = randomizer.
random_real(scale_max - scale_min) + scale_min;
377 int repeat_count = speedtree_max_random_try_count;
378 while (!_terrain->placement_is_acceptable(transform._pos[0], transform._pos[1], height_min, height_max, slope_min, slope_max)) {
379 transform._pos[0] = randomizer.
random_real(x_max - x_min) + x_min;
380 transform._pos[1] = randomizer.
random_real(y_max - y_min) + y_min;
381 if (--repeat_count == 0) {
382 nassert_raise(
"Exceeded speedtree-max-random-try-count; bad placement parameters?");
386 transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]);
390 transform._pos[2] = randomizer.
random_real(height_max - height_min) + height_min;
405 Filename fullpath = Filename::text_filename(stf_filename);
408 if (!vfs->
exists(fullpath)) {
409 speedtree_cat.warning()
410 <<
"Couldn't find " << stf_filename <<
"\n";
415 if (file ==
nullptr) {
417 speedtree_cat.error()
418 <<
"Could not find " << stf_filename <<
"\n";
422 if (speedtree_cat.is_debug()) {
423 speedtree_cat.debug()
424 <<
"Reading STF file " << fullpath <<
"\n";
427 istream *in = file->open_read_file(
true);
448 if (loader ==
nullptr) {
459 AlreadyLoaded already_loaded;
463 while (in && !in.eof()) {
466 AlreadyLoaded::iterator ai = already_loaded.find(srt_filename);
467 if (ai != already_loaded.end()) {
475 PT(
PandaNode) srt_root = loader->load_sync(srt_filename);
477 if (srt_root !=
nullptr) {
487 already_loaded[srt_filename] = tree;
494 for (
int ni = 0; ni < num_instances && in && !in.eof(); ++ni) {
496 PN_stdfloat rotate, scale;
497 in >> pos[0] >> pos[1] >> pos[2] >> rotate >> scale;
499 if (!speedtree_5_2_stf) {
502 PN_stdfloat height_min, height_max, slope_min, slope_max;
503 in >> height_min >> height_max >> slope_min >> slope_max;
506 if (tree !=
nullptr) {
521 speedtree_cat.error()
522 <<
"Unexpected text in " << pathname <<
" at \"" << text <<
"\"\n";
542 if (terrain->setup_terrain(terrain_file)) {
560 _needs_repopulate =
true;
562 if (terrain ==
nullptr) {
575 _terrain_render.SetShaderLoader(_forest_render.GetShaderLoader());
577 SpeedTree::STerrainRenderInfo trender_info;
578 trender_info.m_strShaderPath = _os_shaders_dir.c_str();
581 trender_info.m_strNormalMap = os_specific.c_str();
583 trender_info.m_strSplatMap = os_specific.c_str();
585 for (
int i = 0; i < SpeedTree::c_nNumTerrainSplatLayers; ++i) {
587 trender_info.m_astrSplatLayers[i] = os_specific.c_str();
591 trender_info.m_fNormalMapBlueScale = 1.0f;
592 trender_info.m_bShadowsEnabled =
false;
593 trender_info.m_bZPrePass =
false;
595 _terrain_render.SetRenderInfo(trender_info);
599 if (speedtree_follow_terrain) {
611 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
615 if (_terrain !=
nullptr) {
616 for (
int i = 0; i < num_instances; ++i) {
619 pos[2] = _terrain->get_height(pos[0], pos[1]);
624 for (
int i = 0; i < num_instances; ++i) {
634 _needs_repopulate =
true;
645 _shadow_infos.clear();
646 int num_shadow_maps = speedtree_cascading_shadow_splits.
get_num_words();
647 if (num_shadow_maps > SpeedTree::c_nMaxNumShadowMaps) {
648 speedtree_cat.warning()
649 <<
"SpeedTree is current compiled to support a maximum of " 650 << SpeedTree::c_nMaxNumShadowMaps <<
" shadow maps.\n";
651 num_shadow_maps = SpeedTree::c_nMaxNumShadowMaps;
653 _shadow_infos.insert(_shadow_infos.begin(), num_shadow_maps, ShadowInfo());
654 for (
int smi = 0; smi < num_shadow_maps; ++smi) {
655 _shadow_infos[smi]._shadow_split = speedtree_cascading_shadow_splits[smi];
658 SpeedTree::SForestRenderInfo render_info = _forest_render.GetRenderInfo();
660 render_info.m_nMaxAnisotropy = speedtree_max_anisotropy;
661 render_info.m_bHorizontalBillboards = speedtree_horizontal_billboards;
662 render_info.m_fAlphaTestScalar = speedtree_alpha_test_scalar;
663 render_info.m_bZPrePass = speedtree_z_pre_pass;
664 render_info.m_nMaxBillboardImagesByBase = speedtree_max_billboard_images_by_base;
665 render_info.m_fVisibility = speedtree_visibility;
666 render_info.m_fGlobalLightScalar = speedtree_global_light_scalar;
667 render_info.m_sLightMaterial.m_vSpecular = SpeedTree::Vec4(speedtree_specular_color[0], speedtree_specular_color[1], speedtree_specular_color[2], speedtree_specular_color[3]);
668 render_info.m_sLightMaterial.m_vEmissive = SpeedTree::Vec4(speedtree_emissive_color[0], speedtree_emissive_color[1], speedtree_emissive_color[2], speedtree_emissive_color[3]);
669 render_info.m_bSpecularLighting = speedtree_specular_lighting;
670 render_info.m_bTransmissionLighting = speedtree_transmission_lighting;
671 render_info.m_bDetailLayer = speedtree_detail_layer;
672 render_info.m_bDetailNormalMapping = speedtree_detail_normal_mapping;
673 render_info.m_bAmbientContrast = speedtree_ambient_contrast;
674 render_info.m_fTransmissionScalar = speedtree_transmission_scalar;
675 render_info.m_fFogStartDistance = speedtree_fog_distance[0];
676 render_info.m_fFogEndDistance = speedtree_fog_distance[1];
677 render_info.m_vFogColor = SpeedTree::Vec3(speedtree_fog_color[0], speedtree_fog_color[1], speedtree_fog_color[2]);
678 render_info.m_vSkyColor = SpeedTree::Vec3(speedtree_sky_color[0], speedtree_sky_color[1], speedtree_sky_color[2]);
679 render_info.m_fSkyFogMin = speedtree_sky_fog[0];
680 render_info.m_fSkyFogMax = speedtree_sky_fog[1];
681 render_info.m_vSunColor = SpeedTree::Vec3(speedtree_sun_color[0], speedtree_sun_color[1], speedtree_sun_color[2]);
682 render_info.m_fSunSize = speedtree_sun_size;
683 render_info.m_fSunSpreadExponent = speedtree_sun_spread_exponent;
684 render_info.m_fSunFogBloom = speedtree_sun_fog_bloom;
685 render_info.m_nNumShadowMaps = num_shadow_maps;
686 render_info.m_nShadowMapResolution = speedtree_shadow_map_resolution;
687 render_info.m_bSmoothShadows = speedtree_smooth_shadows;
688 render_info.m_bShowShadowSplitsOnTerrain = speedtree_show_shadow_splits_on_terrain;
689 render_info.m_bWindEnabled = speedtree_wind_enabled;
690 render_info.m_bFrondRippling = speedtree_frond_rippling;
692 _forest_render.SetRenderInfo(render_info);
694 _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
695 _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
696 speedtree_max_num_visible_cells);
697 _visible_terrain.Reserve(speedtree_max_num_visible_cells);
699 _needs_repopulate =
true;
707 set_wind(
double strength,
const LVector3 &direction) {
708 _forest_render.SetGlobalWindStrength(strength);
709 _forest_render.SetGlobalWindDirection(SpeedTree::Vec3(direction[0], direction[1], direction[2]));
722 if (!license.empty()) {
723 SpeedTree::CCore::Authorize(license.c_str());
725 if (!speedtree_license.empty()) {
726 SpeedTree::CCore::Authorize(speedtree_license.c_str());
730 _authorized = SpeedTree::CCore::IsAuthorized();
732 SpeedTree::CCore::SetTextureFlip(
true);
744 _os_shaders_dir(copy._os_shaders_dir),
745 _shadow_infos(copy._shadow_infos),
746 #ifdef ST_DELETE_FOREST_HACK
749 _forest_render(*(new SpeedTree::CForestRender)),
751 _time_delta(copy._time_delta)
755 _forest_render.SetRenderInfo(copy._forest_render.GetRenderInfo());
756 _terrain_render.SetRenderInfo(copy._terrain_render.GetRenderInfo());
759 _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
760 _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
761 speedtree_max_num_visible_cells);
762 _visible_terrain.Reserve(speedtree_max_num_visible_cells);
764 Trees::const_iterator ti;
765 for (ti = copy._trees.
begin(); ti != copy._trees.
end(); ++ti) {
766 InstanceList *instance_list = (*ti);
768 if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->
get_tree())) {
769 speedtree_cat.warning()
770 <<
"Failed to register tree " << tree->
get_fullpath() <<
"\n";
774 _trees.
push_back(
new InstanceList(*instance_list));
780 _needs_repopulate =
true;
781 mark_internal_bounds_stale();
791 _forest_render.ClearInstances();
849 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
852 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
854 STInstances &instances = instance_list->_instances;
855 STInstances::iterator sti;
856 for (sti = instances.begin(); sti != instances.end(); ++sti) {
858 (*sti) = orig_transform *
xform;
862 mark_internal_bounds_stale();
891 nassertr(gsg !=
nullptr,
true);
892 if (!validate_api(gsg)) {
897 _forest_render.SetGlobalTime(clock->
get_frame_time() + _time_delta + _global_time_delta);
898 _forest_render.AdvanceGlobalWind();
902 CPT(
TransformState) orig_modelview = data.get_modelview_transform(trav);
904 CPT(
TransformState) camera_transform = modelview->invert_compose(TransformState::make_identity());
905 LMatrix4f modelview_mat = LCAST(
float, modelview->get_mat());
906 const LPoint3 &camera_pos = camera_transform->get_pos();
909 LMatrix4f projection_mat =
913 _view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]),
914 SpeedTree::Mat4x4(projection_mat.get_data()),
915 SpeedTree::Mat4x4(modelview_mat.get_data()),
923 bool show_textures =
true;
928 _forest_render.EnableTexturing(show_textures);
929 _terrain_render.EnableTexturing(show_textures);
935 LColor ambient_color(0.0f, 0.0f, 0.0f, 0.0f);
938 LColor diffuse_color;
940 int diffuse_priority = 0;
961 if (dlight !=
nullptr) {
965 _light_dir = SpeedTree::Vec3(dir[0], dir[1], dir[2]);
971 _light_dir = SpeedTree::Vec3(0.0, 0.0, -1.0);
974 ambient_color.set(1.0f, 1.0f, 1.0f, 1.0f);
975 diffuse_color.set(1.0f, 1.0f, 1.0f, 1.0f);
978 SpeedTree::SForestRenderInfo render_info = _forest_render.GetRenderInfo();
979 render_info.m_sLightMaterial.m_vAmbient = SpeedTree::Vec4(ambient_color[0], ambient_color[1], ambient_color[2], 1.0f);
980 render_info.m_sLightMaterial.m_vDiffuse = SpeedTree::Vec4(diffuse_color[0], diffuse_color[1], diffuse_color[2], 1.0f);
981 _forest_render.SetRenderInfo(render_info);
983 _forest_render.SetLightDir(_light_dir);
985 SpeedTree::st_float32 updated_splits[SpeedTree::c_nMaxNumShadowMaps];
986 memset(updated_splits, 0,
sizeof(updated_splits));
987 for (
int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
988 updated_splits[smi] = _shadow_infos[smi]._shadow_split;
991 _forest_render.SetCascadedShadowMapDistances(updated_splits, lens->
get_far());
992 _forest_render.SetShadowFadePercentage(speedtree_shadow_fade);
994 if (!_needs_repopulate) {
1029 TransformState::make_identity());
1030 object->set_draw_callback(
new DrawCallback(
this));
1048 if (validate_api(gsg)) {
1049 setup_for_render(gsg);
1060 int &internal_vertices,
1062 Thread *current_thread)
const {
1063 internal_vertices = 0;
1065 SpeedTree::CExtents extents;
1066 Trees::const_iterator ti;
1067 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
1071 const STInstances &st_instances = instance_list->_instances;
1072 STInstances::const_iterator ii;
1073 for (ii = st_instances.begin(); ii != st_instances.end(); ++ii) {
1074 SpeedTree::CExtents tree_extents = tree->
get_tree()->GetExtents();
1075 tree_extents.Rotate((*ii).GetRotationAngle());
1076 tree_extents.Scale((*ii).GetScale());
1077 tree_extents.Translate((*ii).GetPos());
1078 extents.ExpandAround(tree_extents);
1082 const SpeedTree::Vec3 &emin = extents.Min();
1083 const SpeedTree::Vec3 &emax = extents.Max();
1084 internal_bounds =
new BoundingBox(LPoint3(emin[0], emin[1], emin[2]),
1085 LPoint3(emax[0], emax[1], emax[2]));
1095 PandaNode::output(out);
1104 void SpeedTreeNode::
1105 write(ostream &out,
int indent_level)
const {
1106 PandaNode::write(out, indent_level);
1125 const char *error = SpeedTree::CCore::GetError();
1126 if (error !=
nullptr) {
1135 void SpeedTreeNode::
1136 set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode eMode)
const {
1139 SpeedTree::CRenderState::SetBlending(
false);
1140 SpeedTree::CRenderState::SetAlphaTesting(
false);
1141 SpeedTree::CRenderState::SetAlphaToCoverage(
false);
1144 case SpeedTree::TRANS_TEXTURE_ALPHA_TESTING:
1145 SpeedTree::CRenderState::SetAlphaTesting(
true);
1147 case SpeedTree::TRANS_TEXTURE_ALPHA_TO_COVERAGE:
1148 SpeedTree::CRenderState::SetAlphaToCoverage(
true);
1150 case SpeedTree::TRANS_TEXTURE_BLENDING:
1151 SpeedTree::CRenderState::SetBlending(
true);
1162 void SpeedTreeNode::
1164 PandaNode::set_cull_callback();
1167 _needs_repopulate =
false;
1171 speedtree_cat.warning()
1172 <<
"SpeedTree license not available.\n";
1176 _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS,
1177 speedtree_max_num_visible_cells);
1179 _forest_render.SetCullCellSize(speedtree_cull_cell_size);
1190 void SpeedTreeNode::
1192 Thread *current_thread) {
1193 if (node->
is_of_type(SpeedTreeNode::get_class_type()) && node !=
this) {
1198 Children children = node->
get_children(current_thread);
1199 for (
int i = 0; i < children.get_num_children(); i++) {
1201 CPT(
TransformState) child_transform = transform->compose(child->get_transform());
1202 r_add_instances(child, child_transform, current_thread);
1210 void SpeedTreeNode::
1212 _forest_render.ClearInstances();
1215 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
1216 InstanceList *instance_list = (*ti);
1218 const STInstances &instances = instance_list->_instances;
1219 if (instances.empty()) {
1227 if (!_forest_render.AddInstances(tree->
get_tree(), &instances[0], instances.size())) {
1228 speedtree_cat.warning()
1229 <<
"Failed to add " << instances.size()
1230 <<
" instances for " << *tree <<
"\n";
1235 _forest_render.GetPopulationStats(_population_stats);
1236 print_forest_stats(_population_stats);
1239 int max_instances_by_cell = 1;
1240 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
1241 InstanceList *instance_list = (*ti);
1243 const STInstances &instances = instance_list->_instances;
1244 if (instances.empty()) {
1248 int max_instances = 1;
1249 SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
1250 si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->
get_tree());
1251 if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) {
1252 max_instances = std::max(max_instances, (
int)si->second);
1255 max_instances_by_cell = std::max(max_instances_by_cell, max_instances);
1258 _visible_trees.Reserve(_forest_render.GetBaseTrees(),
1259 _forest_render.GetBaseTrees().size(),
1260 speedtree_max_num_visible_cells,
1261 max_instances_by_cell,
1262 speedtree_horizontal_billboards);
1268 void SpeedTreeNode::
1269 update_terrain_cells() {
1272 SpeedTree::TTerrainCellArray &cells = _visible_terrain.m_aCellsToUpdate;
1274 int num_tile_res = _terrain_render.GetMaxTileRes();
1275 PN_stdfloat cell_size = _terrain_render.GetCellSize();
1280 GeomEnums::UH_static);
1281 int num_vertices = num_tile_res * num_tile_res;
1283 size_t num_bytes = vertex_data->get_array(0)->get_data_size_bytes();
1285 int num_cells = (int)cells.size();
1286 for (
int ci = 0; ci < num_cells; ++ci) {
1287 SpeedTree::CTerrainCell *cell = cells[ci];
1288 nassertv(cell !=
nullptr && cell->GetVbo() !=
nullptr);
1289 int cell_yi = cell->Row();
1290 int cell_xi = cell->Col();
1293 _terrain->fill_vertices(vertex_data,
1294 cell_xi * cell_size, cell_yi * cell_size,
1295 cell_size, num_tile_res);
1299 const unsigned char *data_pointer = handle->get_read_pointer(
true);
1300 SpeedTree::CGeometryBuffer *vbo = (SpeedTree::CGeometryBuffer *)cell->GetVbo();
1302 nassertv(vbo->NumVertices() == num_tile_res * num_tile_res);
1303 nassertv(vbo->NumVertices() * vbo->VertexSize() == handle->get_data_size_bytes());
1304 vbo->OverwriteVertices(data_pointer, num_vertices, 0);
1312 bool SpeedTreeNode::
1315 nassertr(pipe !=
nullptr,
true);
1317 #if defined(SPEEDTREE_OPENGL) 1318 static const string compiled_api =
"OpenGL";
1319 #elif defined(SPEEDTREE_DIRECTX9) 1320 static const string compiled_api =
"DirectX9";
1322 #error Unexpected graphics API. 1325 if (pipe->get_interface_name() != compiled_api) {
1326 speedtree_cat.error()
1327 <<
"SpeedTree is compiled for " << compiled_api
1328 <<
", cannot render with " << pipe->get_interface_name()
1342 void SpeedTreeNode::
1344 PStatTimer timer(_draw_speedtree_pcollector);
1346 DCAST_INTO_V(geom_cbdata, data);
1350 setup_for_render(gsg);
1353 SpeedTree::CRenderState::SetAlphaFunction(SpeedTree::ALPHAFUNC_GREATER, 0.0f);
1356 _forest_render.StartRender();
1358 if (_forest_render.ShadowsAreEnabled()) {
1361 PStatTimer timer(_draw_speedtree_shadows_pcollector);
1362 render_forest_into_shadow_maps();
1363 _forest_render.ClearBoundTextures( );
1366 if (!_forest_render.UploadViewShaderParameters(_view)) {
1367 speedtree_cat.warning()
1368 <<
"Couldn't set view parameters\n";
1373 PStatTimer timer1(_draw_speedtree_terrain_pcollector);
1375 _terrain_render.UploadShaderConstants
1376 (&_forest_render, _light_dir,
1377 _forest_render.GetRenderInfo().m_sLightMaterial);
1380 set_transparent_texture_mode(SpeedTree::TRANS_TEXTURE_NOTHING);
1383 bool terrain = _terrain_render.Render
1384 (&_forest_render, _visible_terrain, SpeedTree::RENDER_PASS_STANDARD,
1385 _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial,
1386 &_forest_render.GetRenderStats());
1389 speedtree_cat.warning()
1390 <<
"Failed to render terrain\n";
1400 PStatTimer timer1(_draw_speedtree_trees_pcollector);
1404 SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_ALPHA_TO_COVERAGE;
1408 set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode(mode));
1410 bool branches = _forest_render.RenderBranches(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
1411 bool fronds = _forest_render.RenderFronds(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
1412 bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
1413 bool leaf_cards = _forest_render.RenderLeafCards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
1414 bool billboards = _forest_render.RenderBillboards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
1420 if (!branches || !fronds || !leaf_meshes || !leaf_cards ) {
1421 speedtree_cat.warning()
1422 <<
"Failed to render forest completely: " 1423 << branches <<
" " << fronds <<
" " << leaf_meshes <<
" " << leaf_cards <<
" " << billboards <<
"\n";
1428 _forest_render.EndRender();
1430 if (_forest_render.ShadowsAreEnabled() && speedtree_show_overlays) {
1431 _forest_render.RenderOverlays();
1444 void SpeedTreeNode::
1445 render_forest_into_shadow_maps() {
1446 bool success =
true;
1449 SpeedTree::CRenderState::SetMultisampling(
false);
1450 SpeedTree::CRenderState::SetAlphaToCoverage(
false);
1452 #if defined(SPEEDTREE_OPENGL) 1454 glDisable(GL_SCISSOR_TEST);
1457 for (
int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
1458 const SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
1459 const SpeedTree::SForestCullResults &light_cull = _shadow_infos[smi]._light_cull;
1461 if (_forest_render.BeginShadowMap(smi, light_view)) {
1462 success &= _forest_render.UploadViewShaderParameters(light_view);
1466 SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f);
1468 success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW);
1472 SpeedTree::CRenderState::SetPolygonOffset(10.0f, 1.0f);
1474 success &= _forest_render.RenderFronds(light_cull, SpeedTree::RENDER_PASS_SHADOW);
1475 success &= _forest_render.RenderLeafMeshes(light_cull, SpeedTree::RENDER_PASS_SHADOW);
1476 success &= _forest_render.RenderLeafCards(light_cull, SpeedTree::RENDER_PASS_SHADOW, light_view);
1480 success &= _forest_render.EndShadowMap(smi);
1488 speedtree_cat.warning()
1489 <<
"Failed to render shadow maps\n";
1499 void SpeedTreeNode::
1501 if (!_done_first_init) {
1506 #ifdef SPEEDTREE_OPENGL 1509 GLenum err = glewInit();
1510 if (err != GLEW_OK) {
1511 speedtree_cat.error()
1512 <<
"GLEW initialization failed: %s\n", glewGetErrorString(err);
1520 if (!GLEW_VERSION_2_0) {
1521 speedtree_cat.error()
1522 <<
"The SpeedTree OpenGL implementation requires OpenGL 2.0 or better to run; this system has version " << glGetString(GL_VERSION) <<
"\n";
1526 #endif // SPEEDTREE_OPENGL 1528 _done_first_init =
true;
1531 #ifdef SPEEDTREE_DIRECTX9 1534 SpeedTree::DX9::SetDevice(dxgsg->_screen->_d3d_device);
1535 #endif // SPEEDTREE_DIRECTX9 1537 if (_needs_repopulate) {
1541 Trees::const_iterator ti;
1542 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
1543 InstanceList *instance_list = (*ti);
1545 const STInstances &instances = instance_list->_instances;
1546 if (instances.empty()) {
1550 int max_instances = 2;
1551 SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
1552 si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->
get_tree());
1553 if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) {
1554 max_instances = std::max(max_instances, (
int)si->second);
1558 string os_textures_dir;
1559 if (!speedtree_textures_dir.empty()) {
1560 os_textures_dir = speedtree_textures_dir.
get_value().to_os_specific();
1563 #if defined(WIN32) || defined(WIN64) 1564 if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] !=
'\\') {
1565 os_textures_dir +=
"\\";
1568 if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] !=
'/') {
1569 os_textures_dir +=
"/";
1574 if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->
get_tree(),
1575 max_instances, speedtree_horizontal_billboards,
1576 os_textures_dir.c_str())) {
1577 if (speedtree_cat.is_debug()) {
1578 speedtree_cat.debug()
1579 <<
"Failed to init tree graphics for " << *tree <<
"\n";
1586 if (!_forest_render.InitGraphics(
false)) {
1587 speedtree_cat.warning()
1588 <<
"Failed to init graphics\n";
1596 _forest_render.UpdateTreeCellExtents();
1600 if (!_terrain_render.Init(speedtree_terrain_num_lods,
1601 speedtree_terrain_resolution,
1602 speedtree_terrain_cell_size,
1603 _terrain->get_st_vertex_format())) {
1604 speedtree_cat.warning()
1605 <<
"Failed to init terrain\n";
1613 _needs_repopulate =
false;
1616 PStatTimer timer1(_draw_speedtree_terrain_update_pcollector);
1617 update_terrain_cells();
1624 void SpeedTreeNode::
1627 PStatTimer timer1(_cull_speedtree_trees_pcollector);
1628 _forest_render.CullAndComputeLOD(_view, _visible_trees);
1631 PStatTimer timer1(_cull_speedtree_terrain_pcollector);
1632 _terrain_render.CullAndComputeLOD(_view, _visible_terrain);
1635 if (_forest_render.ShadowsAreEnabled()) {
1636 PStatTimer timer1(_cull_speedtree_shadows_pcollector);
1637 for (
int smi = 0; smi < (int)_shadow_infos.size(); ++smi) {
1638 SpeedTree::CView &light_view = _shadow_infos[smi]._light_view;
1639 SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull;
1641 _forest_render.ComputeLightView
1642 (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi,
1645 light_view.SetLodRefPoint(_view.GetCameraPos());
1646 _forest_render.CullAndComputeLOD(light_view, light_cull,
false);
1655 void SpeedTreeNode::
1656 print_forest_stats(
const SpeedTree::CForest::SPopulationStats &forest_stats)
const {
1657 fprintf(stderr,
"\n Forest Population Statistics\n");
1658 fprintf(stderr,
" ---------------------------------------------------\n");
1659 fprintf(stderr,
" # of tree cull cells: %d\n", forest_stats.m_nNumCells);
1660 fprintf(stderr,
" # of unique base trees: %d\n", forest_stats.m_nNumBaseTrees);
1661 fprintf(stderr,
" total # of instances: %d\n", forest_stats.m_nNumInstances);
1662 fprintf(stderr,
" average # of instances per base: %g\n", forest_stats.m_fAverageNumInstancesPerBase);
1663 fprintf(stderr,
" max # of billboards/instances per cell: %d\n", forest_stats.m_nMaxNumBillboardsPerCell);
1664 fprintf(stderr,
" max # of instances per cell per base:\n");
1665 SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator i;
1666 for (i = forest_stats.m_mMaxNumInstancesPerCellPerBase.begin( ); i != forest_stats.m_mMaxNumInstancesPerCellPerBase.end( ); ++i) {
1667 fprintf(stderr,
" %35s: %4d\n", SpeedTree::CFixedString(i->first->GetFilename( )).NoPath( ).c_str( ), i->second);
1669 fprintf(stderr,
" average # instances per cell: %g\n", forest_stats.m_fAverageInstancesPerCell);
1670 fprintf(stderr,
" max # of billboard images: %d\n", forest_stats.m_nMaxNumBillboardImages);
1671 fprintf(stderr,
"\n");
1690 int num_trees = _trees.
size();
1692 Trees::const_iterator ti;
1693 for (ti = _trees.
begin(); ti != _trees.
end(); ++ti) {
1711 node->fillin(scan, manager);
1720 void SpeedTreeNode::
1722 PandaNode::fillin(scan, manager);
1726 for (
int i = 0; i < num_trees; i++) {
1727 InstanceList *instance_list =
new InstanceList(
nullptr);
1728 instance_list->fillin(scan, manager);
1729 if (instance_list->get_tree() ==
nullptr) {
1731 delete instance_list;
1743 void SpeedTreeNode::InstanceList::
1744 output(ostream &out)
const {
1745 out << *_tree <<
": " << _instances.size() <<
" instances";
1751 void SpeedTreeNode::InstanceList::
1752 write(ostream &out,
int indent_level)
const {
1753 indent(out, indent_level)
1754 << *_tree <<
": " << _instances.size() <<
" instances.\n";
1755 STInstances::const_iterator ii;
1756 for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
1757 indent(out, indent_level + 2)
1783 int num_instances = _instances.size();
1785 STInstances::const_iterator ii;
1786 for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
1804 PT(
PandaNode) srt_root = loader->load_sync(srt_filename);
1806 if (srt_root !=
nullptr) {
1819 _instances.reserve(num_instances);
1820 for (
int i = 0; i < num_instances; i++) {
1822 transform.
fillin(scan, manager);
1823 _instances.push_back(transform);
1832 void SpeedTreeNode::DrawCallback::
1834 _node->draw_callback(data);
PN_stdfloat get_max_height() const
Returns the largest height value that might be returned by get_height().
GraphicsStateGuardianBase * get_gsg() const
Returns a pointer to the current GSG.
A GraphicsStateGuardian for rendering into DirectX9 contexts.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
A light shining from infinitely far away in a particular direction, like sunlight.
This specialization on CallbackData is passed when the callback is initiated from deep within the dra...
std::string get_dirname() const
Returns the directory part of the filename.
A basic node of the scene graph or data graph.
NodePath find(const std::string &path) const
Searches for a node below the referenced node that matches the indicated string.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
A specific implementation of STTerrain that supports basic heightmaps loaded from an image file,...
STTerrain * get_terrain() const
Returns the terrain associated with the node, or NULL if there is no terrain.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
This is our own Panda specialization on the default STL map.
get_pipe
Returns the graphics pipe on which this GSG was created.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for any number of different kinds of lenses, linear and otherwise.
bool has_terrain() const
Returns true if a valid terrain has been associated with the node, false otherwise.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void write_error(std::ostream &out)
Writes the current SpeedTree error message to the indicated stream.
int count_total_instances() const
Returns the total number of trees that will be rendered by this node, counting all instances of all t...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
bool is_empty() const
Returns true if the NodePath contains no nodes.
size_type_0 size() const
Returns the number of elements in the ordered vector.
void clear()
Removes all elements from the ordered vector.
Specifies parameters that may be passed to the loader.
A hierarchy of directories and files that appears to be one continuous file system,...
virtual CoordinateSystem get_internal_coordinate_system() const
Returns the coordinate system used internally by the GSG.
virtual void output(std::ostream &out) const
Writes a brief description of the node to the indicated output stream.
void add_instances(const NodePath &root, const TransformState *transform=TransformState::make_identity())
Walks the scene graph beginning at root, looking for nested SpeedTreeNodes.
get_near
Returns the position of the near plane (or cylinder, sphere, whatever).
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
bool has_instance_list(const STTree *tree) const
Returns true if the indicated tree has any instances within this node, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
bool resolve_filename(const DSearchPath &searchpath, const std::string &default_extension=std::string())
Searches the given search path for the filename.
const Filename & get_normal_map() const
Returns the normal map that should be applied to the terrain.
bool setup_terrain(const Filename &terrain_file)
A convenience function to set up terrain geometry by reading a terrain.txt file as defined by SpeedTr...
const Lens * get_lens() const
Returns the particular Lens used for rendering.
get_num_trees
Returns the number of unique tree objects that have been added to the node.
bool is_valid() const
Returns true if the node is valid and ready to render, false otherwise.
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
int remove_tree(const STTree *tree)
Removes all instances of the indicated tree.
A light source that seems to illuminate all points in space at once.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the abstract base class that defines the interface needed to describe a terrain for rendering...
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node,...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This is a generic data block that is passed along to a CallbackObject when a callback is made.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
The abstract base class for a file or directory within the VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_string()
Extracts a variable-length string.
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
void snap_to_terrain()
Adjusts all the trees in this node so that their Z position matches the height of the terrain at thei...
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
bool is_valid() const
Returns true if the terrain data is well-defined and ready to use.
const TransformState * get_cs_transform() const
Returns the transform from the camera's coordinate system to the GSG's internal coordinate system.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so.
get_num_instances
Returns the number of instances of this tree.
A lightweight class that represents a single element that may be timed and/or counted via stats.
size_t get_num_words() const
Returns the number of words in the variable's value.
static Loader * get_global_ptr()
Returns a pointer to the global Loader.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_terrain(STTerrain *terrain)
Associated a terrain with the node.
get_value
Returns the variable's value.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
const STTree * get_tree() const
Returns the particular tree this list refers to.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
double random_real(double range)
Returns a random double in the range [0, range).
void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
get_filename
If a BAM is a file, then the BamWriter should contain the name of the file.
get_instance_list
Returns a list of transforms that corresponds to the instances at which the indicated tree appears.
The smallest atom of cull.
get_on_light
Returns the nth light turned on by the attribute, sorted in render order.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
The name of a file, such as a texture file or an Egg file.
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
void set_instance(int n, const STTransform &transform)
Replaces the transform of the nth instance of this tree.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
const NodePath & get_scene_root() const
Returns the root node of the scene.
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
void add_instance(const STTree *tree, const STTransform &transform)
Adds a new instance of the indicated tree at the indicated transform.
A ClockObject keeps track of elapsed real time and discrete time.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
An object to create GraphicsOutputs that share a particular 3-D API.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
void remove_all_trees()
Removes all instances of all trees from the node.
bool is_valid() const
Returns true if the tree was successfully loaded and is ready to be used, false otherwise.
void sort()
Maps to sort_unique().
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
get_children
Returns an object that can be used to walk through the list of children of the node.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
get_num_on_lights
Returns the number of lights that are turned on by the attribute.
bool set_num_rows(int n)
Sets the length of the array to n rows in all of the various arrays (presumably by adding rows).
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Interfaces with the SpeedTree library to render SpeedTree objects, especially trees,...
void prepare_scene(GraphicsStateGuardianBase *gsgbase, const RenderState *net_state)
Walks through the scene graph beginning at this node, and does whatever initialization is required to...
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
PN_stdfloat get_min_height() const
Returns the smallest height value that might be returned by get_height().
get_instance
Returns the transform of the nth instance of this tree.
bool has_all_off() const
Returns true if this attrib turns off all stages (although it may also turn some on).
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is called by make_from_bam to read in all of the relevant data from the BamFil...
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
GraphicsStateGuardianBase * get_gsg() const
Returns the GraphicsStateGuardian in effect.
const SpeedTree::CTreeRender * get_tree() const
Returns a const pointer to the internal SpeedTree object.
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
bool add_from_stf(const Filename &stf_filename, const LoaderOptions &options=LoaderOptions())
Opens and reads the named STF (SpeedTree Forest) file, and adds the SRT files named within as instanc...
const Filename & get_splat_layer(int n) const
Returns the nth splat layer that is to be applied to the terrain.
void reload_config()
Re-reads the current setting of all of the relevant config variables and applies them to this node.
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
bool is_directory() const
Returns true if the filename exists and is a directory name, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, int pipeline_stage, Thread *current_thread) const
Returns a newly-allocated BoundingVolume that represents the internal contents of the node.
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film,...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
const Filename & get_fullpath() const
Returns the full pathname to the SRT file that was loaded for this tree, as passed to the constructor...
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
PandaNode * node() const
Returns the referenced node of the path.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
int find_on_searchpath(const DSearchPath &searchpath)
Performs the reverse of the resolve_filename() operation: assuming that the current filename is fully...
get_direction
Returns the direction in which the light is aimed.
int get_num_splat_layers() const
Returns the number of splat layers that are to be applied to the terrain.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A handy class to return random numbers.
SceneSetup * get_scene() const
Returns the SceneSetup object.
Encapsulates all the communication with a particular instance of a given rendering backend.
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data)
Adds the node's contents to the CullResult we are building up during the cull traversal,...
get_color
Returns the basic color of the light.
This class stores a list of directories that can be searched, in order, to locate a particular file.
get_tree
Returns the STTree pointer for the nth tree.
void add_instances_from(const SpeedTreeNode *other)
Adds all of the instances defined within the indicated SpeedTreeNode as instances of this node.
static void register_with_read_factory()
Tells the BamReader how to create objects of type SpeedTreeNode.
int add_instance(const STTransform &transform)
Adds a new instance of this tree at the indicated transform.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Filename get_cwd() const
Returns the current directory name.
virtual void load_data()=0
This will be called at some point after initialization.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A class to retrieve the individual data elements previously stored in a Datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static bool authorize(const std::string &license="")
Make this call to initialized the SpeedTree API and verify the license.
get_child
Returns the nth child node of this node.
InstanceList & modify_instance_list(const STTree *tree)
Returns a modifiable list of transforms that corresponds to the instances of this tree.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
void add_random_instances(const STTree *tree, int quantity, PN_stdfloat x_min, PN_stdfloat x_max, PN_stdfloat y_min, PN_stdfloat y_max, PN_stdfloat scale_min, PN_stdfloat scale_max, PN_stdfloat height_min, PN_stdfloat height_max, PN_stdfloat slope_min, PN_stdfloat slope_max, Randomizer &randomizer=Randomizer())
Creates a number of random instances of the indicated true, within the indicated range.
InstanceList & add_tree(const STTree *tree)
Adds a new tree for rendering.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
const Filename & get_splat_map() const
Returns the splat map that should be applied to the terrain.
PN_stdfloat get_splat_layer_tiling(int n) const
Returns the tiling value of the nth splat layer.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void set_lost_state(bool lost_state)
Sets the lost_state flag.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
get_far
Returns the position of the far plane (or cylinder, sphere, whatever).
get_priority
Returns the priority associated with this light.
Encapsulates a single tree model in the SpeedTree library, as loaded from an SRT file.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
This is the data for one array of a GeomVertexData structure.
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
void set_wind(double strength, const LVector3 &direction)
Specifies the overall wind strength and direction.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.