osg.PrimitiveFunctor
是一个纯虚类,用于定义遍历OpenSceneGraph中几何图形的原语的方法。
在OpenSceneGraph中,几何图形是使用一个个可渲染的原语(primitive)来组成的,每种原语都由一堆顶点、颜色、法线等属性描述。osg.PrimitiveFunctor的作用就是定义处理这些原语的方法,例如绘制、计算表面积等。
osg.PrimitiveFunctor有两个纯虚函数:
void apply( unsigned int mode, unsigned int count, const void* indices )
:处理一个原语的方法。void setVertexArray( const osg::Vec3* vertices, unsigned int vtx_num )
:设置顶点数组的方法。其中,apply
是必须实现的方法,用于处理具体的原语;而setVertexArray
是可选的,用于在处理原语前设置顶点的数组和数量。
在使用osg.PrimitiveFunctor时一般需要补充定义一个继承自它的类,并实现自己的apply方法。
下面是一个简单示例,绘制一个立方体的各个面:
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PrimitiveFunctor>
struct MyPrimitiveFunctor : public osg::PrimitiveFunctor
{
void setVertexArray( const osg::Vec3* vertices, unsigned int vtx_num ) override
{
vertex_data = vertices;
vertex_num = vtx_num;
}
void apply( unsigned int mode, unsigned int count, const void* indices ) override
{
auto* vertices = new osg::Vec3[count];
for( unsigned int i = 0; i < count; ++i )
{
unsigned int idx = *(reinterpret_cast<const unsigned int*>(indices) + i);
vertices[i] = vertex_data[idx];
}
auto* geometry = new osg::Geometry;
auto* vertices_array = new osg::Vec3Array( count, vertices );
geometry->setVertexArray( vertices_array );
auto* geode = new osg::Geode;
geode->addDrawable( geometry );
switch( mode )
{
case osg::PrimitiveSet::QUADS:
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, count ) );
break;
case osg::PrimitiveSet::TRIANGLES:
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::TRIANGLES, 0, count ) );
break;
default:
break;
}
osg::ref_ptr<osgDB::Options> options = new osgDB::Options;
options->setOptionString( "OutputTextureFiles" );
osgDB::writeNodeFile( *geode, "test.osg", options );
delete[] vertices;
}
const osg::Vec3* vertex_data = nullptr;
unsigned int vertex_num = 0;
};
int main( int argc, char** argv )
{
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back( {-0.5,-0.5,0.5} );
vertices->push_back( {0.5,-0.5,0.5} );
vertices->push_back( {0.5,0.5,0.5} );
vertices->push_back( {-0.5,0.5,0.5} );
vertices->push_back( {-0.5,-0.5,-0.5} );
vertices->push_back( {0.5,-0.5,-0.5} );
vertices->push_back( {0.5,0.5,-0.5} );
vertices->push_back( {-0.5,0.5,-0.5} );
unsigned int indices_sum[][4] = {
{0,1,2,3},
{1,5,6,2},
{5,4,7,6},
{4,0,3,7},
{3,2,6,7},
{0,4,5,1}
};
osg::ref_ptr<osg::DrawElementsUInt> indices[6];
for( int i = 0; i < 6; ++i )
{
unsigned int* data = new unsigned int[4];
for( int j = 0; j < 4; ++j )
data[j] = indices_sum[i][j];
indices[i] = new osg::DrawElementsUInt( osg::PrimitiveSet::QUADS, 4, data );
}
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
geometry->setVertexArray( vertices.get() );
for( int i = 0; i < 6; ++i )
geometry->addPrimitiveSet( indices[i].get() );
MyPrimitiveFunctor functor;
geometry->accept( functor );
return 0;
}
输出截图: