osgAnimation例子的注释的注释

转自:http://www.cnblogs.com/sunliming/archive/2011/12/12/2284995.html

 #include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/Geometry>
#include <osg/Geode> #include <osgUtil/Optimizer> #include <osgDB/Registry>
#include <osgDB/ReadFile> #include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator> #include <osgSim/OverlayNode> #include <osgViewer/Viewer>
#include <iostream> // 创建动画路径,参数有中心点,半径,以及循环时间
osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
{
// 实例化动画路径类
// set up the animation path
osg::AnimationPath* animationPath = new osg::AnimationPath;
// 设置动画路径的播放模式,当前使用循环模式(SWING LOOP NO_LOOPING )SWING就是在一个区间内顺逆方向循环,LOOP是顺一个方向循环
animationPath->setLoopMode(osg::AnimationPath::LOOP); // 分40个阶段 这个意思就是分为四十个控制点,犹如四十条边的多边形,沿着这个路线飞行
int numSamples = ;
float yaw = 0.0f;
// 偏航的分量,这是一个角度分量,算出来每一个多边形的边对应的角度分量2*PI/(n-1)
float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
// 旋转角度为30度
float roll = osg::inDegrees(30.0f); // 时间分量
double time=0.0f;
//平均的两个控制点之间的时间
double time_delta = looptime/(double)numSamples;
// 将时间控制点与位置坐标插入到动画路径中
for(int i=;i<numSamples;++i)
{
//这儿是计算出来每个多边形的顶点的坐标,(sinx*r,cosx*r,0.0)是相当于中心点的增量
osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
//四元数表示方向,表示在3D空间中的旋转方向**四元数很复杂**这个表示,绕x轴旋转roll,y轴旋转-(yaw+90),z轴0
osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0))); //和flash动画类似,控制点有位置和转动角度,这样控制点之间是均匀运动
animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation)); //递增yaw和time
yaw += yaw_delta;
time += time_delta; }
return animationPath;
} // 创建底板,中心点位置在center,半径为radius
osg::Node* createBase(const osg::Vec3& center,float radius)
{ // 一个10x10的底板
int numTilesX = ;
int numTilesY = ; // 长度与宽度的尺寸
float width = *radius;
float height = *radius; // 计算初始位置与x、y的分量
osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f)); // 计算每个小格子的顶点坐标并压入数组中
// fill in vertices for grid, note numTilesX+1 * numTilesY+1...
osg::Vec3Array* coords = new osg::Vec3Array;
int iy;
for(iy=;iy<=numTilesY;++iy)
{
for(int ix=;ix<=numTilesX;++ix)
{
coords->push_back(v000+dx*(float)ix+dy*(float)iy);
}
} // 设置颜色的数组,当前为黑白色两种颜色
//Just two colours - black and white.
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
int numColors=colors->size(); // 设置绘制四边形的顶点索引与每个四边形的颜色
int numIndicesPerRow=numTilesX+;
osg::UByteArray* coordIndices = new osg::UByteArray; // assumes we are using less than 256 points...
osg::UByteArray* colorIndices = new osg::UByteArray;
for(iy=;iy<numTilesY;++iy)
{
for(int ix=;ix<numTilesX;++ix)
{
// four vertices per quad.
coordIndices->push_back(ix +(iy+)*numIndicesPerRow);
coordIndices->push_back(ix +iy*numIndicesPerRow);
coordIndices->push_back((ix+)+iy*numIndicesPerRow);
coordIndices->push_back((ix+)+(iy+)*numIndicesPerRow); // one color per quad
colorIndices->push_back((ix+iy)%numColors);
}
} // 设置法线向量
// set up a single normal
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,0.0f,1.0f)); // 设置顶点坐标数组
osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(coords);
geom->setVertexIndices(coordIndices); // 设置颜色数组
geom->setColorArray(colors);
geom->setColorIndices(colorIndices);
geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); // 设置法线数组
geom->setNormalArray(normals);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL); // 需要绘制什么形状的图形,当前为四边形
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,,coordIndices->size())); // 将绘制的的图形添加到osg::Geode中
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geom); return geode;
} // 创建移动的模型,中心点在center,半径为radius
osg::Node* createMovingModel(const osg::Vec3& center, float radius)
{
float animationLength = 10.0f; // 创建动画路径,中心点在center,半径为radius,循环时间为10.0f
osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); osg::Group* model = new osg::Group; // 从外部读取一个模型glider.osg作为飞行的模型
osg::Node* glider = osgDB::readNodeFile("glider.osg");
if (glider)
{
// 根据模型的包围球来计算矩阵
// 平移到原点,缩放模型,然后沿z轴旋转-90度
const osg::BoundingSphere& bs = glider->getBound(); float size = radius/bs.radius()*0.3f;
osg::MatrixTransform* positioned = new osg::MatrixTransform;
//设置这个值在对象生命周期内为静态的不可改变的数值,或者动态的在对象生命周期内变化的值
positioned->setDataVariance(osg::Object::STATIC);
//设置转移矩阵参数
positioned->setMatrix(osg::Matrix::translate(-bs.center())* /*表示平移物体,注意osg的坐标系是z轴是向上的*/
osg::Matrix::scale(size,size,size)* /*x,y,z轴的放缩比例*/
osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f)); /*x,y,z轴的旋转角度*/ positioned->addChild(glider); // 设置动画路径的回调函数,使在渲染循环中不停的沿动画路径移动,设置坐标系变换
osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
xform->addChild(positioned); model->addChild(xform);
} // 从外部读取一个模型cessna.osg
// 操作同上,设置动画路径的回调函数,使在渲染的循环中不停的沿动画路径移动
osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
if (cessna)
{
const osg::BoundingSphere& bs = cessna->getBound(); float size = radius/bs.radius()*0.3f;
osg::MatrixTransform* positioned = new osg::MatrixTransform;
positioned->setDataVariance(osg::Object::STATIC);
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size,size,size)*
osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f)); positioned->addChild(cessna); osg::MatrixTransform* xform = new osg::MatrixTransform;
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
xform->addChild(positioned); model->addChild(xform);
} return model;
} // 创建覆盖图,根据覆盖的实现技术来设置
osg::Node* createModel(bool overlay, osgSim::OverlayNode::OverlayTechnique technique)
{
osg::Vec3 center(0.0f,0.0f,0.0f);
float radius = 100.0f; osg::Group* root = new osg::Group; // 创建底板与飞行的模型
float baseHeight = center.z()-radius*0.5;
osg::Node* baseModel = createBase(osg::Vec3(center.x(), center.y(), baseHeight),radius);
osg::Node* movingModel = createMovingModel(center,radius*0.8f); // 是否设置覆盖图
if (overlay)
{
// 根据命令行传入的参数来设置
osgSim::OverlayNode* overlayNode = new osgSim::OverlayNode(technique);
overlayNode->setContinuousUpdate(true);
// 需要设置的覆盖的图的模型为飞行的模型,当前为从外部加载的模型
overlayNode->setOverlaySubgraph(movingModel);
// 设置覆盖图距离底板的高度
overlayNode->setOverlayBaseHeight(baseHeight-0.01);
overlayNode->addChild(baseModel);
// 将覆盖图的节点加入到根节点中
root->addChild(overlayNode);
}
else
{
// 不设置覆盖图
root->addChild(baseModel);
} root->addChild(movingModel); return root;
} int main( int argc, char **argv )
{
// 是否使用覆盖模拟
bool overlay = false;
// 使用命令行参数实例化osg::ArgumentParset类,方便以后的操作
osg::ArgumentParser arguments(&argc,argv);
while (arguments.read("--overlay")) overlay = true; // 获得覆盖节点采用哪种技术实现,提供三种实现技术
osgSim::OverlayNode::OverlayTechnique technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY;
while (arguments.read("--object")) { technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
while (arguments.read("--ortho") || arguments.read("--orthographic")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
while (arguments.read("--persp") || arguments.read("--perspective")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY; overlay=true; } // initialize the viewer.
osgViewer::Viewer viewer; // 创建底板与飞行的物体,飞行物体通过外部读取
// load the nodes from the commandline arguments.
osg::Node* model = createModel(overlay, technique);
if (!model)
{
return ;
} // 创建一个osg::MatrixTransform并设置场景沿x轴旋转30度
// tilt the scene so the default eye position is looking down on the model.
osg::MatrixTransform* rootnode = new osg::MatrixTransform;
rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
rootnode->addChild(model); /// 对整个场景进行优化
// run optimization over the scene graph
osgUtil::Optimizer optimzer;
optimzer.optimize(rootnode); // 将整个节点设置到场景中进行渲染
// set the scene to render
viewer.setSceneData(rootnode); // 设置相机的操作器,当前使用跟踪球的模式进行操作
viewer.setCameraManipulator(new osgGA::TrackballManipulator()); // viewer.setUpViewOnSingleScreen(1); // 提供两中渲染的循环模式
// 第一中采用老式的模式
// 第二中采用封装模式
#if 0 // use of custom simulation time. viewer.realize(); double simulationTime = 0.0; while (!viewer.done())
{
viewer.frame(simulationTime);
simulationTime += 0.001;
} return ;
#else // normal viewer usage.
return viewer.run(); #endif
}

osgAnimation例子的注释的注释的更多相关文章

  1. HTML <!--...--> 注释 、CSS/JS //注释 和 /*.....*/ 注释

    <!-- -->是HTML的注释标签,使用<和>是符合HTML标签语法规则的. /* */(注释代码块).//(注释单行)是CSS和JS的注释标签. 两种注释有各自的使用环境, ...

  2. jsp 变量和方法的声明 Java程序片 HTML注释 JSP注释

    <%!...%> 声明变量和方法 <%!...%>之中的变量为JSP页面的成员变量,当多个线程访问本页面时,多个线程共享此变量. <%@ page contentType ...

  3. 改变Emacs下的注释代码方式以支持当前行(未选中情况下)的注释/反注释

    Emacs下支持多行代码的注释/反注释,命令是comment-or-uncomment-region. 我喜欢把它绑定在快捷键C-c C-/上,如下: (global-set-key [?\C-c ? ...

  4. Python中的注释和解注释

    注释 目标 注释的作用 单行注释(行注释) 多行注释(块注释) 01. 注释的作用 使用用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序的可读性 02. 单行注释(行注释) 以 # 开头,# ...

  5. [No000018D]Vim快速注释/取消注释多行的几种方法-Vim使用技巧(2)

    在使用Vim进行编程时,经常遇到需要快速注释或取消注释多行代码的场景,Vim教程网根据已有的教程介绍,总结了三种快速注释/取消注释多行代码的方法. 一.使用Vim可视化模式快速注释/取消注释多行 在V ...

  6. 【Python全栈】HTML <!--...--> 注释 、CSS/JS //注释 和 /*.....*/ 注释

    HTML <!--...--> 注释 .CSS/JS //注释 和 /*.....*/ 注释 <!-- -->是HTML的注释标签,使用 < 和 > 是符合HTML ...

  7. c#中//注释和///注释的区别

    c#中//注释和///注释的区别 ///会被编译,//不会所以使用///会减慢编译的速度(但不会影响执行速度)///会在其它的人调用你的代码时提供智能感知 也是一种注释,但是这种注释主要有两种作用:1 ...

  8. 【转】HTML <!--...--> 注释 、CSS/JS //注释 和 /*.....*/ 注释

    原文地址:http://www.cnblogs.com/iceflorence/p/5815409.html <!-- -->是HTML的注释标签,使用 < 和 > 是符合HT ...

  9. PLSQL常用配置之窗口/版面保存、SQL格式化/美化、SQL注释\去掉注释等快捷键配置、登陆历史修改配置

    http://blog.csdn.net/hyeidolon/article/details/8251791   PLSQL常用配置之窗口/版面保存.SQL格式化/美化.SQL注释\去掉注释等快捷键配 ...

随机推荐

  1. git版本控制管理实践-3

    git -m 和git -a -m(-am) . 的区别? usally two steps to commit files to respository: first, git add somefi ...

  2. Java牛人

    Java领域有很多著名的人物,他们为Java社区编写框架.产品.工具或撰写书籍改变了Java编程的方式.本文是<最受欢迎的8位Java牛人>的2.0版本. PS:排名不分先后.本文的信息整 ...

  3. 关于DataTable添加新列到指定列的方法

    在开发新项目的时候发现了一个问题 dtResult.Columns.Add()方法只能将指定的列添加到DataTable的列的最后的位置,但是不能添加到指定的列上.举例来说,假设dtResult总共有 ...

  4. vs2015安装体验

    后边出现这样的问题该怎么解决?

  5. python解析git log后生成页面显示git更新日志信息

    使用git log可以查到git上项目的更新日志. 如下两个git项目,我想把git的日志信息解析成一个便于在浏览器上查看的页面. https://github.com/gityf/lua https ...

  6. Java 计算数学表达式(字符串解析求值工具)

    Java字符串转换成算术表达式计算并输出结果,通过这个工具可以直接对字符串形式的算术表达式进行运算,并且使用非常简单. 这个工具中包含两个类 Calculator 和 ArithHelper Calc ...

  7. windows系统和ubuntu虚拟机之间文件共享——samba

    参考:http://www.cnblogs.com/phinecos/archive/2009/06/06/1497717.html 一. samba的安装: sudo apt-get insall  ...

  8. espcms列表页ajax无限加载

    类似百度图片的效果,滚动到底部后,点击加载更多,加载出第二页,第三页... 替代了传统的上一页,下一页,第几页,以达到在某些情况下使得用户体验更好. 二次开发方法: 1.先在模板文件中增加ajax文件 ...

  9. HikariCP

    HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池. 为何要使用HiKariCP?这要先从BoneCP说起: 什么?不是有C3P0/DBCP这些成熟的数据库连接池吗 ...

  10. Laravel 创建数据库

    1.根目录输入 php artisan migrate 2.创建表 php artisan migrate:make create_authors_table --table authors --cr ...