【OpenSceneGraph】UpdateCallback Example

来源:互联网 发布:千牛mac版怎么安装 编辑:程序博客网 时间:2024/06/06 18:47

        OpenSceneGraph是一个跨平台的开源三维库,被广泛的应用在游戏、虚拟现实、三维重建、地理信息等领域。OSG提供了基于OpenGL的面向对象框架,使得开发者能够轻松的实现或优化底层图形接口调用,并且其拥有的众多工具为图形应用的快速开发提供最大程度的便捷。

        本例给出OpenSceneGraph中,更新回调操作(UpdateCallback)的一个简单用例。

        通过模拟LOD细节层次算法,对圆柱面的Geometry绑定更新回调操作,通过计算视点到包围盒的距离,然后对圆柱面进行动态设置划分阈值。


程序运行结果如下:




main函数

#include "stdafx.h"#include "tool.h"#include "callbacks.h"#include <string.h>#include <string>void createCylinder(osgViewer::Viewer* viewer, void* grp, void* geometry, float* center, float radius, float height, unsigned char * color) {if(!geometry) return;osg::Group *root = static_cast<osg::Group*> (grp);if(!root) return;int  i, ndiv = 16;osg::ref_ptr<osg::Vec3Array> cylVert = new osg::Vec3Array;cylVert->reserve(2*(ndiv+1));osg::ref_ptr<osg::Vec3Array> cylNorm = new osg::Vec3Array;cylNorm->reserve(2*(ndiv+1));float delta =osg::PI * 2 / ndiv;for( i = 0; i <= ndiv; ++i){float a, b, angle;if(i == ndiv)  angle = 0;else angle = delta * i;a = radius * cos(angle);b = radius * sin(angle);osg::Vec3 v, n;v[0] = a + center[0], v[1] = b + center[1], v[2] = center[2] + height ;cylVert->push_back(v);v[2] = center[2];cylVert->push_back(v);        n[0] = a, n[1] = b, n[2] = 0;cylNorm->push_back(n);cylNorm->push_back(n);}osg::Geometry *body = new osg::Geometry;body->setUseDisplayList(false);body->setUseVertexBufferObjects(true);body->setVertexArray(cylVert);body->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0, 2*(ndiv+1)));body->setNormalArray(cylNorm);body->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);body->setDataVariance(osg::Object::DYNAMIC);osgUtil::SmoothingVisitor::smooth(*body);body->setUpdateCallback(new MyGeometryCallback(16, 16, viewer, osg::Vec3(center[0], center[1], center[2]), radius, height));if( color !=NULL){osg::Vec4 clr = gbUtilColorNormalized( color);osg::Vec4Array* colors = new osg::Vec4Array;colors->push_back( clr);body->setColorArray( colors );body->setColorBinding(osg::Geometry::BIND_OVERALL);}osg::Geode *geo = new osg::Geode;geo->addDrawable(body);osg::ComputeBoundsVisitor boundvisitor;geo->accept(boundvisitor);osg::BoundingBox bb;bb = boundvisitor.getBoundingBox();root->addChild(geo);}int _tmain(int argc, _TCHAR* argv[]){osg::ref_ptr<osg::Group> root = new osg::Group;osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;srand(0);for(int i = 0; i < 1; ++ i) {osg::ref_ptr<osg::Geode> geo = new osg::Geode;float x = rand() % 20 * 1.0;float y = rand() % 20 * 1.0;float z = rand() % 20 * 1.0;float center[3] = {x, y, z};unsigned char color[3] = {255, 0, 0};createCylinder(viewer, root, geo, center, 50.0, 20.0, color);}viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);viewer->setSceneData(root.get());viewer->addEventHandler(new osgViewer::StatsHandler);viewer->setUpViewInWindow(100, 100, 640, 480);return viewer->run();}


callbacks.h
#ifndef _CALLBACKS_H_#define _CALLBACKS_H_#include "osgHead.h"#include <time.h>#include <random>#include <assert.h>#include <math.h>float dist(const osg::Vec3& vec) {return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);}class MyGeometryCallback : public osg::Drawable::UpdateCallback,public osg::Drawable::AttributeFunctor{public:MyGeometryCallback(int pdiv, int div, osg::ref_ptr<osgViewer::Viewer> viewer, osg::Vec3 center, float radius, float height) : _prendiv(pdiv), _curndiv(div), _viewer(viewer), _center(center), _radius(radius), _height(height){}virtual void update(osg::NodeVisitor *nv, osg::Drawable *drawable){osg::Vec3f eye,center,up;_viewer->getCamera()->getViewMatrixAsLookAt(eye,center,up);float x = eye[0] - _center[0];float y = eye[1] - _center[1];float z = eye[2] - _center[2];float dist = sqrt(x * x + y * y + z * z);osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);if(!geometry) return;if(dist < 300.0) _curndiv = 32;else if(dist < 600.0) _curndiv = 16;else _curndiv = 8;if(_prendiv != _curndiv) {osg::ref_ptr<osg::Vec3Array> cylVert = new osg::Vec3Array;osg::ref_ptr<osg::Vec3Array> cylNorm = new osg::Vec3Array;cylNorm->reserve( 2*(_curndiv+1));cylVert->reserve( 2*(_curndiv+1));_prendiv = _curndiv;osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*> (geometry->getVertexArray());osg::Vec3Array* nverts = dynamic_cast<osg::Vec3Array*> (geometry->getNormalArray());if(!verts || !nverts) return;verts->resize(2*(_curndiv+1));nverts->resize(2*(_curndiv+1));float delta = osg::PI*2/_curndiv;int idx = 0;for(int i = 0; i <= _curndiv; ++i){float a, b, angle;if( i == _curndiv)angle = 0;elseangle = delta*i;a = _radius * cos(angle);b = _radius * sin(angle);osg::Vec3 v, n;v[0] = a + _center[0];v[1] = b + _center[1];v[2] = _height + _center[2];n[0] = a, n[1] = b, n[2] = 0;verts->at(idx) = v;nverts->at(idx ++) = n;v[2] = _center[2];verts->at(idx) = v;nverts->at(idx++) = n;}geometry->removePrimitiveSet(0);geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0, 2*(_curndiv+1)));geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);verts->dirty();nverts->dirty();drawable->dirtyBound();if(geometry) osgUtil::SmoothingVisitor::smooth(*geometry);}}int                _prendiv;int                _curndiv;float              _radius;float              _height;osg::Vec3          _center;osgViewer::Viewer* _viewer;};#endif

tool.h

#ifndef __TOOL__H_#define __TOOL__H_#include "osgHead.h"osg::Vec4 gbUtilColorNormalized( unsigned char color[3]);#endif

tool.cpp

#include "stdafx.h"#include "tool.h"osg::Vec4 gbUtilColorNormalized( unsigned char  color[3]){if( color)return osg::Vec4( color[0]/255.0, color[1]/255.0, color[2]/255.0, 1);elsereturn osg::Vec4(0,0,0,1);}



0 0
原创粉丝点击