From fd8369142a291a473e8d1587ad0d7fcc252b6ad5 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Wed, 6 Feb 2013 21:53:57 +0000 Subject: [PATCH] Building performance improvements. Use sensible LoD range of 10km and gradual fade-out to 20km rather than fixed 20km+ LoD range. Also make deeper quad-tree to make culling easier. --- simgear/scene/material/mat.cxx | 2 ++ simgear/scene/material/mat.hxx | 4 ++++ simgear/scene/tgdb/SGBuildingBin.cxx | 13 +++++++------ simgear/scene/tgdb/SGBuildingBin.hxx | 29 +++++++++++++++++++--------- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 359657e5..65d1401d 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -320,6 +320,8 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, building_large_max_width = props->getFloatValue("building-large-max-width-m", 75.0); building_large_min_depth = props->getFloatValue("building-large-min-depth-m", 50.0); building_large_max_depth = props->getFloatValue("building-large-max-depth-m", 75.0); + + building_range = props->getDoubleValue("building-range-m", 10000.0); cos_object_max_density_slope_angle = cos(props->getFloatValue("object-max-density-angle-deg", 20.0) * osg::PI/180.0); cos_object_zero_density_slope_angle = cos(props->getFloatValue("object-zero-density-angle-deg", 30.0) * osg::PI/180.0); diff --git a/simgear/scene/material/mat.hxx b/simgear/scene/material/mat.hxx index 1959cfff..7d03b577 100644 --- a/simgear/scene/material/mat.hxx +++ b/simgear/scene/material/mat.hxx @@ -211,6 +211,8 @@ public: inline double get_building_large_min_depth () const { return building_large_min_depth; } inline double get_building_large_max_depth () const { return building_large_max_depth; } + inline double get_building_range () const { return building_range; } + inline double get_cos_object_max_density_slope_angle () const { return cos_object_max_density_slope_angle; } inline double get_cos_object_zero_density_slope_angle () const { return cos_object_zero_density_slope_angle; } @@ -415,6 +417,8 @@ private: double building_large_min_depth; double building_large_max_depth; + double building_range; + // Cosine of the angle of maximum and zero density, // used to stop buildings and random objects from being // created on too steep a slope. diff --git a/simgear/scene/tgdb/SGBuildingBin.cxx b/simgear/scene/tgdb/SGBuildingBin.cxx index 7d5e4861..8a29f35b 100644 --- a/simgear/scene/tgdb/SGBuildingBin.cxx +++ b/simgear/scene/tgdb/SGBuildingBin.cxx @@ -64,7 +64,6 @@ namespace simgear typedef std::map > BuildingStateSetMap; static BuildingStateSetMap statesetmap; -static int numBuildings; typedef std::map > EffectMap; static EffectMap buildingEffectMap; @@ -136,6 +135,8 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const smallBuildingFraction = mat->get_building_small_fraction(); mediumBuildingFraction = mat->get_building_medium_fraction(); + buildingRange = mat->get_building_range(); + SG_LOG(SG_TERRAIN, SG_DEBUG, "Building fractions " << smallBuildingFraction << " " << mediumBuildingFraction); @@ -753,10 +754,11 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const for (int i = 0; i < 3; i++) { + // Create a quad tree. Only small and medium buildings are faded out. BuildingGeometryQuadtree quadbuilding(GetBuildingCoord(), AddBuildingLeafObject(), SG_BUILDING_QUAD_TREE_DEPTH, - MakeBuildingLeaf(20000.0, effect)); + MakeBuildingLeaf(buildingRange, effect, (i != 2))); // Transform building positions from the "geocentric" positions we // get from the scenery polys into the local Z-up coordinate @@ -768,8 +770,8 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const BuildingInstanceTransformer(transInv)); quadbuilding.buildQuadTree(rotatedBuildings.begin(), rotatedBuildings.end()); - for (size_t i = 0; i < quadbuilding.getRoot()->getNumChildren(); ++i) - group->addChild(quadbuilding.getRoot()->getChild(i)); + for (size_t j = 0; j < quadbuilding.getRoot()->getNumChildren(); ++j) + group->addChild(quadbuilding.getRoot()->getChild(j)); } return group; @@ -826,10 +828,9 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const MatrixTransform* mt = new MatrixTransform(transform); SGBuildingBin* bin = NULL; - + BOOST_FOREACH(bin, buildings) { - numBuildings = numBuildings + bin->getNumBuildings(); ref_ptr group = bin->createBuildingsGroup(transInv, options); for (size_t i = 0; i < group->getNumChildren(); ++i) diff --git a/simgear/scene/tgdb/SGBuildingBin.hxx b/simgear/scene/tgdb/SGBuildingBin.hxx index a6d01f34..43a4fcd5 100644 --- a/simgear/scene/tgdb/SGBuildingBin.hxx +++ b/simgear/scene/tgdb/SGBuildingBin.hxx @@ -45,7 +45,7 @@ #include #include -#define SG_BUILDING_QUAD_TREE_DEPTH 2 +#define SG_BUILDING_QUAD_TREE_DEPTH 4 #define SG_BUILDING_FADE_OUT_LEVELS 4 using namespace osg; @@ -118,6 +118,9 @@ private: float mediumBuildingMaxDepth; float largeBuildingMaxDepth; + // Visibility range for buildings + float buildingRange; + // Shared geometries of the building set ref_ptr smallSharedGeometry; ref_ptr mediumSharedGeometry; @@ -191,30 +194,38 @@ public: // Helper classes for creating the quad tree struct MakeBuildingLeaf { - MakeBuildingLeaf(float range, Effect* effect) : - _range(range), _effect(effect) {} + MakeBuildingLeaf(float range, Effect* effect, bool fade) : + _range(range), _effect(effect), _fade_out(fade) {} MakeBuildingLeaf(const MakeBuildingLeaf& rhs) : - _range(rhs._range), _effect(rhs._effect) + _range(rhs._range), _effect(rhs._effect), _fade_out(rhs._fade_out) {} LOD* operator() () const { LOD* result = new LOD; - // Create a series of LOD nodes so trees cover decreases slightly - // gradually with distance from _range to 2*_range - for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++) - { + if (_fade_out) { + // Create a series of LOD nodes so buidling cover decreases + // gradually with distance from _range to 2*_range + for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++) + { + EffectGeode* geode = new EffectGeode; + geode->setEffect(_effect.get()); + result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0))); + } + } else { + // No fade-out, so all are visible for 2X range EffectGeode* geode = new EffectGeode; geode->setEffect(_effect.get()); - result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0))); + result->addChild(geode, 0, 2.0 * _range); } return result; } float _range; ref_ptr _effect; + bool _fade_out; }; struct AddBuildingLeafObject