1
0
Fork 0

LOD ranges rework.

Rework the LOD ranges.

1. The scenery ranges are now deltas (avoids overlapping values)
2. The AI/MP pixel mode now has a default radius that is 20 for Aircraft, 200 for ships, 350 for carriers. This is a simple constant in a virtual function.
3. Added the ability to set the AI/MP ranges equal which means use the low detail model.
4. Changed high detail only to be indicated by a -ve number in maxRangeDetail
5. Re-ordered the range list to go from lowest detail at [0] to highest detail at the end. This is because OSG always loads the models starting from zero on the assumption that the detail increases with the index.

This fixes the pixel mode, which previously would use the radius of the parent which would be confusingly large, and unrelated to the actual size of the model. With the simple defaults that we have the pixel values set in the ranges won't exactly match the rendered size of the model on screen, but it will be a lot closer and more importantly meaningful.
This commit is contained in:
Richard Harrison 2018-10-30 20:10:30 +01:00
parent 04eb045931
commit c99ea20883
8 changed files with 83 additions and 31 deletions

View file

@ -310,7 +310,7 @@ void FGAIBase::updateInterior()
if(d2 <= _maxRangeInterior){ // if the AI is in-range we load the interior
_interior = SGModelLib::loadPagedModel(_modeldata->getInteriorPath(), props, _modeldata);
if(_interior.valid()){
_interior->setRange(0, 0.0, _maxRangeInterior);
_interior->setRange(modelHighDetailIndex, 0.0, _maxRangeInterior);
aip.add(_interior.get());
_modeldata->setInteriorLoaded(true);
SG_LOG(SG_AI, SG_INFO, "AIBase: Loaded interior model " << _interior->getName());
@ -322,25 +322,54 @@ void FGAIBase::updateInterior()
/** update LOD properties of the model */
void FGAIBase::updateLOD()
{
double maxRangeDetail = fgGetDouble("/sim/rendering/static-lod/ai-detailed", 3000.0);
double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/ai-bare", 10000.0);
double maxRangeDetail = fgGetDouble("/sim/rendering/static-lod/aimp-detailed", 3000.0);
double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/aimp-bare", 10000.0);
_maxRangeInterior = fgGetDouble("/sim/rendering/static-lod/ai-interior", 50.0);
_maxRangeInterior = fgGetDouble("/sim/rendering/static-lod/aimp-interior", 50.0);
if (_model.valid())
{
if( maxRangeDetail == 0.0 )
bool pixel_mode = !fgGetBool("/sim/rendering/static-lod/aimp-range-mode-distance", false);
if (pixel_mode)
_model->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN);
else
_model->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
if (maxRangeDetail < 0) // disable the bare model
{
// Disable LOD. The First entry in the LOD node is the most detailed
// Disable LOD. The first entry in the LOD node is the most detailed
// so use that.
_model->setRange(0, 0.0, FLT_MAX);
if (_model->getNumFileNames() == 2) {
_model->setRange(1, FLT_MAX, FLT_MAX);
_model->setRange(modelHighDetailIndex, 0.0, FLT_MAX); // all ranges.
_model->setRange(modelLowDetailIndex, FLT_MAX, FLT_MAX);
}
else
_model->setRange(modelHighDetailIndex , 0.0, FLT_MAX); // all ranges.
}
else if (maxRangeBare == maxRangeDetail) // only use the bare model
{
double start_range, end_range;
if (pixel_mode) {
// pixels, so the start of the range is when we want this to be drawn. this should
// be zero pixels to ensure that something is visible.
start_range = maxRangeDetail;
end_range = FLT_MAX;
}
else {
// meters; so start from 0 end and at the max range.
start_range = maxRangeDetail;
end_range = FLT_MAX;
}
if (_model->getNumFileNames() == 2) {
_model->setRange(modelHighDetailIndex , FLT_MAX, FLT_MAX);
_model->setRange(modelLowDetailIndex , start_range, end_range);
}
else
_model->setRange(modelHighDetailIndex , start_range, end_range);
}
else
{
if( fgGetBool("/sim/rendering/static-lod/ai-range-mode-pixel", false ) )
if(pixel_mode)
{
/* In pixel size mode, the range sense is reversed, so we want the
* detailed model [0] to be displayed when the "range" is really
@ -356,21 +385,28 @@ void FGAIBase::updateLOD()
maxRangeBare = maxRangeDetail;
SG_LOG(SG_AI,
SG_WARN,
"/sim/rendering/static-lod/ai-bare greater " <<
"than /sim/rendering/static-lod/ai-detailed when using " <<
"/sim/rendering/static-lod/ai-range-mode-pixel=true. Ignoring ai-bare."
"/sim/rendering/static-lod/aimp-bare greater " <<
"than /sim/rendering/static-lod/aimp-detailed when using " <<
"/sim/rendering/static-lod/aimp-range-mode-distance=false. Ignoring ai-bare."
);
}
_model->setRangeMode( osg::LOD::PIXEL_SIZE_ON_SCREEN );
if (_model->getNumFileNames() == 2) {
_model->setRange(0, maxRangeDetail, 100000 );
_model->setRange(1, maxRangeBare, maxRangeDetail);
/*if (_model->getRadius() < 0)
{
osg::BoundingSphere bs = _model->computeBound();
if (bs.radius() > 0) {
_model->setRadius(bs.radius());
_model->setCenterMode(osg::LOD::CenterMode::USER_DEFINED_CENTER);
}
}*/
_model->setRange(modelHighDetailIndex , maxRangeDetail, 100000); // most detailed
_model->setRange(modelLowDetailIndex , maxRangeBare, maxRangeDetail); // least detailed
} else {
/* If we have only one LoD for this model, then we want to
* display it from the smallest pixel value
*/
_model->setRange(0, min(maxRangeBare, maxRangeDetail), 100000 );
_model->setRange(modelHighDetailIndex , min(maxRangeBare, maxRangeDetail), 100000 );
}
} else {
/* In non-pixel range mode we're dealing with straight distance.
@ -384,20 +420,19 @@ void FGAIBase::updateLOD()
maxRangeBare = maxRangeDetail;
SG_LOG(SG_AI,
SG_WARN,
"/sim/rendering/static-lod/ai-bare less than " <<
"than /sim/rendering/static-lod/ai-detailed. Ignoring ai-bare."
"/sim/rendering/static-lod/aimp-bare less than " <<
"than /sim/rendering/static-lod/aimp-detailed. Ignoring ai-bare."
);
}
_model->setRangeMode( osg::LOD:: DISTANCE_FROM_EYE_POINT);
if (_model->getNumFileNames() == 2) {
_model->setRange(0, 0, maxRangeDetail);
_model->setRange(1, maxRangeDetail, maxRangeBare);
_model->setRange(modelHighDetailIndex , 0, maxRangeDetail); // most detailed
_model->setRange(modelLowDetailIndex , maxRangeDetail, maxRangeDetail+maxRangeBare); // least detailed
} else {
/* If we have only one LoD for this model, then we want to
* display it from whatever range.
*/
_model->setRange(0, 0, max(maxRangeBare, maxRangeDetail));
_model->setRange(modelHighDetailIndex , 0, max(maxRangeBare, maxRangeDetail));
}
}
}
@ -488,11 +523,13 @@ std::vector<std::string> FGAIBase::resolveModelPath(ModelSearchOrder searchOrder
}
// At this point we're looking for a regular model to display at closer range.
// From experimentation it seems to work best if the LODs are in the range list in terms of detail
// from lowest to highest - so insert this at the end.
auto p = simgear::SGModelLib::findDataFile(model_path);
if (!p.empty()) {
_installed = true;
SG_LOG(SG_AI, SG_DEBUG, "Found DATA model " << p);
path_list.insert(path_list.begin(), p);
path_list.insert(path_list.end(), p);
}
}
@ -520,6 +557,7 @@ bool FGAIBase::init(ModelSearchOrder searchOrder)
vector<string> model_list = resolveModelPath(searchOrder);
_model= SGModelLib::loadPagedModel(model_list, props, _modeldata);
_model->setName("AI-model range animation node");
_model->setRadius(getDefaultModelRadius());
updateLOD();
initModel();

View file

@ -55,6 +55,12 @@ public:
FGAIBase(object_type ot, bool enableHot);
virtual ~FGAIBase();
// these depend on the order in which the models are loaded. OSG is a little vague about this, but
// from experimentation it seems to work best if the LODs are in the range list in terms of detail
// from lowest to highest
const int modelLowDetailIndex = 0;
const int modelHighDetailIndex = 1;
virtual void readFromScenario(SGPropertyNode* scFileNode);
enum ModelSearchOrder {
@ -69,7 +75,8 @@ public:
virtual void bind();
virtual void unbind();
virtual void reinit() {}
// default model radius for LOD.
virtual double getDefaultModelRadius() { return 20.0; }
void updateLOD();
void updateInterior();
void setManager(FGAIManager* mgr, SGPropertyNode* p);

View file

@ -48,6 +48,7 @@ public:
void setSign(const string& );
void setDeckAltitude(const double altitude_feet);
void setTACANChannelID(const string &);
virtual double getDefaultModelRadius() { return 350.0; }
virtual void bind();
void UpdateWind ( double dt );

View file

@ -105,9 +105,9 @@ private:
FGAIManager::FGAIManager() :
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
fgGetNode("/sim/rendering/static-lod/aimp-bare", true))),
cb_ai_detailed(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-detailed", true)))
fgGetNode("/sim/rendering/static-lod/aimp-detailed", true)))
{
}

View file

@ -41,6 +41,7 @@ public:
virtual void bind();
virtual void update(double dt);
virtual void reinit();
virtual double getDefaultModelRadius() { return 200.0; }
void setRudder(float r);
void setRoll(double rl);

View file

@ -84,8 +84,8 @@ void FGPgtTerrain::init( osg::Group* terrain ) {
options->setPluginStringData("SimGear::FG_ROOT", globals->get_fg_root().local8BitStr());
options->setPluginStringData("SimGear::BARE_LOD_RANGE", fgGetString("/sim/rendering/static-lod/bare", boost::lexical_cast<string>(SG_OBJECT_RANGE_BARE)));
options->setPluginStringData("SimGear::ROUGH_LOD_RANGE", fgGetString("/sim/rendering/static-lod/rough", boost::lexical_cast<string>(SG_OBJECT_RANGE_ROUGH)));
options->setPluginStringData("SimGear::BARE_LOD_RANGE", fgGetString("/sim/rendering/static-lod/bare-delta", boost::lexical_cast<string>(SG_OBJECT_RANGE_BARE)));
options->setPluginStringData("SimGear::ROUGH_LOD_RANGE", fgGetString("/sim/rendering/static-lod/rough-delta", boost::lexical_cast<string>(SG_OBJECT_RANGE_ROUGH)));
options->setPluginStringData("SimGear::ROUGH_LOD_DETAILED", fgGetString("/sim/rendering/static-lod/detailed", boost::lexical_cast<string>(SG_OBJECT_RANGE_DETAILED)));
options->setPluginStringData("SimGear::RENDER_BUILDING_MESH", fgGetBool("/sim/rendering/building-mesh", false) ? "true" : "false");

View file

@ -116,7 +116,9 @@ FGTileMgr::FGTileMgr():
_terra_sync(NULL),
_listener(NULL),
_visibilityMeters(fgGetNode("/environment/visibility-m", true)),
_maxTileRangeM(fgGetNode("/sim/rendering/static-lod/bare", true)),
_lodDetailed(fgGetNode("/sim/rendering/static-lod/detailed", true)),
_lodRoughDelta(fgGetNode("/sim/rendering/static-lod/rough-delta", true)),
_lodBareDelta(fgGetNode("/sim/rendering/static-lod/bare-delta", true)),
_disableNasalHooks(fgGetNode("/sim/temp/disable-scenery-nasal", true)),
_scenery_loaded(fgGetNode("/sim/sceneryloaded", true)),
_scenery_override(fgGetNode("/sim/sceneryloaded-override", true)),
@ -295,8 +297,11 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
// cout << "tile width = " << tile_width << " tile_height = "
// << tile_height << endl;
// starting with 2018.3 we will use deltas rather than absolutes as it is more intuitive for the user
// and somewhat easier to visualise
double maxTileRange = _lodDetailed->getDoubleValue() + _lodRoughDelta->getDoubleValue() + _lodBareDelta->getDoubleValue();
double tileRangeM = std::min(vis,_maxTileRangeM->getDoubleValue());
double tileRangeM = std::min(vis, maxTileRange);
int xrange = (int)(tileRangeM / tile_width) + 1;
int yrange = (int)(tileRangeM / tile_height) + 1;
if ( xrange < 1 ) { xrange = 1; }

View file

@ -86,7 +86,7 @@ private:
void schedule_tiles_at(const SGGeod& location, double rangeM);
SGPropertyNode_ptr _visibilityMeters;
SGPropertyNode_ptr _maxTileRangeM, _disableNasalHooks;
SGPropertyNode_ptr _lodDetailed, _lodRoughDelta, _lodBareDelta, _disableNasalHooks;
SGPropertyNode_ptr _scenery_loaded, _scenery_override;
osg::ref_ptr<flightgear::SceneryPager> _pager;