OSG-geometry operations

        Scenes are composed of basic drawing primitives. Basic drawing primitives constitute simple geometry, simple geometry constitutes complex geometry, and complex geometry finally constitutes complex scenes. When multiple geometries are combined, there can be several reasons for slowing down the rendering efficiency of a scene. In many 3D engines, operations to modify the geometry of the scene are provided to achieve optimal rendering efficiency. Although optimal rendering efficiency is only an ideal state, certain geometry operations can improve rendering efficiency to a considerable extent.
        In OSG, in order to obtain the required performance and rendering efficiency, the osgUtil library provides some general geometry operations, these geometry operations mainly include: osgUtil::Simplifier (simplification), ostUtil::SmoothingVisitor (generate normal), osgUtil ::DelaunayTriangulator (generate Delaunay triangulation tool) and osgUtil::TriStripVisitor (striping), etc.

1. Simplify geometry

        The simplified geometry ( osgUtil::Simplifier ) class inherits from the osg::NodeVisitor class, which traverses the geometry in the form of a visitor and simplifies it.
        The simplification of the geometry by the osgUtil::Simplfier class mainly needs to set two parameters, that is, when the sample ratio of the geometry is less than 1, set the error limit of the point ; when the sample ratio of the geometry is greater than 1, set the length limit of the side . Simplify unnecessary points and edges by limiting point errors or edge lengths, and then render geometry through smoothing and striping to improve rendering efficiency. It can also be used to automatically generate low-level models. In general, the larger the sample ratio, the less simplification; the smaller the sample ratio, the more simplification. Optimization can directly call the following function:
        virtual void apply(osg::Geode &geode);      // for leaf nodes
        void simplify(osg::Geometry &geometry); // simplify geometry

        These two functions can also be used for osg::Node nodes, however, the accept() method needs to be used when associating instances.
        osgUtil::Simplifier simplifies using the edge collapse algorithm.
Sample code: 

#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. Delaunay triangulation drawing

        TIN model

        In digital terrain modeling, a triangulated irregular network (TIN) approximates a terrain surface by continuous triangular faces generated from irregularly discretely distributed data points. The advantage of the TIN model is that it can describe the terrain surface with different levels of resolution. Compared with grid data models, TIN models can more accurately represent more complex surfaces with less space and time at a certain resolution. Especially when the terrain contains a large number of features, such as fault surfaces and structural lines, the TIN model can better take these features into account, so that it can express the surface morphology more accurately and reasonably.
        For the TIN model, the basic requirements are as follows:
        (1) TIN is unique;
        (2) strive for the best triangle geometry;
        (3) ensure that the nearest neighbor points form a triangle

        Among all possible triangulations, the Delaunay triangulation performs best in terrain fitting and is often used in TIN generation. When disjoint breaklines, etc. are used as pre-defined constraints in the generation of TINs, Delaunay triangulation with constraints must be considered .

        The osgUtil::DelaunayTriangulator class
        The osgUtil::DelaunayTriangulator class directly inherits from the osg::Referenced class.
        There are three steps to create a Delaunay triangulation:
        (1) Create a vertex array;
        (2) Create an osgUtiil::DelaunayTriangulator object, initialize the vertex array, and generate a triangulation at the same time. The program code is as follows:
        bool triangulate() // Start to generate a triangular mesh
        (3) Create a geometry object, and add the drawing primitives generated by the osgUtil::DelaunayTriangulator class object to the geometry. When generating the Delaunay TIN, you can also add some constraints, which can be points, lines or polygons, for example:
        void addInputConstraint(DelaunayConstraint *dc) ; // Add constraints

Delaunay triangulation drawing example

#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. Triangular belt drawing

        The triangle strip drawing (osgTUtil::TriStripVisitor) class is inherited from the osgUtil::BaseOptimizerVIsitor class. It uses the visitor mechanism to traverse the geometry in the scene to achieve triangle strip drawing to improve rendering efficiency.
        Two commonly used member functions of osgUtil::TriStrioVisitor are described below:
        void stripify(osg::Geometry &drawable);// strip geometry
        virtual void apply(osg::Geode &geode); // apply to leaf node
        association The accept() method needs to be called when the leaf node instance is used. Indexed TINs are not directly supported by most graphics cards. When rendering a triangle, generally three vertices are submitted at the same time. In this way, the shared vertices will be submitted multiple times, and the triangle will be submitted once when it is used.

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. Generate vertex normal vector

         Generate vertex normal vector ( osgUtil::SmoothingVisitor ) class inherits from osg::NodeVisitor class, it uses visitor mechanism to traverse the geometry in the scene to generate vertex normal vector.
        A commonly used member function of osgUtil::SmoothingVisitor is described below:
       static void smooth(osg::Geometry &geoset);
        This function is used to generate the vertex normal vector. Please note that this is a static function.
        In many applications, each point on the mesh requires a surface normal vector, which is useful for a variety of purposes, such as:
        > Computing lighting
        > Backface culling
        > Simulating particle system "bounce" effects on surfaces
        > Accelerated collision detection.

...
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());

...

Guess you like

Origin blog.csdn.net/liangfei868/article/details/127628032