[3.4] - OSG study notes - polygon grid

        If readers have a certain understanding of OpenGL, they should know that in order to quickly render polygons, OpenGL specifies that it can directly display simple convex polygons. The so-called simple convex polygon means that the points on the line connecting any two points on the polygon belong to the polygon. Rendering results for concave polygons or self-intersecting polygons will be undefined. Listed below are some polygons that need to be gridded.

        In order to correctly display concave polygons or self-intersecting polygons, they must be decomposed into simple convex polygons, which is called polygon gridding . OSG is an encapsulation of the underlying OpenGL API, so it can only directly display simple convex polygons. For concave polygons or self-intersecting polygons, the rendering is also uncertain.

        In OSG, a polygon gridded class osgUtil::Tessellator is provided, which inherits from the osg::Referenced class.

        The following three steps are required for polygon grid rendering in OSG: 
        (1) Create a polygon grid object;
        (2) Set the type of grid object, usually there are the following three types:
 

TESS_TYPE_GEOMETRY gridded geometry
TESS_TYPE_DRAWABLE Drawable in gridded geometry (such as polygons, triangles, quadrilaterals, etc.)
TESS_TYPE_POLYGEONS Tessellate only the polygons in the geometry

        (3) Specify the corresponding wrapping rules according to the calculated wrapping numbers.

1. Surrounding number

        In the 5th edition of "OpenGL Programming Guide", it was pointed out that "For a simple contour line, the number of surrounds without a point is the algebraic sum of all contours surrounding this point (expressed by a signed integer, and the summation rule is: Counterclockwise wrapping contours are positive, clockwise wrapping contours are negative). This procedure associates a signed integer value with each vertex on the plane. Note that for all points in the region, their wrapping numbers are all the same".
        The figure below shows the calculation method of the contour line and the encircling number. You can use this figure to understand the encircling number and how to calculate the encircling number.

 2. Surrounding rules

        A region is an interior region if its wrapping number is of the type chosen by the wrapping rules. In general, the wrapping rules define regions with odd and non-zero wrapping numbers as interior regions. The surrounding rules are mainly determined for the surrounding numbers.

        Several commonly used surround rules are as follows:

TESS_WINDING_ODD = GLU_TESS_WINDING_ODD Surrounding number is odd
TESS_WINDING_NONZERO = GLU_TESS_WINDING_NONZERO Surrounding number is non-zero
TESS_WINDING_POSITIVE = GLU_TESS_WINDING_POSITIVE The wrapping number is a positive number
TESS_WINDING_NEGATIVE = GLU_TESS_WINDING_NEGATIVE The wrapping number is negative
TESS_WINDING_ABS_GEQ_TWO = GLU_TESS_WINDING_ABS_GEO_TWO The wrapping number is greater than or equal to 2 in absolute value

#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/ShapeDrawable>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osgUtil/Tessellator>

// 使用分格化绘制凹多边形
osg::ref_ptr<osg::Geode> tesslatorGeometry()
{
    osg::rer_ptr<osg::Geode> geode = new osg::Geode();
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
    geode->addDrawable(geom.get());
    
    // 以下是一些顶点数据
    const float wall[5][3] = {...};
    
    const float door[4][3] = {...};

    const float windows[16][3] = {...};

    // 设置顶点数据
    osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array();
    geom->setVertexArray(coords.get());

    // 设置法线
    osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array();
    normal.push_back(osg::Vec3(0.0f,-1.0f,0.0f));
    geom->setNormalArray(normal.get());
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    // 添加墙
    for(int i=0;i<5;++i)
    {
        coords->push_back(osg::Vec3(wall[i][0],wall[i][1],wall[i][2]));
    }
    geom->addPrimitiveSet(new osg::DrawArray(osg::PrimitiveSet::POLYGON,0,5));
    
    // 添加门
    for(int i=0;i<4;++i)
    {
        coords->push_back(osg::Vec3(door[i][0],door[i][1],door[i][2]));
    }
    // 添加窗
    for(int i=0;i<16;++i)
    {
        coords->push_back(osg::Vec3(windows[i][0],windows[i][1],windows[i][2]));
    }

    geom->addPrimitiveSet(new osg::DrawArray(osg::PrimitiveSet::QUADS,5,20));
    
    // 创建分格化对象
    osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::TesseLLator();
    tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
    tscx->setBoundaryOnly(false);// 只显示轮廓线为false
    tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);
    tscx->retessellatePolyons(*(geom.get()));
    return geode.get();
}

int main()
{
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    osg::ref_ptr<osg::Group> root = new osg::Group();
    osg::ref_ptr<osg::Geode> geode = tesslatorGeometry();
    root->addChild(geode.get());
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());
    viewer->setSceneData(root.get());
    viewer->realize();
    viewer->run();
    return 0;
}

Guess you like

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