OpenSceneGraph基础:Helloworld

来源:互联网 发布:linux 时间 修改 编辑:程序博客网 时间:2024/05/15 18:42

OpenSceneGraph的基本流程(main函数):

转载请注明http://blog.csdn.net/boksic 如有疑问欢迎留言

int main() {Group *scene = startupScene();osgViewer::Viewer viewer;viewer.setSceneData(scene);viewer.setCameraManipulator(new osgGA::TrackballManipulator);viewer.realize();while (!viewer.done()) {viewer.frame();update(0.005); // do the update advancing 5ms} return 0;}

  • startupScene函数是自己建立的场景初始化函数,返回值是包含了场景图形数据的Group类
  • 接着初始化Viewer类,以及提供了模型操作功能的TrackballManipulator
  • 最后就是最为重要的渲染部分-Viewer的循环,每帧都会调用自定义的update函数

场景初始化(startupScene)

建立模型数据

这里使用的是程序内部初始化数据,包含了顶点坐标,面索引以及顶点颜色

(部分网上教程里还使用了顶点的颜色索引colorIndexArray,但该功能因为非常影响性能,现在的OSG中已废除了该功能。所以顶点与色彩应按对应关系初始化)

// 顶点osg::Vec3Array *vertexArray = new osg::Vec3Array();vertexArray->push_back(osg::Vec3(-2, -2, 0)); // front left vertexArray->push_back(osg::Vec3(+2, -2, 0)); // front right vertexArray->push_back(osg::Vec3(+2, +2, 0)); // back right vertexArray->push_back(osg::Vec3(-2, +2, 0)); // back left vertexArray->push_back(osg::Vec3(0, 0, 2*sqrt(2))); // peakvertexArray->push_back(osg::Vec3(0, 0, -2*sqrt(2))); // lower peak// 面,全部按逆时针顺序索引顶点osg::DrawElementsUInt *faceArray = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);faceArray->push_back(0); // face 0faceArray->push_back(1);faceArray->push_back(4);faceArray->push_back(1); // face 1faceArray->push_back(2);faceArray->push_back(4);faceArray->push_back(2); // face 2faceArray->push_back(3);faceArray->push_back(4);faceArray->push_back(3); // face 3faceArray->push_back(0);faceArray->push_back(4);faceArray->push_back(0); // face 4faceArray->push_back(5);faceArray->push_back(1);faceArray->push_back(2); // face 5faceArray->push_back(1);faceArray->push_back(5);faceArray->push_back(3); // face 6faceArray->push_back(2);faceArray->push_back(5);faceArray->push_back(0); // face 7faceArray->push_back(3);faceArray->push_back(5);// 色彩osg::Vec4Array *colorArray = new osg::Vec4Array();colorArray->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //index 0colorArray->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //index 1colorArray->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //index 2colorArray->push_back(osg::Vec4(1.0f, 0.0f, 1.0f, 1.0f)); //index 3colorArray->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); //index 4 colorArray->push_back(osg::Vec4(1.0f, 1.0f, 0.5f, 1.0f)); //index 5

将建立的数据存为osg里的对象:

osg::Geometry *geometry = new osg::Geometry();geometry->setVertexArray(vertexArray);geometry->setColorArray(colorArray);geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);geometry->addPrimitiveSet(faceArray);

Osg中定义了Drawables虚基类用于存储形状数据,该类派生出了3个子类

  1. DrawPixels,封装opengl的glDrawPixels
  2. ShapeDrawable,用于绘制OSG自带的简单集合体
  3. Geometry,功能最为广泛的子类,本例当中就是使用该类

Geometry的setVertexArray() , setColorArray() , setNormalArray()等函数用于设置坐标,颜色,法线等数据。setColorBinding()用于设置颜色绑定方式,本例中的BIND_PER_VERTEX即每个顶点对应一个颜色。addPrimitiveSet()则告诉OSG如何利用这些数据绘制图形,前面我们使用了DrawElementsUInt为PrimitiveSe的派生类来按照三角形绘制数据,这点与OpenGL下的代码非常相似。

建立叶节点:

Geode *pyramidObject = new Geode();pyramidObject->addDrawable(geometry);
Geode类派生自Node节点类,Geode即Geometry Node,用于保存几何信息。该类的addDrawable()函数可用来将Drawables类的数据关联起来。

建立组节点

    osg::Group *root = new osg::Group();    for (int i = 0; i < 1000; i++) {        tr[i] = new osg::PositionAttitudeTransform;        tr[i]->setPosition(osg::Vec3(((float)rand() / RAND_MAX * 4) * 1000, ((float)rand() / RAND_MAX * 4) * 1000, 0));        tr[i]->addChild(pyramidObject);        root->addChild(tr[i]);    }    return root;}

组节点类Group继承自Node,OSG编程的核心,可通过addChild()添加子节点,也可以拥有父节点。

Group有几个派生类,其中一个是Tranform类用于几何变换,不过Transform是虚基类,实际使用MatrixTransform或PositionAttitudeTransform这两个子类。本例中的tr是一个PositionAttitudeTransform类对象的数组,该类可以通过setPosition来设置位置或者通过四元数来实现旋转。

本程序建立了1000个实现随机分布的Transform子节点,每个节点都添加了前面的叶节点作为几何数据。

初始化的部分就结束了。


场景更新

float t= 0;void update(float dt) {// keep track of the timet+= 0.02*dt;double ro = (3 / 4)*(3.1415926 / 2);//float myRand = ((float)rand() / RAND_MAX);for (int i = 0; i < 1000; i++) {osg::Vec3d currentPosition = tr[i]->getPosition();osg::Vec3d *newPosition; newPosition = new osg::Vec3d(sin(3 * t*i + ro) * (10 + i), sin(4 * t*i) ,i);//+ dt * (i + 1) / 10  tr[i]->setPosition(osg::Vec3(newPosition->x(), newPosition->y(), newPosition->z()));}}

更新部分通过全局变量t来控制时间,使用Transform节点的setPosition来控制模型位置,本例实现的是一个随时间变化的丽莎如图形:



或者改变参数实现其他效果:







0 0
原创粉丝点击