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. JqueryEasyUI 解决IE下加载时页面错乱的问题 分类: JavaScript JqueryEasyUI 2014-09-20 09:50 545人阅读 评论(1) 收藏

    问题描述: 一直觉得jqueryeasyui在IE下的渲染效果不大好,尤其刚进入页面时的加载,页面会出现布局错乱,虽然是一闪而过,但是给用户的体验不好: 可以通过在页面onload时,增加一个遮罩层, ...

  2. String之-如何取得精确byte长度字符串

    背景:公司生产线上出现异常,报的错是记录日志时数据库长度超出,导致异常,经查询发现是由于在计算byte长度时出了问题. 问题代码: operatorLog.setOperAfterData(updat ...

  3. POJ 3241 Object Clustering 曼哈顿最小生成树

    Object Clustering   Description We have N (N ≤ 10000) objects, and wish to classify them into severa ...

  4. struct 类型重定义

    类型定义的那个头文件只需要在功能源文件里#include 开始在主函数源文件里也#include,所以出现了重定义

  5. JMeter设置集合点

    集合点:简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点, 还拿那个用户和密码的地方,每到输入用户 ...

  6. 浅谈C++多态性

    本文转载至http://blog.csdn.net/hackbuteer1/article/details/7475622 总结: (1)区分概念:    重载----同一个类中,相同的函数名字,不同 ...

  7. 利用scp传输文件小结

    从本地复制到远程 scp mysql-5.5.29-linux2.6-x86_64.tar.gz 192.168.1.11:/opt 指定端口: scp -P 60022 /opt/ray/nginx ...

  8. class.forname()用法 转

    主要功能 Class.forName(xxx.xx.xx)返回的是一个类 Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类, 也就是说JVM会执行该类的静态代码段 ...

  9. JDK NIO编程

    我们首先需要澄清一个概念:NIO到底是什么的简称?有人称之为New I/O,因为它相对于之前的I/O类库是新增的,所以被称为New I/O,这是它的官方叫法.但是,由于之前老的I/O类库是阻塞I/O, ...

  10. css整理-02 颜色和字体

    颜色 命名颜色 RGB指定颜色 数值: 0-255 百分比 三元组:红绿蓝 16进制RGB web安全颜色 在256色计算机系统上总能避免抖动的颜色 表示为rgb值20%和51的倍数 web安全色的简 ...