OSG ジオメトリ操作

        シーンは基本的な描画プリミティブで構成され、基本的な描画プリミティブは単純なジオメトリを構成し、単純なジオメトリは複雑なジオメトリを構成し、複雑なジオメトリは最終的に複雑なシーンを構成します。複数のジオメトリを組み合わせると、シーンのレンダリング効率が低下する原因がいくつか考えられます。多くの 3D エンジンでは、最適なレンダリング効率を達成するために、シーンのジオメトリを変更する操作が提供されています。最適なレンダリング効率は理想的な状態にすぎませんが、特定のジオメトリ操作によりレンダリング効率を大幅に向上させることができます。
        OSG では、必要なパフォーマンスとレンダリング効率を得るために、osgUtilライブラリはいくつかの一般的なジオメトリ操作を提供します。これらのジオメトリ操作には、主に osgUtil::Simplifier (単純化)、ostUtil::SmoothingVisitor (法線の生成)、osgUtil ::DelaunayTriangulator が含まれます。 (ドローネ三角形分割ツールの生成) および osgUtil::TriStripVisitor (ストライピング) など。

1. ジオメトリを単純化する

        簡素化されたジオメトリ ( osgUtil::Simplifier ) クラスは osg::NodeVisitor クラスを継承し、ビジターの形式でジオメトリを走査して簡素化します。
        osgUtil::Simplfier クラスによるジオメトリの単純化では、主に 2 つのパラメータを設定する必要があります。つまり、ジオメトリのサンプル比が 1 未満の場合は、ポイントの誤差制限を設定します。ジオメトリのサンプル比が 1 未満の場合は、ポイントの誤差制限を設定します。 1 より大きい場合は、辺の長さ制限を設定しますポイント エラーやエッジの長さを制限することで不要なポイントとエッジを簡素化し、スムージングとストライプ化によってジオメトリをレンダリングしてレンダリング効率を向上させます。また、低レベル モデルの自動生成にも使用できます。一般に、サンプル比が大きいほど単純化は少なくなり、サンプル比が小さいほど単純化は大きくなります。最適化では次の関数を直接呼び出すことができます:
        virtual void apply(osg::Geode &geode);      // リーフ ノードの場合
        void simplify(osg::Geometry &geometry); // ジオメトリを単純化します

        これら 2 つの関数は osg::Node ノードにも使用できますが、インスタンスを関連付けるときは accept() メソッドを使用する必要があります。
        osgUtil::Simplifier は、エッジ崩壊アルゴリズムを使用して簡素化します。
サンプルコード: 

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include osg/PositionAttitudeTransform>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/StateSetManipulator>
#include <osgUtil/Optimizer>
#include <osgUtil/Simplifer>

int main()
[
    // 创建Viewer对象,场景浏览器
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    
    // 切换网格模式,方便比较模型
    viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));

    osg::ref_ptr<osg::Group> root = new osg::Group();
    
    // 设置样本比率,样本比率越大,简化越小,反之,简化越多
    float sampleRatio = 0.3f;
    
    // 设置点的最大误差
    float maxError = 4.0f;
    
    // 创建简化对象
    osg::ref_ptr<osg::Node> node1 = osgDB::readNodeFile("cow.org");

    // 深拷贝牛的模型到node2节点
    osg::ref_ptr<osg::Node> node2 = (osg::Node*)(node1->clone(osg::CopyOp::DEEP_COPY_ALL));

    // 创建一个位置变换节点
    osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();

    // 设置位置
    pat->setPosition(osg::Vec3(10.0f,0.0f,0.0f));

    // 添加子节点
    pat->addChild(node2.get());

    // 简化处理
    pat->accept(simplifier);

    // 添加到场景
    root->addChild(node1.get());
    root->addChild(node2.get());

    // 优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());
    viewer->setSceneData(root.get());
    viewer->realize();
    viewer->ruN();

    return 0;
}

2. ドロネー三角形分割図

        TINモデル

        デジタル地形モデリングでは、不規則不規則三角形ネットワーク (TIN) は、不規則に離散的に分布したデータ ポイントから生成された連続した三角形の面によって地形表面を近似します。TIN モデルの利点は、さまざまな解像度レベルで地形サーフェスを記述できることです。グリッド データ モデルと比較して、TIN モデルは、特定の解像度でより少ないスペースと時間で、より複雑なサーフェスをより正確に表現できます。特に地形に断層面や構造線などのフィーチャが多数含まれている場合、TIN モデルはこれらのフィーチャをより適切に考慮できるため、表面形態をより正確かつ合理的に表現できます。
        TIN モデルの基本要件は次のとおりです:
        (1) TIN は一意であること、
        (2) 最適な三角形ジオメトリを追求すること、
        (3) 最近隣の点が三角形を形成することを保証すること

        考えられるすべての三角形分割の中で、ドロネー三角形分割は地形フィッティングで最も優れたパフォーマンスを発揮し、TIN 生成でよく使用されます。TIN の生成において、互いに素なブレークラインなどが事前定義された制約として使用される場合、制約付きのドロネー三角形分割を考慮する必要があります。

        osgUtil::DelaunayTriangulator クラス
        osgUtil::DelaunayTriangulator クラスは、osg::Referenced クラスを直接継承します。
        Delaunay 三角形分割を作成するには 3 つの手順があります:
        (1) 頂点配列を作成する;
        (2) osgUtiil::DelaunayTriangulator オブジェクトを作成し、頂点配列を初期化し、同時に三角形分割を生成します。プログラム コードは次のとおりです。
        bool triangulate() // 三角形メッシュの生成を開始します
        (3) ジオメトリ オブジェクトを作成し、osgUtil::DelaunayTriangulator クラス オブジェクトによって生成された描画プリミティブをジオメトリに追加します。Delaunay TIN を生成するときに、点、線、多角形などの制約を追加することもできます (例:
        void addInputConstraint(DelaunayConstraint *dc) ; // 制約を追加します)

ドロネー三角形分割の描画例

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include osg/PositionAttitudeTransform>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/StateSetManipulator>
#include <osgUtil/Optimizer>
#include <osgUtil/DelaunayTriangulator>

#include "Tex.h"

int main()
[
    // 创建Viewer对象,场景浏览器
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    
    // 切换网格模式,方便比较模型
    viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));

    osg::ref_ptr<osg::Group> root = new osg::Group();
    
    // 创建顶点数组
    osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array();
    
    // 计算顶点数组的大小
    unsigned int a = sizeof(vertex) / sizeof(float[3]);
    
    // 添加顶点数据
    for(unsigned int i = 0; i <a;++i)
    {
        coords->push_back(osg::Vec3(vertex[i][0],vertex[i][1],vertex[i][2]));
    }

    // 创建Delaunay三角网对象
    osg::ref_ptr<osgUtil::DelaunayTriangulator> dt = new osgUtil::DelaunayTriangulator(coords.get());
    dt->triangulate();

    // 创建几何体
    osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
    geometry->setVertexArray(coords.get());
    geometry->addPrimitiveSet(dt->getTriangles());

    osg::ref_ptr<osg::Geode> geode = new osg::Geode();
    geode->addDrawable(geometry.get());
    root->addChild(geode.get());

    // 优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());
    viewer->setSceneData(root.get());
    viewer->realize();
    viewer->ruN();

    return 0;
}

3. 三角ベルトの描画

        三角形ストリップ描画 (osgTUtil::TriStripVisitor) クラスは、osgUtil::BaseOptimizerVIsitor クラスから継承されており、ビジター メカニズムを使用してシーン内のジオメトリを走査し、三角形ストリップ描画を実現してレンダリング効率を向上させます。
        osgUtil::TriStrioVisitor の 2 つの一般的に使用されるメンバー関数については、以下で説明します:
        void Stripeify(osg::Geometry &drawable);// ジオメトリをストリップする
        virtual void apply(osg::Geode &geode); // リーフ ノードの
        関連付けに適用します。リーフ ノード インスタンスが使用されるときにメソッドを呼び出す必要があります。インデックス付き TIN は、ほとんどのグラフィック カードでは直接サポートされていません。三角形をレンダリングする場合、通常は 3 つの頂点が同時に送信されます。このように、共有頂点は複数回送信され、三角形は使用時に 1 回送信されます。

osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
geometry->setVertexArray(v.get());
geometry->setTexCoordArray(vt.get());
geometry->setColorArray(vc.get());
...

osgUtil::TriStripVisitor stripper;
stripper.stripify(*(geometry.get()));

osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->addDrawable(geometry.get());

...

4. 頂点法線ベクトルの生成

         頂点法線ベクトルの生成 ( osgUtil::SmoothingVisitor ) クラスは osg::NodeVisitor クラスから継承し、ビジター メカニズムを使用してシーン内のジオメトリを走査し、頂点法線ベクトルを生成します。
        osgUtil::SmoothingVisitor の一般的に使用されるメンバー関数については、以下で説明します:
       static voidSmooth(osg::Geometry &geoset);
        この関数は、頂点法線ベクトルを生成するために使用されます。これは静的関数であることに注意してください。
        多くのアプリケーションでは、メッシュ上の各ポイントに表面法線ベクトルが必要です。これは、次のようなさまざまな目的に役立ちます。 > ライティングの計算 >
        背面
        カリング
        > 表面上のパーティクル システムの「バウンス」効果のシミュレーション
        > 高速衝突検出。

...
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
...

// 生成点面法向
osgUtil::SmoothingVisitor::smooth(*(geometry.get()));

osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->addDrawable(geometry.get());

...

おすすめ

転載: blog.csdn.net/liangfei868/article/details/127628032