OSG动画学习

转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9

学习动画,看了osganimationskinning这个例子,感觉OSG的动画实现的太灵活了.
一个简单的模型节点变换动画过程如下:

1.定义一些变换位置
2.定义动画关键帧,包含了时间,位置,旋转等数据
这里可以设置受变化作用的节点
3.给节点设置一个动画管理器,这个动画管理器是继承自Osg::NodeCallback,所以其实是个Callback类.
4.把定义的关键帧的数据,送给动画管理器
5.创建一个等待变化的节点
6.把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
7.开始动画

好的东西写不出来,只把这个程序的一些理解记录一下.
这个例子来自OSG的代码中的Example->osganimationskinning

 /*  -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <iostream>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgUtil/SmoothingVisitor>
#include <osg/io_utils>
#include <osgAnimation/Bone>
#include <osgAnimation/Skeleton>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/Skinning>
#include <osgAnimation/BasicAnimationManager> // 创建的是些辅助的线条,跟随节点的运动
osg::Geode* createAxis()
{
osg::Geode* geode (new osg::Geode());
osg::Geometry* geometry (new osg::Geometry());
osg::Vec3Array* vertices (new osg::Vec3Array());
vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
vertices->push_back (osg::Vec3 ( 1.0, 0.0, 0.0));
vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
vertices->push_back (osg::Vec3 ( 0.0, 1.0, 0.0));
vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
vertices->push_back (osg::Vec3 ( 0.0, 0.0, 1.0));
geometry->setVertexArray (vertices);
osg::Vec4Array* colors (new osg::Vec4Array());
colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
geometry->setColorArray (colors);
geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:INES,,));
geode->addDrawable( geometry );
return geode;
}
// 创建了一个等待变换的BOX
osgAnimation::RigGeometry* createTesselatedBox(int nsplit, float size)
{
osgAnimation::RigGeometry* geometry = new osgAnimation::RigGeometry;
osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
osg::ref_ptr<osg::Vec3Array> colors (new osg::Vec3Array());
geometry->setVertexArray (vertices.get());
geometry->setColorArray (colors.get());
geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX); float step = size / nsplit;
float s = 0.5/4.0;
for (int i = ; i < nsplit; i++)
{
float x = - + i * step;
std::cout << x << std::endl;
vertices->push_back (osg::Vec3 ( x, s, s));
vertices->push_back (osg::Vec3 ( x, -s, s));
vertices->push_back (osg::Vec3 ( x, -s, -s));
vertices->push_back (osg::Vec3 ( x, s, -s));
osg::Vec3 c (,,);
c[i%] = ;
colors->push_back (c);
colors->push_back (c);
colors->push_back (c);
colors->push_back (c);
}
osg::ref_ptr<osg::UIntArray> array = new osg::UIntArray;
for (int i = ; i < nsplit - ; i++)
{
int base = i * ;
array->push_back(base);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
array->push_back(base+);
} geometry->addPrimitiveSet(new osg:rawElementsUInt(osg:rimitiveSet::TRIANGLES, array->size(), &array->front()));
geometry->setUseDisplayList( false );
return geometry;
}
// 把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
void initVertexMap(osgAnimation::Bone* b0,
osgAnimation::Bone* b1,
osgAnimation::Bone* b2,
osgAnimation::RigGeometry* geom,
osg::Vec3Array* array)
{
osgAnimation::VertexInfluenceSet vertexesInfluences;
osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap;
(*vim)[b0->getName()].setName(b0->getName());
(*vim)[b1->getName()].setName(b1->getName());
(*vim)[b2->getName()].setName(b2->getName());
for (int i = ; i < (int)array->size(); i++)
{
float val = (*array)[];
std::cout << val << std::endl;
// 把每个顶点的变换分配给变换节点
if (val >= - && val <= )
(*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,));
else if ( val > && val <= )
(*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,));
else if ( val > )
(*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,));
}
geom->setInfluenceMap(vim);
} int main (int argc, char* argv[])
{
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
osg::ref_ptr<osgAnimation::Skeleton> skelroot = new osgAnimation::Skeleton;
skelroot->setDefaultUpdateCallback();
// 定义一些变换位置,这些位置会在关键帧的设置用到
osg::ref_ptr<osgAnimation::Bone> root = new osgAnimation::Bone;
{
root->setBindMatrixInBoneSpace(osg::Matrix::identity());
root->setBindMatrixInBoneSpace(osg::Matrix::translate(-,,));
root->setName("root");
root->setDefaultUpdateCallback();
}
osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone;
right0->setBindMatrixInBoneSpace(osg::Matrix::translate(,,));
right0->setName("right0");
right0->setDefaultUpdateCallback("right0");
osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone;
right1->setBindMatrixInBoneSpace(osg::Matrix::translate(,,));
right1->setName("right1");
right1->setDefaultUpdateCallback("right1");
// 定义变换点之间的父子关系,也就是相对变换的关系
root->addChild(right0.get());
right0->addChild(right1.get());
skelroot->addChild(root.get());
osg::Group* scene = new osg::Group;
osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager;
scene->setUpdateCallback(manager.get());
// 关键帧的定义,时间和位置,现在给的是旋转运动方式,更多的变换方式,可以看一下osgAnimation中的数据结构定义
// 定义right0的关键帧,时间和旋转
osgAnimation::Animation* anim = new osgAnimation::Animation;
{
osgAnimation:uatKeyframeContainer* keys0 = new osgAnimation:uatKeyframeContainer;
osg:uat rotate;
rotate.makeRotate(osg:I_2, osg::Vec3(,,));
// osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))中第一个参数是时间点,单位是秒,第二个参数就是这个时间点,要旋转到的位置,本例中是旋转,也可以换成其它变换方式
keys0->push_back(osgAnimation:uatKeyframe(,osg:uat(,,,)));
keys0->push_back(osgAnimation:uatKeyframe(,rotate));
keys0->push_back(osgAnimation:uatKeyframe(,rotate));
osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
sampler->setKeyframeContainer(keys0);
// osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right0->getUpdateCallback());
osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
channel->setName("quaternion");
channel->setTargetName("right0");
anim->addChannel(channel);
}
// 定义right1的关键帧
{
osgAnimation:uatKeyframeContainer* keys1 = new osgAnimation:uatKeyframeContainer;
osg:uat rotate;
rotate.makeRotate(osg:I_2, osg::Vec3(,,));
keys1->push_back(osgAnimation:uatKeyframe(,osg:uat(,,,)));
keys1->push_back(osgAnimation:uatKeyframe(,osg:uat(,,,)));
keys1->push_back(osgAnimation:uatKeyframe(,rotate));
osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
sampler->setKeyframeContainer(keys1);
osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
//osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right1->getUpdateCallback());
channel->setName("quaternion");
channel->setTargetName("right1");
anim->addChannel(channel);
} // 把时间和位置告诉动画管理器
manager->registerAnimation(anim);
manager->buildTargetReference(); // let's start ! 开始动画
manager->playAnimation(anim);
// we will use local data from the skeleton
osg::MatrixTransform* rootTransform = new osg::MatrixTransform;
rootTransform->setMatrix(osg::Matrix::rotate(osg:I_2,osg::Vec3(,,)));
// 把创建的线条指示放到变换节点中,主要是一个指示作用
right0->addChild(createAxis());
// 使节点数据更新完毕后,再进行渲染动作
right0->setDataVariance(osg::Object:YNAMIC);
right1->addChild(createAxis());
right1->setDataVariance(osg::Object:YNAMIC);
//
osg::MatrixTransform* trueroot = new osg::MatrixTransform;
trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr()));
trueroot->addChild(createAxis());
trueroot->addChild(skelroot.get());
trueroot->setDataVariance(osg::Object:YNAMIC);
// trueroot也是节点,需要加到场景中去,现在是把它设置为rootTransform的一个子节点
rootTransform->addChild(trueroot);
scene->addChild(rootTransform); // 现在创建等待变换的盒子
osgAnimation::RigGeometry* geom = createTesselatedBox(, 4.0);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geom);
skelroot->addChild(geode);
osg::ref_ptr<osg::Vec3Array> src = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
geom->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
geom->setDataVariance(osg::Object:YNAMIC);
// 给盒子的每个顶点设置变换方式
initVertexMap(root.get(), right0.get(), right1.get(), geom, src.get());
// let's run !
viewer.setSceneData( scene );
viewer.realize();
// 开始运行了
while (!viewer.done())
{
viewer.frame();
}
return ;
}

OSG动画学习的更多相关文章

  1. Android动画学习(二)——Tween Animation

    前两天写过一篇Android动画学习的概述,大致的划分了下Android Animation的主要分类,没有看过的同学请移步:Android动画学习(一)——Android动画系统框架简介.今天接着来 ...

  2. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  3. android动画学习

    android动画学习   转载自:http://www.open-open.com/lib/view/open1329994048671.html 3.0以前,android支持两种动画模式,twe ...

  4. ios 动画学习的套路 (二)

    有它们俩你就够了! 说明:下面有些概念我说的不怎么详细,网上实在是太多了,说了我觉得也意义不大了!但链接都给大家了,可以自己去看,重点梳理学习写动画的一个过程和一些好的博客! (一) 说说这两个三方库 ...

  5. iOS动画学习-视觉效果

    CALayer不仅仅是iOS动画学习-CALayer中介绍的那些内容,他还有一些其他属性,比如shadowColor,borderWidth,borderColor等等,这些属性我们只需要简单点设置就 ...

  6. Unity Shader序列帧动画学习笔记

    Unity Shader序列帧动画学习笔记 关于无限播放序列帧动画的一点问题 在学shader的序列帧动画时,书上写了这样一段代码: fixed4 frag(v2f i){ // 获得整数时间 flo ...

  7. HTML5 Canvas画图与动画学习59例

    HTML5 Canvas画图与动画学习59例 学习HTML5 动画,画图的好资料. HTML5 Canvas画图与动画学习59例

  8. iOS核心动画学习整理

    最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...

  9. Windows Phone 7 ListBox 列表项渐显加载动画学习笔记

    在wp7程序中,当程序功能越来越复杂时,性能问题是我们不得不考虑的一个问题.在聊天列表中,如果聊天项过多,而且项目UI组件足够复杂时, 我们不得不想尽办法让UI尽快加载.所以有一种可行的方案,就是像Q ...

随机推荐

  1. android 入门-Activity及 字体

    private Button sButton; private TextView mTextView; private Button fButton; ,,,,}; @Override protect ...

  2. linux SecureCRT ssh key认证登陆

    转自:http://blog.chinaunix.net/uid-20639775-id-3207171.html 通过SecureCRT创建key登录认证 一.生成公钥/密钥对 使用SecureCR ...

  3. 11g添加asm

    1.创建组 2.创建grid用户 3.用grid安装Gride Infrastructure软件 4.执行root.sh[root@ora11g softdb]# /u01/app/11.2.0/gr ...

  4. CRC校验(转)

    CRC即循环冗余校验码(Cyclic Redundancy Check[1] ):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据 ...

  5. cocos2dx游戏开发——微信打飞机学习笔记(一)——开发准备

    一.环境的搭建 1.Windows开发准备: (1)软件下载及安装 •下载Cocos2d-x 最新版本:http://www.cocos2d-x.org/download 或者从Cocos2d-x G ...

  6. 【Tomcat】直接启动tomcat时为tomcat指定JDK 而不是读取环境变量中的配置

    在windows环境下以批处理文件方式启动tomcat,只要运行<CATALINA_HOME>/bin/startup.bat这个文件,就可以启动Tomcat.在启动时,startup.b ...

  7. 梳理源码中 View 的工作原理

    欢迎Follow我的GitHub, 关注我的掘金. 在View的工作过程中, 执行三大流程完成显示, 测量(measure)流程, 布局(layout)流程, 绘制(draw)流程. 从perform ...

  8. python 类型判断-- isinstance函数

    判断类型 函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str.list.dict,也可以用在我们自定义的类,它们本质上都是数据类型. 假设有如下的 Per ...

  9. Spring常用工具类

    Spring框架下自带了丰富的工具类,在我们开发时可以简化很多工作: 1.Resource访问文件资源: 具体有: ResourceUtils.getFile(url); FileSystemReso ...

  10. POJ 1635 树的最小表示法/HASH

    题目链接:http://poj.org/problem?id=1635 题意:给定两个由01组成的串,0代表远离根,1代表接近根.相当于每个串对应一个有根的树.然后让你判断2个串构成的树是否是同构的. ...