请问osg pagelod如何使用

本人OSG刚学习,想用pagelod将四个不同分辨率、同一地区的OSGB数据加载进来并生成索引,利用到眼距离不同,分别加载不同分辨率数据,但运行结果不对,求各位指点


```c++
void createObliqueIndexes(std::string fileDir)
{
    //string dataDir = fileDir + "/Data";
    string dataDir = fileDir;

    osg::ref_ptr group = new osg::Group();
    vector<string> subDirs;
    findDir(dataDir, subDirs);
        for (size_t i = 0; i < subDirs.size(); i++)
    {
        string name = DirOrPathGetName(subDirs[i]);

        string path = dataDir + "/" + subDirs[i];

        osg::ref_ptr node = osgDB::readNodeFile(path);

        osg::ref_ptr lod = new osg::PagedLOD();

        auto bs = node->getBound();
        auto c = bs.center();    //中心
        auto r = bs.radius();    //半径
        lod->setCenter(c);
        lod->setRadius(r);
        lod->setRangeMode(osg::LOD::RangeMode::DISTANCE_FROM_EYE_POINT);    
        osg::ref_ptr geode = new osg::Geode;
        geode->getOrCreateStateSet();
        lod->addChild(geode.get());

        std::string relativeFilePath = subDirs[i];  //相对路径

        if (0 == i)
        {
            lod->setFileName(0, "");
            lod->setFileName(1, relativeFilePath);

            lod->setRange(0, 0, 1.0);            //第一层不可见
            lod->setRange(1, 100.0, 200.0);
        }

        if (1 == i)
        {
            //lod->setFileName(0, "");
            lod->setFileName(2, relativeFilePath);

            //lod->setRange(0, 0, 1.0);            //第一层不可见
            lod->setRange(2, 200.0, 300.0);
        }

        if (2 == i)
        {
            //lod->setFileName(0, "");
            lod->setFileName(3, relativeFilePath);

            //lod->setRange(0, 0, 1.0);            //第一层不可见
            lod->setRange(3, 300.0, 400.0);
        }

        if (3 == i)
        {
            //lod->setFileName(0, "");
            lod->setFileName(4, relativeFilePath);

            //lod->setRange(0, 0, 1.0);            //第一层不可见
            lod->setRange(4, 400.0, FLT_MAX);
        }

        lod->setDatabasePath("");

        group->addChild(lod);
    }
    std::string outputLodFile = fileDir + "/Data.osgb";
    osgDB::writeNodeFile(*group, outputLodFile);

}


```

osg::PagedLOD是一个OpenSceneGraph中的节点类型,在场景图中表示一个细节程度逐步增高的场景对象。需要注意的是,PagedLOD节点并不直接包含任何几何体或者几何体文件,它实际上是一个分层节点,内部包含一些细节更强的子节点,这些子节点决定了场景的细节程度。

PagedLOD节点的使用通常有两种方式,一种是通过初始化函数 osg::PagedLOD::addRange() 来将不同级别的细节添加到节点中,另一种是通过调用 osgDB::Registry::instance()->readNodeFile() 来从磁盘上加载场景数据。以下是一个简单的例子:

osg::ref_ptr pagedLOD = new osg::PagedLOD;
pagedLOD->setFileName(0, "path-to-low-detail.osg");
pagedLOD->setFileName(1, "path-to-medium-detail.osg");
pagedLOD->setFileName(2, "path-to-high-detail.osg");
pagedLOD->addRange(0, 1000.0f);
pagedLOD->addRange(1000.0f, 2000.0f);
pagedLOD->addRange(2000.0f, FLT_MAX);

在上面的例子中,我们创建了一个PagedLOD节点,并通过设置文件名和范围,为它添加了三个子节点,分别代表场景的三个细节级别。其中,每一个子节点对应一个文件,因此可以通过这种方式将不同细节级别的场景数据存储在不同的文件中。而每个子节点在何时显示,是由节点的RangeList属性控制的。在上面的例子中,我们将前三个参数依次传入addRange()函数,表示在每个距离范围内显示对应的子节点。实际上,第一个参数表示显示该子节点的最小距离,第二个参数表示显示该子节点的最大距离。如果一个点距离场景中的PagedLOD节点小于所有子节点的最小距离,则显示0级子节点;如果距离场景的距离大于等于0级子节点的最小距离,但小于1级子节点的最小距离,则显示1级子节点,以此类推。

除了通过添加RangeList属性来控制什么时候显示哪个子节点,还可以通过设置DelayLODReachedReadingPolicy属性来控制触发场景节点细节的渲染时机,例如在时间片段内、帧更新后等等。

osg::PagedLOD节点使用时需要注意以下几点:

  1. 需要将PagedLOD节点插入正确的场景图节点树中,否则无法正常渲染。
  2. 需要设置节点的RangeList属性,否则无法控制什么时候显示哪个子节点。
  3. 需要将节点的子节点内容存储在正确的文件中,并且文件格式需要符合OpenSceneGraph约定。
  4. 需要在需要查看不同细节级别时调整触发细节渲染的DelayLODReachedReadingPolicy属性。

从代码上看,您的PagedLOD的设置似乎是正确的,但是可能存在其他原因导致加载出来的结果不正确,比如数据本身的问题(如坐标系不正确、数据缺失等)、加载方式不正确等等。

建议您检查一下以下几个方面:

1. 确认数据文件的坐标系是否正确,如果坐标系不正确可能会导致数据显示位置不正确。

2. 确认数据文件是否缺失或者损坏,可以尝试单独加载某一个数据文件来检查其是否能够正常加载和显示。

3. 确认加载方式是否正确,可以尝试使用其他加载方式,例如直接加载单个数据文件,来检查是否存在问题。

4. 可以尝试在代码中增加调试信息,输出PagedLOD的设置参数和实际加载的文件名,来检查是否与预期相符。

希望以上建议能够帮助您找到问题所在,如有更多问题,请随时追问。