osgEarth示例分析——osgearth_drawables

前言

此示例绘制各种图形。玫红色的线会根据设置的回调进行变化。

执行命令:

// 此示例不需要mapNode,所以直接执行程序即可
// 透视投影
osgearth_drawblesd.exe

// 正射投影
osgearth_drawblesd.exe --ortho

// 抗锯齿,线条更平滑
osgearth_drawblesd.exe --smooth

// 将组件的node写入到 out.osgt文件,然后再从文件中将node读取出来,加入到场景中
osgearth_drawblesd.exe --serialize

执行效果

透视投影和正射投影的初始状态:

正射投影拖动后的状态,远近的情况下,尺寸不发生变化。

透视投影拖动后的状态,近大远小。

 

  代码分析

主要学习:

  1. LineDrawable 和 PointDrawable的用法。
  2. 通过构造节点回调,动态设置回调。
  3. node节点序列化存储、读取、绘制。
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/LineStipple>
#include <osgGA/StateSetManipulator>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgEarth/LineDrawable>
#include <osgEarth/PointDrawable>
#include <osgEarth/CullingUtils>
#include <osgEarth/VirtualProgram>
#include <osgEarth/GLUtils>

#define LC "[drawables] "

using namespace osgEarth;

// 采用osgEarth的方法绘制
void addVerts(LineDrawable* line, double x, double y)
{
    line->pushVertex(osg::Vec3(x, 0, y));
    line->pushVertex(osg::Vec3(x + 5, 0, y));
    line->pushVertex(osg::Vec3(x + 10, 0, y));
    line->pushVertex(osg::Vec3(x + 10, 0, y + 5));
    line->pushVertex(osg::Vec3(x + 10, 0, y + 10));
    line->pushVertex(osg::Vec3(x + 5, 0, y + 10));
    line->pushVertex(osg::Vec3(x, 0, y + 10));
    line->pushVertex(osg::Vec3(x, 0, y + 5));
    line->finish();
}

// 采用osgEarth的方法绘制
void addLotsOfVerts(LineDrawable* line)
{
    for (int x = 0; x < 10; ++x)
    {
        for (int y = 0; y < 10; ++y)
        {
            line->pushVertex(osg::Vec3(x, 0, y));
        }
    }
    line->finish();
}

// 采用osgEarth的方法绘制
LineDrawable* makeStar(double x, double y, double r)
{
    LineDrawable* star = new LineDrawable(GL_LINES);
    for(float i=0.0f; i<osg::PI*2.0; i += osg::PI/16.0)
    {
        float c = cos(i), s = sin(i);
        star->pushVertex(osg::Vec3(x, 0, y));
        star->pushVertex(osg::Vec3(x+(r*c-r*s), 0, y+(r*c+r*s)));
    }
    star->finish();
    return star;
}

// 采用osgEarth的方法绘制
PointDrawable* makeGridOfPoints(double x, double y)
{
    PointDrawable* grid = new PointDrawable();
    for(float i=x; i<x+20; i+=5)
    {
        for(float j=y; j<y+20; j+=5)
        {
            grid->pushVertex(osg::Vec3(i, 0, j));
        }
    }
    grid->finish();
    return grid;
}

// 采用osg的方法绘制
osg::Node* makeGeometryForImport(double x, double y)
{
    osg::Geometry* geom = new osg::Geometry();
    osg::Vec3Array* verts = new osg::Vec3Array();
    verts->push_back(osg::Vec3(x, 0, y));
    verts->push_back(osg::Vec3(x + 5, 0, y));
    verts->push_back(osg::Vec3(x + 10, 0, y));
    verts->push_back(osg::Vec3(x + 10, 0, y + 5));
    verts->push_back(osg::Vec3(x + 10, 0, y + 10));
    verts->push_back(osg::Vec3(x + 5, 0, y + 10));
    verts->push_back(osg::Vec3(x, 0, y + 10));
    verts->push_back(osg::Vec3(x, 0, y + 5));
    geom->setVertexArray(verts);    
    osg::Vec4Array* colors = new osg::Vec4Array(1);
    (*colors)[0].set(1,1,1,1);
    geom->setColorArray(colors);
    geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, verts->size()));
    geom->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(3.0f));
    geom->getOrCreateStateSet()->setAttributeAndModes(new osg::LineStipple(1, 0xfff0));
    return geom;
}

struct TestFirstCount : public osg::NodeCallback
{
    void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
		// 按照帧,每20帧,线条更新一次位置
        if (nv->getFrameStamp()->getFrameNumber() % 20 == 0)
        {
            LineDrawable* line = (LineDrawable*)node;

            unsigned total = line->getNumVerts();
            unsigned first = line->getFirst();
        
            line->setFirst( (first+1) % total );
            line->setCount( 3 );// 绘制3个点
        }
    }
};

osg::Node* createDrawables()
{
    // You need a viewport uniform for the lines to work.
    // MapNode installs one automatically, but we're not using MapNode
    // in this example.
	// 本节不使用mapNode节点
    osg::Group* group = new osg::Group();
    group->addCullCallback(new InstallViewportSizeUniform());

    float x = 10;
    float y = 10;

	// 定义一条连续线
    LineDrawable* strip = new LineDrawable(GL_LINE_STRIP);
    strip->setLineWidth(8);// 线宽
    strip->setColor(osg::Vec4(1,1,1,1));//颜色
    addVerts(strip, x, y);// 采用第一种方式绘制线
    group->addChild(strip);

	// 定义一条环线
    x += 20;
    LineDrawable* loop = new LineDrawable(GL_LINE_LOOP);
    loop->setLineWidth(1);
    loop->setColor(osg::Vec4(1,1,0,1));
    addVerts(loop, x, y);
    group->addChild(loop);

	// 定义一条连续线
    x += 20;
    LineDrawable* stippled = new LineDrawable(GL_LINE_STRIP);
    stippled->setLineWidth(4);
    stippled->setStipplePattern(0xff00);// 线型
    stippled->setColor(osg::Vec4(0,1,0,1));
    addVerts(stippled, x, y);
    group->addChild(stippled);
    
	// 定义线段(每两个点连接) 
    x += 20;
    LineDrawable* segments = new LineDrawable(GL_LINES);
    segments->setLineWidth(3);
    segments->setColor(osg::Vec4(0,1,1,1));
    addVerts(segments, x, y);
    group->addChild(segments);

	// 定义一条连续线
    x += 20;
    LineDrawable* firstCount = new LineDrawable(GL_LINE_STRIP);
    firstCount->setLineWidth(5);
    firstCount->setColor(osg::Vec4(1,0,1,1));
    addVerts(firstCount, x, y);
    firstCount->addUpdateCallback(new TestFirstCount());// 此处对线设置回调方法
    group->addChild(firstCount);
    
	// 采用osg的方式定义线条geometry节点
    x += 20;
    osg::ref_ptr<osg::Node> node = makeGeometryForImport(x, y);
    LineGroup* lines = new LineGroup();// 采用lineGroup的方式,绘制线
    lines->import(node.get());// 导入定义好的node图元
    group->addChild(lines);

	// 绘制很多点,大小颜色都默认
    x += 20;
    LineDrawable* points = new LineDrawable(GL_POINTS);
    addVerts(points, x, y);
    group->addChild(points);

	// 绘制线段
    x = 20;
    y -= 20;
    for(unsigned i=0; i<10; ++i)
    {
        LineDrawable* across = new LineDrawable(GL_LINES);
        across->pushVertex(osg::Vec3(x, 0, y));
        across->pushVertex(osg::Vec3(x+100, 0, y));
        across->setLineWidth((float)(i+1));
        across->finish();
        group->addChild(across);
        y -= (i+2);
    }

	// 绘制star
    x = 20;
    y -= 20;
    LineDrawable* star = makeStar(x, y, 10);
    star->setColor(osg::Vec4(1,1,1,1));
    star->setLineWidth(1.0f);
    group->addChild(star);

    x += 40;
    LineDrawable* star2 = makeStar(x, y, 10);
    star2->setColor(osg::Vec4(1,.5,0,1));
    star2->setLineWidth(2.0f);
    group->addChild(star2);

    x += 40;
    LineDrawable* star3 = makeStar(x, y, 10);
    star3->setColor(osg::Vec4(1,1,0,1));
    star3->setLineWidth(3.0f);
    group->addChild(star3);

	// 绘制点网格
    y -= 40;
    x = 20;
    PointDrawable* grid = makeGridOfPoints(x, y);
    grid->setPointSize(3.0f);
    grid->setColor(osg::Vec4(0,1,1,1));
    group->addChild(grid);

	// 绘制点网格
    x += 50;
    PointDrawable* grid2 = makeGridOfPoints(x, y);
    grid2->setPointSize(20.0f);
    GLUtils::setPointSmooth(grid2->getOrCreateStateSet(), 1);
    group->addChild(grid2);

    return group;
}

int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    osgViewer::Viewer viewer(arguments);

    osg::ref_ptr<osg::Node> node = createDrawables();

#ifdef OSG_GL3_AVAILABLE
    // Sets up the State for GL3 mode
    viewer.setRealizeOperation(new GL3RealizeOperation());
#endif

    if (arguments.read("--ortho"))
    {
        viewer.realize();
        double r = node->getBound().radius() * 1.2;
        double ar = viewer.getCamera()->getViewport()->width() / viewer.getCamera()->getViewport()->height();
        viewer.getCamera()->setProjectionMatrixAsOrtho(-r, +r, -r/ar, +r/ar, -r*2.0, +r*2.0);
    }

    if (arguments.read("--antialias") || arguments.read("--smooth"))
    {
        GLUtils::setLineSmooth(node->getOrCreateStateSet(), 1);// 配置线条抗锯齿
        GLUtils::setPointSmooth(node->getOrCreateStateSet(), 1);// 配置点抗锯齿
        node->getOrCreateStateSet()->setMode(GL_BLEND, 1);// 混合模式
    }

    if (arguments.read("--serialize"))// 序列化
    {
        const char* fileName = "out.osgt";

        OE_NOTICE << "Writing to " << fileName << " ..." << std::endl;
        if (!osgDB::writeNodeFile(*node.get(), fileName)) // 将组建好的node写入文件
        {
            OE_WARN << "serialize failed!\n";
            return -1;
        }

        OE_NOTICE << "Reading from " << fileName << " ..." << std::endl;
        node = osgDB::readRefNodeFile(fileName);// 从out.osgt文件中,读取node,并将其加入到场景中
        if (!node.valid())
        {
            OE_WARN << "deserialize failed!\n";
            return -1;
        }
    }

    // Sets up global default uniform values needed by osgEarth
	// 设置 osgEarth 所需的全局默认统一值
    GLUtils::setGlobalDefaults(viewer.getCamera()->getOrCreateStateSet());

    viewer.setSceneData(node.get());
    // 设置事件处理器和操作器
    viewer.addEventHandler(new osgViewer::StatsHandler());
    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

    return viewer.run();
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值