1
0
Fork 0

Update osg AI model LOD structure

This commit is contained in:
Lars Toenning 2021-11-26 20:34:50 +01:00 committed by Stuart Buchanan
parent b5dd4a8b6b
commit bda359558c
3 changed files with 87 additions and 17 deletions

View file

@ -237,6 +237,9 @@ FGAIBase::removeModel()
aip.clear();
_modeldata = nullptr;
_model = nullptr;
_interior = nullptr;
_high_res = nullptr;
_low_res = nullptr;
// pass it on to the pager, to be be deleted in the pager thread
pSceneryManager->getPager()->queueDeleteRequest(temp);
@ -378,6 +381,7 @@ void FGAIBase::updateInterior()
if (!_modeldata->getInteriorLoaded()) { // interior is not yet load
_interior = SGModelLib::loadPagedModel(_modeldata->getInteriorPath(), props, _modeldata);
_group->addChild(_interior);
if (_interior.valid()) {
bool pixel_mode = !fgGetBool("/sim/rendering/static-lod/aimp-range-mode-distance", false);
if (pixel_mode) {
@ -388,7 +392,6 @@ void FGAIBase::updateInterior()
_interior->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
_interior->setRange(0, 0.0, _maxRangeInterior);
}
aip.add(_interior.get());
_modeldata->setInteriorLoaded(true);
SG_LOG(SG_AI, SG_INFO, "AIBase: Loaded interior model " << _interior->getName());
}
@ -416,23 +419,27 @@ void FGAIBase::updateLOD()
{
// High detail model (only)
// - disables the low detail detail model by setting its visibility from 0 to 0
if (_model->getNumFileNames() == 2) {
if (_high_res.valid()) {
_model->setRange(modelHighDetailIndex, 0.0, FLT_MAX); // all ranges.
_model->setRange(modelLowDetailIndex, 0.0, 0.0); // turn it off
}
else {
_model->setRange(0, 0.0, FLT_MAX); // only one model.
// only having low-res model
_model->setRange(modelLowDetailIndex, 0.0, FLT_MAX); // only having low-res model.
_model->setRange(modelHighDetailIndex, 0.0, 0.0); // only having low-res model.
}
}
else if ((int)maxRangeBare == (int)maxRangeDetail)
{
// low detail model (only)
if (_model->getNumFileNames() == 2) {
if (_low_res.valid()) {
_model->setRange(modelHighDetailIndex, 0, 0); // turn it off
_model->setRange(modelLowDetailIndex, 0, FLT_MAX);
}
else {
_model->setRange(0, 0, FLT_MAX);
// Only having high_res model
_model->setRange(modelHighDetailIndex, 0, FLT_MAX);
_model->setRange(modelLowDetailIndex, 0, 0.0);
}
}
else
@ -459,7 +466,7 @@ void FGAIBase::updateLOD()
);
}
if (_model->getNumFileNames() == 2) {
if (_low_res.valid() && _high_res.valid()) {
/*if (_model->getRadius() < 0)
{
osg::BoundingSphere bs = _model->computeBound();
@ -470,9 +477,14 @@ void FGAIBase::updateLOD()
}*/
_model->setRange(modelHighDetailIndex , maxRangeDetail, FLT_MAX); // most detailed
_model->setRange(modelLowDetailIndex , maxRangeBare, maxRangeDetail); // least detailed
} else {
// we have only one model it obviously will have to be displayed from the smallest value
_model->setRange(0, min(maxRangeBare, maxRangeDetail), FLT_MAX );
} else if (_low_res.valid() && !_high_res.valid()) {
// we have only low_res_model model it obviously will have to be displayed from the smallest value
_model->setRange(modelLowDetailIndex, min(maxRangeBare, maxRangeDetail), FLT_MAX );
_model->setRange(modelHighDetailIndex, 0,0);
} else if (!_low_res.valid() && _high_res.valid()) {
// we have only high_res model it obviously will have to be displayed from the smallest value
_model->setRange(modelHighDetailIndex, min(maxRangeBare, maxRangeDetail), FLT_MAX );
_model->setRange(modelLowDetailIndex, 0,0);
}
} else {
/* In non-pixel range mode we're dealing with straight distance.
@ -491,11 +503,15 @@ void FGAIBase::updateLOD()
}
if (_model->getNumFileNames() == 2) {
if (_low_res.valid() && _high_res.valid()) {
_model->setRange(modelHighDetailIndex , 0, maxRangeDetail); // most detailed
_model->setRange(modelLowDetailIndex , maxRangeDetail, maxRangeDetail+maxRangeBare); // least detailed
} else {
_model->setRange(0, 0, maxRangeBare + maxRangeDetail); // only one model, so display from 0 to the highest value in meters
} else if (_low_res.valid() && !_high_res.valid()) {
_model->setRange(modelLowDetailIndex, 0, maxRangeBare + maxRangeDetail); // only low_res, so display from 0 to the highest value in meters
_model->setRange(modelHighDetailIndex, 0, 0);
} else if (!_low_res.valid() && _high_res.valid()) {
_model->setRange(modelHighDetailIndex, 0, maxRangeBare + maxRangeDetail); // only high_res, so display from 0 to the highest value in meters
_model->setRange(modelLowDetailIndex, 0, 0);
}
}
}
@ -645,8 +661,44 @@ bool FGAIBase::init(ModelSearchOrder searchOrder)
_modeldata->addErrorContext("multiplayer", getCallSign());
}
// Load models
_model = new osg::LOD();
vector<string> model_list = resolveModelPath(searchOrder);
_model= SGModelLib::loadPagedModel(model_list, props, _modeldata);
if(model_list.size() == 1 && _modeldata && _modeldata->hasInteriorPath()) {
// Only one model and interior available (expecting this to be a high_res model)
_low_res = new osg::PagedLOD(); // Dummy node to keep LOD node happy
_model->addChild(_low_res);
_high_res = SGModelLib::loadPagedModel(model_list[0], props, _modeldata);
_group = osg::ref_ptr<osg::Group>(new osg::Group());
_group->addChild(_high_res);
_model->addChild(_group);
} else if (model_list.size() == 1) {
// low_res model only (as we do not have any interior)
_low_res = SGModelLib::loadPagedModel(model_list[0], props, _modeldata);
_model->addChild(_low_res);
_group = osg::ref_ptr<osg::Group>(new osg::Group()); // Dummy node to keep LOD node happy
_model->addChild(_group);
} else {
// high and low-res model
assert(model_list.size() == 2);
_low_res = SGModelLib::loadPagedModel(model_list[0], props, _modeldata);
_model->addChild(_low_res);
_high_res = SGModelLib::loadPagedModel(model_list[1], props, _modeldata);
_group = osg::ref_ptr<osg::Group>(new osg::Group());
_group->addChild(_high_res);
_model->addChild(_group);
}
// Set PagedLODs to MAX Range. The visibility is controlled with the top-level LOD node
if(_high_res.valid()) {
_high_res->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
_high_res->setRange(0, 0, FLT_MAX);
}
if(_low_res.valid()) {
_low_res->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
_low_res->setRange(0, 0, FLT_MAX);
}
_model->setName("AI-model range animation node");
_model->setRadius(getDefaultModelRadius());
@ -1198,11 +1250,20 @@ bool FGAIBase::isValid() const
return !fp || fp->isValidPlan();
}
osg::PagedLOD* FGAIBase::getSceneBranch() const
osg::LOD* FGAIBase::getSceneBranch() const
{
return _model;
}
bool FGAIBase::modelLoaded() const
{
if(_low_res.valid())
return _low_res->getNumChildren() >= 1;
else if (_high_res.valid())
return _high_res->getNumChildren() >= 1;
return false;
}
SGGeod FGAIBase::getGeodPos() const
{
return pos;

View file

@ -147,7 +147,13 @@ public:
double _getCartPosY() const;
double _getCartPosZ() const;
osg::PagedLOD* getSceneBranch() const;
osg::LOD* getSceneBranch() const;
/**
*
* @return true if at least one model (either low_res or high_res) is loaded
*/
bool modelLoaded() const;
void setScenarioPath(const std::string& scenarioPath);
@ -271,7 +277,10 @@ private:
int _refID;
object_type _otype;
bool _initialized = false;
osg::ref_ptr<osg::PagedLOD> _model;
osg::ref_ptr<osg::LOD> _model;
osg::ref_ptr<osg::PagedLOD> _low_res;
osg::ref_ptr<osg::PagedLOD> _high_res;
osg::ref_ptr<osg::Group> _group;
osg::ref_ptr<osg::PagedLOD> _interior;
osg::ref_ptr<FGAIModelData> _modeldata;

View file

@ -402,7 +402,7 @@ static InitPosResult checkCarrierSceneryLoaded(const SGSharedPtr<FGAICarrier> ca
}
// and then wait for the load to actually be synced to the main thread
if (carrierRef->getSceneBranch()->getNumChildren() < 1) {
if (!carrierRef->modelLoaded()) {
return ContinueWaiting;
}