mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
add time_delta interfaces
This commit is contained in:
parent
33886780c4
commit
a552cfa859
@ -111,6 +111,58 @@ get_terrain() const {
|
||||
return _terrain;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::set_time_delta
|
||||
// Access: Published
|
||||
// Description: Specifies an offset that is to be added each frame to
|
||||
// the global clock's frame_time for the purpose of
|
||||
// animating the trees in this particular node. Also
|
||||
// see set_global_time_delta().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SpeedTreeNode::
|
||||
set_time_delta(double delta) {
|
||||
_time_delta = delta;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::get_time_delta
|
||||
// Access: Published
|
||||
// Description: Returns an offset that is to be added each frame to
|
||||
// the global clock's frame_time for the purpose of
|
||||
// animating the trees in this particular node. Also
|
||||
// see get_global_time_delta().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double SpeedTreeNode::
|
||||
get_time_delta() const {
|
||||
return _time_delta;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::set_global_time_delta
|
||||
// Access: Published, Static
|
||||
// Description: Specifies an offset that is to be added each frame to
|
||||
// the global clock's frame_time for the purpose of
|
||||
// animating the trees in all SpeedTreeNodes. Also
|
||||
// see set_time_delta().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SpeedTreeNode::
|
||||
set_global_time_delta(double delta) {
|
||||
_global_time_delta = delta;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::get_global_time_delta
|
||||
// Access: Published, Static
|
||||
// Description: Returns an offset that is to be added each frame to
|
||||
// the global clock's frame_time for the purpose of
|
||||
// animating the trees in all SpeedTreeNodes. Also
|
||||
// see get_time_delta().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double SpeedTreeNode::
|
||||
get_global_time_delta() {
|
||||
return _global_time_delta;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::InstanceList::Constructor
|
||||
// Access: Public
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "dxGraphicsStateGuardian9.h"
|
||||
#endif
|
||||
|
||||
double SpeedTreeNode::_global_time_delta = 0.0;
|
||||
bool SpeedTreeNode::_authorized;
|
||||
bool SpeedTreeNode::_done_first_init;
|
||||
TypeHandle SpeedTreeNode::_type_handle;
|
||||
@ -65,13 +66,14 @@ PStatCollector SpeedTreeNode::_draw_speedtree_terrain_update_pcollector("Draw:Sp
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SpeedTreeNode::
|
||||
SpeedTreeNode(const string &name) :
|
||||
PandaNode(name)
|
||||
PandaNode(name),
|
||||
#ifdef ST_DELETE_FOREST_HACK
|
||||
// Early versions of SpeedTree don't destruct unused CForestRender
|
||||
// objects correctly. To avoid crashes, we have to leak these
|
||||
// things.
|
||||
, _forest_render(*(new SpeedTree::CForestRender))
|
||||
_forest_render(*(new SpeedTree::CForestRender)),
|
||||
#endif
|
||||
_time_delta(0.0)
|
||||
{
|
||||
init_node();
|
||||
// For now, set an infinite bounding volume. Maybe in the future
|
||||
@ -92,14 +94,14 @@ SpeedTreeNode(const string &name) :
|
||||
shaders_dir = token_filename.get_dirname();
|
||||
} else {
|
||||
if (!shaders_dir.is_directory()) {
|
||||
speedtree_cat.warning()
|
||||
<< "speedtree-shaders-dir is set to " << shaders_dir
|
||||
<< ", which doesn't exist.\n";
|
||||
speedtree_cat.warning()
|
||||
<< "speedtree-shaders-dir is set to " << shaders_dir
|
||||
<< ", which doesn't exist.\n";
|
||||
} else {
|
||||
speedtree_cat.warning()
|
||||
<< "speedtree-shaders-dir is set to " << shaders_dir
|
||||
<< ", which exists but doesn't contain " << token_filename
|
||||
<< ".\n";
|
||||
speedtree_cat.warning()
|
||||
<< "speedtree-shaders-dir is set to " << shaders_dir
|
||||
<< ", which exists but doesn't contain " << token_filename
|
||||
<< ".\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,7 +171,7 @@ add_tree(const STTree *tree) {
|
||||
|
||||
if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->get_tree())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to register tree " << tree->get_fullpath() << "\n";
|
||||
<< "Failed to register tree " << tree->get_fullpath() << "\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
}
|
||||
@ -225,7 +227,7 @@ remove_all_trees() {
|
||||
const STTree *tree = instance_list->get_tree();
|
||||
if (!_forest_render.UnregisterTree(tree->get_tree())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to unregister tree " << tree->get_fullpath() << "\n";
|
||||
<< "Failed to unregister tree " << tree->get_fullpath() << "\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
delete instance_list;
|
||||
@ -313,7 +315,7 @@ void SpeedTreeNode::
|
||||
add_instances(const NodePath &root, const TransformState *transform) {
|
||||
nassertv(!root.is_empty());
|
||||
r_add_instances(root.node(), transform->compose(root.get_transform()),
|
||||
Thread::get_current_thread());
|
||||
Thread::get_current_thread());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -361,12 +363,12 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform)
|
||||
CPT(TransformState) new_trans = transform->compose(other_trans);
|
||||
|
||||
if (speedtree_follow_terrain && has_terrain()) {
|
||||
STTransform new_transform = new_trans;
|
||||
new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
|
||||
this_instance_list.add_instance(new_transform);
|
||||
STTransform new_transform = new_trans;
|
||||
new_transform._pos[2] = _terrain->get_height(new_transform._pos[0], new_transform._pos[1]);
|
||||
this_instance_list.add_instance(new_transform);
|
||||
|
||||
} else {
|
||||
this_instance_list.add_instance(new_trans.p());
|
||||
this_instance_list.add_instance(new_trans.p());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,12 +389,12 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SpeedTreeNode::
|
||||
add_random_instances(const STTree *tree, int quantity,
|
||||
float x_min, float x_max,
|
||||
float y_min, float y_max,
|
||||
float scale_min, float scale_max,
|
||||
float height_min, float height_max,
|
||||
float slope_min, float slope_max,
|
||||
Randomizer &randomizer) {
|
||||
float x_min, float x_max,
|
||||
float y_min, float y_max,
|
||||
float scale_min, float scale_max,
|
||||
float height_min, float height_max,
|
||||
float slope_min, float slope_max,
|
||||
Randomizer &randomizer) {
|
||||
InstanceList &instance_list = add_tree(tree);
|
||||
_needs_repopulate = true;
|
||||
|
||||
@ -407,12 +409,12 @@ add_random_instances(const STTree *tree, int quantity,
|
||||
// Spin till we find a valid match with terrain.
|
||||
int repeat_count = speedtree_max_random_try_count;
|
||||
while (!_terrain->placement_is_acceptable(transform._pos[0], transform._pos[1], height_min, height_max, slope_min, slope_max)) {
|
||||
transform._pos[0] = randomizer.random_real(x_max - x_min) + x_min;
|
||||
transform._pos[1] = randomizer.random_real(y_max - y_min) + y_min;
|
||||
if (--repeat_count == 0) {
|
||||
nassert_raise("Exceeded speedtree-max-random-try-count; bad placement parameters?");
|
||||
return;
|
||||
}
|
||||
transform._pos[0] = randomizer.random_real(x_max - x_min) + x_min;
|
||||
transform._pos[1] = randomizer.random_real(y_max - y_min) + y_min;
|
||||
if (--repeat_count == 0) {
|
||||
nassert_raise("Exceeded speedtree-max-random-try-count; bad placement parameters?");
|
||||
return;
|
||||
}
|
||||
}
|
||||
transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]);
|
||||
|
||||
@ -483,7 +485,7 @@ add_from_stf(const Filename &stf_filename, const LoaderOptions &options) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SpeedTreeNode::
|
||||
add_from_stf(istream &in, const Filename &pathname,
|
||||
const LoaderOptions &options, Loader *loader) {
|
||||
const LoaderOptions &options, Loader *loader) {
|
||||
if (loader == NULL) {
|
||||
loader = Loader::get_global_ptr();
|
||||
}
|
||||
@ -514,14 +516,14 @@ add_from_stf(istream &in, const Filename &pathname,
|
||||
PT(PandaNode) srt_root = loader->load_sync(srt_filename);
|
||||
|
||||
if (srt_root != NULL) {
|
||||
NodePath srt(srt_root);
|
||||
NodePath srt_np = srt.find("**/+SpeedTreeNode");
|
||||
if (!srt_np.is_empty()) {
|
||||
SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node());
|
||||
if (srt_node->get_num_trees() >= 1) {
|
||||
tree = srt_node->get_tree(0);
|
||||
}
|
||||
}
|
||||
NodePath srt(srt_root);
|
||||
NodePath srt_np = srt.find("**/+SpeedTreeNode");
|
||||
if (!srt_np.is_empty()) {
|
||||
SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node());
|
||||
if (srt_node->get_num_trees() >= 1) {
|
||||
tree = srt_node->get_tree(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
already_loaded[srt_filename] = tree;
|
||||
}
|
||||
@ -536,14 +538,14 @@ add_from_stf(istream &in, const Filename &pathname,
|
||||
in >> pos[0] >> pos[1] >> pos[2] >> rotate >> scale;
|
||||
|
||||
if (!speedtree_5_2_stf) {
|
||||
// 5.1 or earlier stf files also included these additional
|
||||
// values, which we will ignore:
|
||||
float height_min, height_max, slope_min, slope_max;
|
||||
in >> height_min >> height_max >> slope_min >> slope_max;
|
||||
// 5.1 or earlier stf files also included these additional
|
||||
// values, which we will ignore:
|
||||
float height_min, height_max, slope_min, slope_max;
|
||||
in >> height_min >> height_max >> slope_min >> slope_max;
|
||||
}
|
||||
|
||||
if (tree != NULL) {
|
||||
add_instance(tree, STTransform(pos, rad_2_deg(rotate), scale));
|
||||
add_instance(tree, STTransform(pos, rad_2_deg(rotate), scale));
|
||||
}
|
||||
}
|
||||
in >> os_filename;
|
||||
@ -664,19 +666,19 @@ snap_to_terrain() {
|
||||
int num_instances = instance_list->get_num_instances();
|
||||
if (_terrain != (STTerrain *)NULL) {
|
||||
for (int i = 0; i < num_instances; ++i) {
|
||||
STTransform trans = instance_list->get_instance(i);
|
||||
LPoint3f pos = trans.get_pos();
|
||||
pos[2] = _terrain->get_height(pos[0], pos[1]);
|
||||
trans.set_pos(pos);
|
||||
instance_list->set_instance(i, trans);
|
||||
STTransform trans = instance_list->get_instance(i);
|
||||
LPoint3f pos = trans.get_pos();
|
||||
pos[2] = _terrain->get_height(pos[0], pos[1]);
|
||||
trans.set_pos(pos);
|
||||
instance_list->set_instance(i, trans);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num_instances; ++i) {
|
||||
STTransform trans = instance_list->get_instance(i);
|
||||
LPoint3f pos = trans.get_pos();
|
||||
pos[2] = 0.0f;
|
||||
trans.set_pos(pos);
|
||||
instance_list->set_instance(i, trans);
|
||||
STTransform trans = instance_list->get_instance(i);
|
||||
LPoint3f pos = trans.get_pos();
|
||||
pos[2] = 0.0f;
|
||||
trans.set_pos(pos);
|
||||
instance_list->set_instance(i, trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -746,12 +748,24 @@ reload_config() {
|
||||
|
||||
_terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
|
||||
_terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
|
||||
speedtree_max_num_visible_cells);
|
||||
speedtree_max_num_visible_cells);
|
||||
_visible_terrain.Reserve(speedtree_max_num_visible_cells);
|
||||
|
||||
_needs_repopulate = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::set_wind
|
||||
// Access: Published
|
||||
// Description: Specifies the overall wind strength and direction.
|
||||
// Gusts are controlled internally.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SpeedTreeNode::
|
||||
set_wind(double strength, const LVector3f &direction) {
|
||||
_forest_render.SetGlobalWindStrength(strength);
|
||||
_forest_render.SetGlobalWindDirection(SpeedTree::Vec3(direction[0], direction[1], direction[2]));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SpeedTreeNode::authorize
|
||||
// Access: Published, Static
|
||||
@ -770,10 +784,10 @@ authorize(const string &license) {
|
||||
SpeedTree::CCore::Authorize(license.c_str());
|
||||
} else {
|
||||
if (!speedtree_license.empty()) {
|
||||
SpeedTree::CCore::Authorize(speedtree_license.c_str());
|
||||
SpeedTree::CCore::Authorize(speedtree_license.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_authorized = SpeedTree::CCore::IsAuthorized();
|
||||
|
||||
SpeedTree::CCore::SetTextureFlip(true);
|
||||
@ -791,13 +805,14 @@ SpeedTreeNode::
|
||||
SpeedTreeNode(const SpeedTreeNode ©) :
|
||||
PandaNode(copy),
|
||||
_os_shaders_dir(copy._os_shaders_dir),
|
||||
_shadow_infos(copy._shadow_infos)
|
||||
_shadow_infos(copy._shadow_infos),
|
||||
#ifdef ST_DELETE_FOREST_HACK
|
||||
// Early versions of SpeedTree don't destruct unused CForestRender
|
||||
// objects correctly. To avoid crashes, we have to leak these
|
||||
// things.
|
||||
, _forest_render(*(new SpeedTree::CForestRender))
|
||||
_forest_render(*(new SpeedTree::CForestRender)),
|
||||
#endif
|
||||
_time_delta(copy._time_delta)
|
||||
{
|
||||
init_node();
|
||||
|
||||
@ -807,7 +822,7 @@ SpeedTreeNode(const SpeedTreeNode ©) :
|
||||
// No way to copy these parameters, so we just re-assign them.
|
||||
_terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy);
|
||||
_terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS,
|
||||
speedtree_max_num_visible_cells);
|
||||
speedtree_max_num_visible_cells);
|
||||
_visible_terrain.Reserve(speedtree_max_num_visible_cells);
|
||||
|
||||
Trees::const_iterator ti;
|
||||
@ -816,7 +831,7 @@ SpeedTreeNode(const SpeedTreeNode ©) :
|
||||
const STTree *tree = instance_list->get_tree();
|
||||
if (!_forest_render.RegisterTree((SpeedTree::CTree *)tree->get_tree())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to register tree " << tree->get_fullpath() << "\n";
|
||||
<< "Failed to register tree " << tree->get_fullpath() << "\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
|
||||
@ -916,8 +931,8 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
STInstances &instances = instance_list->_instances;
|
||||
STInstances::iterator sti;
|
||||
for (sti = instances.begin(); sti != instances.end(); ++sti) {
|
||||
STTransform orig_transform = *sti;
|
||||
(*sti) = orig_transform * xform;
|
||||
STTransform orig_transform = *sti;
|
||||
(*sti) = orig_transform * xform;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -963,7 +978,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||
}
|
||||
|
||||
ClockObject *clock = ClockObject::get_global_clock();
|
||||
_forest_render.SetGlobalTime(clock->get_frame_time());
|
||||
_forest_render.SetGlobalTime(clock->get_frame_time() + _time_delta + _global_time_delta);
|
||||
_forest_render.AdvanceGlobalWind();
|
||||
|
||||
// Compute the modelview and camera transforms, to pass to the
|
||||
@ -980,9 +995,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||
lens->get_projection_mat();
|
||||
|
||||
_view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]),
|
||||
SpeedTree::Mat4x4(projection_mat.get_data()),
|
||||
SpeedTree::Mat4x4(modelview_mat.get_data()),
|
||||
lens->get_near(), lens->get_far());
|
||||
SpeedTree::Mat4x4(projection_mat.get_data()),
|
||||
SpeedTree::Mat4x4(modelview_mat.get_data()),
|
||||
lens->get_near(), lens->get_far());
|
||||
|
||||
// Convert the render state to SpeedTree's input.
|
||||
const RenderState *state = data._state;
|
||||
@ -1012,17 +1027,17 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||
for (int i = 0; i < la->get_num_on_lights(); ++i) {
|
||||
NodePath light = la->get_on_light(i);
|
||||
if (!light.is_empty() && light.node()->is_of_type(DirectionalLight::get_class_type())) {
|
||||
// A directional light.
|
||||
DirectionalLight *light_obj = DCAST(DirectionalLight, light.node());
|
||||
if (dlight == NULL || light_obj->get_priority() > dlight->get_priority()) {
|
||||
// Here's the most important directional light.
|
||||
dlight = light_obj;
|
||||
dlight_np = light;
|
||||
}
|
||||
// A directional light.
|
||||
DirectionalLight *light_obj = DCAST(DirectionalLight, light.node());
|
||||
if (dlight == NULL || light_obj->get_priority() > dlight->get_priority()) {
|
||||
// Here's the most important directional light.
|
||||
dlight = light_obj;
|
||||
dlight_np = light;
|
||||
}
|
||||
} else if (!light.is_empty() && light.node()->is_of_type(AmbientLight::get_class_type())) {
|
||||
// An ambient light. We keep the color only.
|
||||
AmbientLight *light_obj = DCAST(AmbientLight, light.node());
|
||||
ambient_color += light_obj->get_color();
|
||||
// An ambient light. We keep the color only.
|
||||
AmbientLight *light_obj = DCAST(AmbientLight, light.node());
|
||||
ambient_color += light_obj->get_color();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1105,9 +1120,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
||||
// SpeedTree to render the forest during the actual draw.
|
||||
CullableObject *object =
|
||||
new CullableObject(NULL, data._state,
|
||||
TransformState::make_identity(),
|
||||
TransformState::make_identity(),
|
||||
trav->get_gsg());
|
||||
TransformState::make_identity(),
|
||||
TransformState::make_identity(),
|
||||
trav->get_gsg());
|
||||
object->set_draw_callback(new DrawCallback(this));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
@ -1171,7 +1186,7 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
|
||||
const SpeedTree::Vec3 &emin = extents.Min();
|
||||
const SpeedTree::Vec3 &emax = extents.Max();
|
||||
internal_bounds = new BoundingBox(LPoint3f(emin[0], emin[1], emin[2]),
|
||||
LPoint3f(emax[0], emax[1], emax[2]));
|
||||
LPoint3f(emax[0], emax[1], emax[2]));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1277,10 +1292,13 @@ init_node() {
|
||||
}
|
||||
|
||||
_forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS,
|
||||
speedtree_max_num_visible_cells);
|
||||
speedtree_max_num_visible_cells);
|
||||
|
||||
_forest_render.SetCullCellSize(speedtree_cull_cell_size);
|
||||
|
||||
// Doesn't appear to be necessary to call this explicitly.
|
||||
//_forest_render.EnableWind(true);
|
||||
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
@ -1291,7 +1309,7 @@ init_node() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SpeedTreeNode::
|
||||
r_add_instances(PandaNode *node, const TransformState *transform,
|
||||
Thread *current_thread) {
|
||||
Thread *current_thread) {
|
||||
if (node->is_of_type(SpeedTreeNode::get_class_type()) && node != this) {
|
||||
SpeedTreeNode *other = DCAST(SpeedTreeNode, node);
|
||||
add_instances_from(other, transform);
|
||||
@ -1331,8 +1349,8 @@ repopulate() {
|
||||
|
||||
if (!_forest_render.AddInstances(tree->get_tree(), &instances[0], instances.size())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to add " << instances.size()
|
||||
<< " instances for " << *tree << "\n";
|
||||
<< "Failed to add " << instances.size()
|
||||
<< " instances for " << *tree << "\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
}
|
||||
@ -1361,10 +1379,10 @@ repopulate() {
|
||||
}
|
||||
|
||||
_visible_trees.Reserve(_forest_render.GetBaseTrees(),
|
||||
_forest_render.GetBaseTrees().size(),
|
||||
speedtree_max_num_visible_cells,
|
||||
max_instances_by_cell,
|
||||
speedtree_horizontal_billboards);
|
||||
_forest_render.GetBaseTrees().size(),
|
||||
speedtree_max_num_visible_cells,
|
||||
max_instances_by_cell,
|
||||
speedtree_horizontal_billboards);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1385,7 +1403,7 @@ update_terrain_cells() {
|
||||
// A temporary vertex data object for populating terrain.
|
||||
PT(GeomVertexData) vertex_data =
|
||||
new GeomVertexData("terrain", _terrain->get_vertex_format(),
|
||||
GeomEnums::UH_static);
|
||||
GeomEnums::UH_static);
|
||||
int num_vertices = num_tile_res * num_tile_res;
|
||||
vertex_data->set_num_rows(num_vertices);
|
||||
size_t num_bytes = vertex_data->get_array(0)->get_data_size_bytes();
|
||||
@ -1399,8 +1417,8 @@ update_terrain_cells() {
|
||||
//cerr << "populating cell " << cell_xi << " " << cell_yi << "\n";
|
||||
|
||||
_terrain->fill_vertices(vertex_data,
|
||||
cell_xi * cell_size, cell_yi * cell_size,
|
||||
cell_size, num_tile_res);
|
||||
cell_xi * cell_size, cell_yi * cell_size,
|
||||
cell_size, num_tile_res);
|
||||
|
||||
const GeomVertexArrayData *array_data = vertex_data->get_array(0);
|
||||
CPT(GeomVertexArrayDataHandle) handle = array_data->get_handle();
|
||||
@ -1502,7 +1520,7 @@ draw_callback(CallbackData *data) {
|
||||
|
||||
if (!terrain) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to render terrain\n";
|
||||
<< "Failed to render terrain\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
|
||||
// Clear the terrain so we don't keep spamming error messages.
|
||||
@ -1525,11 +1543,16 @@ draw_callback(CallbackData *data) {
|
||||
bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD);
|
||||
bool leaf_cards = _forest_render.RenderLeafCards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
|
||||
bool billboards = _forest_render.RenderBillboards(_visible_trees, SpeedTree::RENDER_PASS_STANDARD, _view);
|
||||
|
||||
// Sometimes billboards comes back false, particularly if wind is
|
||||
// disabled; but the billboards appear to have been rendered
|
||||
// successfully. Weird. Just removing this test from the
|
||||
// condition.
|
||||
|
||||
if (!branches || !fronds || !leaf_meshes || !leaf_cards || !billboards) {
|
||||
if (!branches || !fronds || !leaf_meshes || !leaf_cards /* || !billboards */) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to render forest completely: "
|
||||
<< branches << " " << fronds << " " << leaf_meshes << " " << leaf_cards << " " << billboards << "\n";
|
||||
<< "Failed to render forest completely: "
|
||||
<< branches << " " << fronds << " " << leaf_meshes << " " << leaf_cards << " " << billboards << "\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
}
|
||||
@ -1624,7 +1647,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
|
||||
GLenum err = glewInit();
|
||||
if (err != GLEW_OK) {
|
||||
speedtree_cat.error()
|
||||
<< "GLEW initialization failed: %s\n", glewGetErrorString(err);
|
||||
<< "GLEW initialization failed: %s\n", glewGetErrorString(err);
|
||||
// Can't proceed without GLEW.
|
||||
_is_valid = false;
|
||||
return;
|
||||
@ -1634,7 +1657,7 @@ setup_for_render(GraphicsStateGuardian *gsg) {
|
||||
// requires it.
|
||||
if (!GLEW_VERSION_2_0) {
|
||||
speedtree_cat.error()
|
||||
<< "The SpeedTree OpenGL implementation requires OpenGL 2.0 or better to run; this system has version " << glGetString(GL_VERSION) << "\n";
|
||||
<< "The SpeedTree OpenGL implementation requires OpenGL 2.0 or better to run; this system has version " << glGetString(GL_VERSION) << "\n";
|
||||
_is_valid = false;
|
||||
return;
|
||||
}
|
||||
@ -1659,47 +1682,47 @@ setup_for_render(GraphicsStateGuardian *gsg) {
|
||||
const STTree *tree = instance_list->get_tree();
|
||||
const STInstances &instances = instance_list->_instances;
|
||||
if (instances.empty()) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
int max_instances = 2;
|
||||
SpeedTree::CMap<const SpeedTree::CTree*, SpeedTree::st_int32>::const_iterator si;
|
||||
si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree());
|
||||
if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) {
|
||||
max_instances = max(max_instances, (int)si->second);
|
||||
max_instances = max(max_instances, (int)si->second);
|
||||
}
|
||||
|
||||
// Get the speedtree-textures-dir to pass for initialization.
|
||||
string os_textures_dir;
|
||||
if (!speedtree_textures_dir.empty()) {
|
||||
os_textures_dir = speedtree_textures_dir.get_value().to_os_specific();
|
||||
// Ensure the path ends with a terminal slash; SpeedTree requires this.
|
||||
os_textures_dir = speedtree_textures_dir.get_value().to_os_specific();
|
||||
// Ensure the path ends with a terminal slash; SpeedTree requires this.
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '\\') {
|
||||
os_textures_dir += "\\";
|
||||
}
|
||||
if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '\\') {
|
||||
os_textures_dir += "\\";
|
||||
}
|
||||
#else
|
||||
if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '/') {
|
||||
os_textures_dir += "/";
|
||||
}
|
||||
if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '/') {
|
||||
os_textures_dir += "/";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(),
|
||||
max_instances, speedtree_horizontal_billboards,
|
||||
os_textures_dir.c_str())) {
|
||||
if (speedtree_cat.is_debug()) {
|
||||
speedtree_cat.debug()
|
||||
<< "Failed to init tree graphics for " << *tree << "\n";
|
||||
write_error(speedtree_cat.debug());
|
||||
}
|
||||
max_instances, speedtree_horizontal_billboards,
|
||||
os_textures_dir.c_str())) {
|
||||
if (speedtree_cat.is_debug()) {
|
||||
speedtree_cat.debug()
|
||||
<< "Failed to init tree graphics for " << *tree << "\n";
|
||||
write_error(speedtree_cat.debug());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init overall graphics
|
||||
if (!_forest_render.InitGraphics(false)) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to init graphics\n";
|
||||
<< "Failed to init graphics\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
_is_valid = false;
|
||||
return;
|
||||
@ -1713,12 +1736,12 @@ setup_for_render(GraphicsStateGuardian *gsg) {
|
||||
if (has_terrain()) {
|
||||
// Now initialize the terrain.
|
||||
if (!_terrain_render.Init(speedtree_terrain_num_lods,
|
||||
speedtree_terrain_resolution,
|
||||
speedtree_terrain_cell_size,
|
||||
_terrain->get_st_vertex_format())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to init terrain\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
speedtree_terrain_resolution,
|
||||
speedtree_terrain_cell_size,
|
||||
_terrain->get_st_vertex_format())) {
|
||||
speedtree_cat.warning()
|
||||
<< "Failed to init terrain\n";
|
||||
write_error(speedtree_cat.warning());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1757,8 +1780,8 @@ cull_forest() {
|
||||
SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull;
|
||||
|
||||
_forest_render.ComputeLightView
|
||||
(_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi,
|
||||
light_view, 0.0f);
|
||||
(_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi,
|
||||
light_view, 0.0f);
|
||||
|
||||
light_view.SetLodRefPoint(_view.GetCameraPos());
|
||||
_forest_render.CullAndComputeLOD(light_view, light_cull, false);
|
||||
@ -1949,7 +1972,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
if (!srt_np.is_empty()) {
|
||||
SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node());
|
||||
if (srt_node->get_num_trees() >= 1) {
|
||||
_tree = (STTree *)srt_node->get_tree(0);
|
||||
_tree = (STTree *)srt_node->get_tree(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,13 @@ PUBLISHED:
|
||||
|
||||
void reload_config();
|
||||
|
||||
void set_wind(double strength, const LVector3f &direction);
|
||||
|
||||
INLINE void set_time_delta(double delta);
|
||||
INLINE double get_time_delta() const;
|
||||
INLINE static void set_global_time_delta(double delta);
|
||||
INLINE static double get_global_time_delta();
|
||||
|
||||
static bool authorize(const string &license = "");
|
||||
|
||||
public:
|
||||
@ -248,6 +255,9 @@ private:
|
||||
typedef pvector<ShadowInfo> ShadowInfos;
|
||||
ShadowInfos _shadow_infos;
|
||||
|
||||
double _time_delta;
|
||||
static double _global_time_delta;
|
||||
|
||||
static bool _authorized;
|
||||
static bool _done_first_init;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user