Техника использования уровней детализации позволяет отображать один и тот же объект более или менее детально, в зависимости от расстояния от него до наблюдателя. Использование этой техники основано на том простом соображении, что мелкие детали трехмерной модели неразличимы на большом расстоянии, значит нет неообходимости в их прорисовке. С одной стороны этот прием позволяет уменьшить общее количество геометрических примитивов, выводимых в буфер кадра, а с другой - не терять в дальности отображения объектов сцены, что очень полезно при создании больших открытых миров.

OSG предосталяет иструментарий для реализации этого приема через класс osg::LOD, наследуемый от всё того же osg::Group. Этот класс позволяет представить один и тот же объект в нескольких уровнях детализации. Каждый уровень детализации характеризуется минимальной и максимальной дистанцией до наблюдателя, при соблюдении которой происходит переключение отображения объекта в этом уровне детализации.

osg::LOD позволяет задавать данный диапазон сразу при задании дочерней ноды, или позже, применением методы setRange()

osg::ref_ptr<osg::LOD> lodNode = new osg::LOD;
lodNode->addChild(node2, 500.0f, FLT_MAX);
lodNode->addChild(node1);
.
.
.
lodNode->setRange(1, 0.0f, 500.0f);

Продолжаем мучать цессну и проиллюстрируем описанную технику примером

main.h

#ifndef     MAIN_H
#define     MAIN_H

#include    <osg/LOD>
#include    <osgDB/ReadFile>
#include    <osgUtil/Simplifier>
#include    <osgViewer/Viewer>

#endif

main.h

#include    "main.h"

int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    osg::ref_ptr<osg::Node> modelL3 = osgDB::readNodeFile("../data/cessna.osg");

    osg::ref_ptr<osg::Node> modelL2 = dynamic_cast<osg::Node *>(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> modelL1 = dynamic_cast<osg::Node *>(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL));

    osgUtil::Simplifier simplifer;
    simplifer.setSampleRatio(0.5f);
    modelL2->accept(simplifer);

    simplifer.setSampleRatio(0.1f);
    modelL1->accept(simplifer);

    osg::ref_ptr<osg::LOD> root = new osg::LOD;
    root->addChild(modelL1.get(), 200.0f, FLT_MAX);
    root->addChild(modelL2.get(), 50.0f, 200.0f);
    root->addChild(modelL3.get(), 0.0f, 50.0f);

    osgViewer::Viewer viewer;
    viewer.setSceneData(root.get());

    return viewer.run();
}

Для начала загружаем модель

osg::ref_ptr<osg::Node> modelL3 = osgDB::readNodeFile("../data/cessna.osg");

Теперь необходимо сгенерировать несколько (ограничимся для примера двумя) моделек, с более низким уровнем детализации. Для этого скопируем загруженную ноду дважды, применяя методику так называемого “глубокого” копирования класса, для ноды реализуемого методом clone()

osg::ref_ptr<osg::Node> modelL2 = dynamic_cast<osg::Node *>(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL));
osg::ref_ptr<osg::Node> modelL1 = dynamic_cast<osg::Node *>(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL));

Теперь редуцируем геометрию этих моделей, используя класс osgUtil::Simplifer. Степень упрощение модели задается методом setSampleRatio() данного класса - чем меньше передаваемый параметр, тем менее детальной будет модель после применения процедуры редукции

osgUtil::Simplifier simplifer;
simplifer.setSampleRatio(0.5f);
modelL2->accept(simplifer);

simplifer.setSampleRatio(0.1f);
modelL1->accept(simplifer);

Когда у нас есть модельки разного уровня детализации мы можем зарядить их в корневую ноду, созданную как умный указатель на osg::LOD. Для каждого уровня детализации задаем дистанцию отображения этого уровня

osg::ref_ptr<osg::LOD> root = new osg::LOD;
root->addChild(modelL1.get(), 200.0f, FLT_MAX);
root->addChild(modelL2.get(), 50.0f, 200.0f);
root->addChild(modelL3.get(), 0.0f, 50.0f);

Под FLT_MAX понимается в некотором роде “бесконечно” большое расстояние до наблюдателя. После запуска вьювера получаем следующую картину

Уровень детализации 3

Уровень детализации 2

Уровень детализации 1

Видно, как при отдалении камеры от объекта снижается детальность отображаемой геометрии. Применяя этот прием можно добится высокой реалистичности сцены при малом расходе ресурсов.