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

  1
  2 /*  -*-c++-*-
  3 *  Copyright (C) 2008 Cedric Pinson <[email protected]>
  4 *
  5 * This library is open source and may be redistributed and/or modified under
  6 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  7 * (at your option) any later version.  The full license is in LICENSE file
  8 * included with this distribution, and on the openscenegraph.org website.
  9 *
 10 * This library is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * OpenSceneGraph Public License for more details.
 14 */
 15 #include <iostream>
 16 #include <osg/Geometry>
 17 #include <osg/MatrixTransform>
 18 #include <osg/Geode>
 19 #include <osgViewer/Viewer>
 20 #include <osgGA/TrackballManipulator>
 21 #include <osgUtil/SmoothingVisitor>
 22 #include <osg/io_utils>
 23 #include <osgAnimation/Bone>
 24 #include <osgAnimation/Skeleton>
 25 #include <osgAnimation/RigGeometry>
 26 #include <osgAnimation/Skinning>
 27 #include <osgAnimation/BasicAnimationManager>
 28
 29 // 创建的是些辅助的线条,跟随节点的运动
 30 osg::Geode* createAxis()
 31 {
 32     osg::Geode* geode (new osg::Geode());
 33     osg::Geometry* geometry (new osg::Geometry());
 34     osg::Vec3Array* vertices (new osg::Vec3Array());
 35     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
 36     vertices->push_back (osg::Vec3 ( 1.0, 0.0, 0.0));
 37     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
 38     vertices->push_back (osg::Vec3 ( 0.0, 1.0, 0.0));
 39     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
 40     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 1.0));
 41     geometry->setVertexArray (vertices);
 42     osg::Vec4Array* colors (new osg::Vec4Array());
 43     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
 44     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
 45     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
 46     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
 47     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
 48     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
 49     geometry->setColorArray (colors);
 50     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);
 51     geometry->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:INES,0,6));
 52     geode->addDrawable( geometry );
 53     return geode;
 54 }
 55 // 创建了一个等待变换的BOX
 56 osgAnimation::RigGeometry* createTesselatedBox(int nsplit, float size)
 57 {
 58     osgAnimation::RigGeometry* geometry = new osgAnimation::RigGeometry;
 59     osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
 60     osg::ref_ptr<osg::Vec3Array> colors (new osg::Vec3Array());
 61     geometry->setVertexArray (vertices.get());
 62     geometry->setColorArray (colors.get());
 63     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);
 64
 65     float step = size / nsplit;
 66     float s = 0.5/4.0;
 67     for (int i = 0; i < nsplit; i++)
 68     {
 69         float x = -1 + i * step;
 70         std::cout << x << std::endl;
 71         vertices->push_back (osg::Vec3 ( x, s, s));
 72         vertices->push_back (osg::Vec3 ( x, -s, s));
 73         vertices->push_back (osg::Vec3 ( x, -s, -s));
 74         vertices->push_back (osg::Vec3 ( x, s, -s));
 75         osg::Vec3 c (0,0,0);
 76         c[i%3] = 1;
 77         colors->push_back (c);
 78         colors->push_back (c);
 79         colors->push_back (c);
 80         colors->push_back (c);
 81     }
 82     osg::ref_ptr<osg::UIntArray> array = new osg::UIntArray;
 83     for (int i = 0; i < nsplit - 1; i++)
 84     {
 85         int base = i * 4;
 86         array->push_back(base);
 87         array->push_back(base+1);
 88         array->push_back(base+4);
 89         array->push_back(base+1);
 90         array->push_back(base+5);
 91         array->push_back(base+4);
 92         array->push_back(base+3);
 93         array->push_back(base);
 94         array->push_back(base+4);
 95         array->push_back(base+7);
 96         array->push_back(base+3);
 97         array->push_back(base+4);
 98         array->push_back(base+5);
 99         array->push_back(base+1);
100         array->push_back(base+2);
101         array->push_back(base+2);
102         array->push_back(base+6);
103         array->push_back(base+5);
104         array->push_back(base+2);
105         array->push_back(base+3);
106         array->push_back(base+7);
107         array->push_back(base+6);
108         array->push_back(base+2);
109         array->push_back(base+7);
110     }
111
112     geometry->addPrimitiveSet(new osg:rawElementsUInt(osg:rimitiveSet::TRIANGLES, array->size(), &array->front()));
113     geometry->setUseDisplayList( false );
114     return geometry;
115 }
116 // 把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
117 void initVertexMap(osgAnimation::Bone* b0,
118                    osgAnimation::Bone* b1,
119                    osgAnimation::Bone* b2,
120                    osgAnimation::RigGeometry* geom,
121                    osg::Vec3Array* array)
122 {
123     osgAnimation::VertexInfluenceSet vertexesInfluences;
124     osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap;
125     (*vim)[b0->getName()].setName(b0->getName());
126     (*vim)[b1->getName()].setName(b1->getName());
127     (*vim)[b2->getName()].setName(b2->getName());
128     for (int i = 0; i < (int)array->size(); i++)
129     {
130         float val = (*array)[0];
131         std::cout << val << std::endl;
132         // 把每个顶点的变换分配给变换节点
133         if (val >= -1 && val <= 0)
134             (*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
135         else if ( val > 0 && val <= 1)
136             (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
137         else if ( val > 1)
138             (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
139     }
140     geom->setInfluenceMap(vim);
141 }
142
143 int main (int argc, char* argv[])
144 {
145     osg::ArgumentParser arguments(&argc, argv);
146     osgViewer::Viewer viewer(arguments);
147     viewer.setCameraManipulator(new osgGA::TrackballManipulator());
148     osg::ref_ptr<osgAnimation::Skeleton> skelroot = new osgAnimation::Skeleton;
149     skelroot->setDefaultUpdateCallback();
150     // 定义一些变换位置,这些位置会在关键帧的设置用到
151     osg::ref_ptr<osgAnimation::Bone> root = new osgAnimation::Bone;
152     {
153         root->setBindMatrixInBoneSpace(osg::Matrix::identity());
154         root->setBindMatrixInBoneSpace(osg::Matrix::translate(-1,0,0));
155         root->setName("root");
156         root->setDefaultUpdateCallback();
157     }
158     osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone;
159     right0->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
160     right0->setName("right0");
161     right0->setDefaultUpdateCallback("right0");
162     osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone;
163     right1->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
164     right1->setName("right1");
165     right1->setDefaultUpdateCallback("right1");
166     // 定义变换点之间的父子关系,也就是相对变换的关系
167     root->addChild(right0.get());
168     right0->addChild(right1.get());
169     skelroot->addChild(root.get());
170     osg::Group* scene = new osg::Group;
171     osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager;
172     scene->setUpdateCallback(manager.get());
173 // 关键帧的定义,时间和位置,现在给的是旋转运动方式,更多的变换方式,可以看一下osgAnimation中的数据结构定义
174     // 定义right0的关键帧,时间和旋转
175     osgAnimation::Animation* anim = new osgAnimation::Animation;
176     {
177         osgAnimation:uatKeyframeContainer* keys0 = new osgAnimation:uatKeyframeContainer;
178         osg:uat rotate;
179         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
180         // osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))中第一个参数是时间点,单位是秒,第二个参数就是这个时间点,要旋转到的位置,本例中是旋转,也可以换成其它变换方式
181         keys0->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
182         keys0->push_back(osgAnimation:uatKeyframe(3,rotate));
183         keys0->push_back(osgAnimation:uatKeyframe(6,rotate));
184         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
185         sampler->setKeyframeContainer(keys0);
186         // osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right0->getUpdateCallback());
187         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
188         channel->setName("quaternion");
189         channel->setTargetName("right0");
190         anim->addChannel(channel);
191     }
192     // 定义right1的关键帧
193     {
194         osgAnimation:uatKeyframeContainer* keys1 = new osgAnimation:uatKeyframeContainer;
195         osg:uat rotate;
196         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
197         keys1->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
198         keys1->push_back(osgAnimation:uatKeyframe(3,osg:uat(0,0,0,1)));
199         keys1->push_back(osgAnimation:uatKeyframe(6,rotate));
200         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
201         sampler->setKeyframeContainer(keys1);
202         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
203         //osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right1->getUpdateCallback());
204         channel->setName("quaternion");
205         channel->setTargetName("right1");
206         anim->addChannel(channel);
207     }
208
209     // 把时间和位置告诉动画管理器
210     manager->registerAnimation(anim);
211     manager->buildTargetReference();
212
213     // let‘s start !   开始动画
214     manager->playAnimation(anim);
215     // we will use local data from the skeleton
216     osg::MatrixTransform* rootTransform = new osg::MatrixTransform;
217     rootTransform->setMatrix(osg::Matrix::rotate(osg:I_2,osg::Vec3(1,0,0)));
218     // 把创建的线条指示放到变换节点中,主要是一个指示作用
219     right0->addChild(createAxis());
220     // 使节点数据更新完毕后,再进行渲染动作
221     right0->setDataVariance(osg::Object:YNAMIC);
222     right1->addChild(createAxis());
223     right1->setDataVariance(osg::Object:YNAMIC);
224     //
225     osg::MatrixTransform* trueroot = new osg::MatrixTransform;
226     trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr()));
227     trueroot->addChild(createAxis());
228     trueroot->addChild(skelroot.get());
229     trueroot->setDataVariance(osg::Object:YNAMIC);
230     // trueroot也是节点,需要加到场景中去,现在是把它设置为rootTransform的一个子节点
231     rootTransform->addChild(trueroot);
232     scene->addChild(rootTransform);
233
234     // 现在创建等待变换的盒子
235     osgAnimation::RigGeometry* geom = createTesselatedBox(4, 4.0);
236     osg::Geode* geode = new osg::Geode;
237     geode->addDrawable(geom);
238     skelroot->addChild(geode);
239     osg::ref_ptr<osg::Vec3Array> src = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
240     geom->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
241     geom->setDataVariance(osg::Object:YNAMIC);
242     // 给盒子的每个顶点设置变换方式
243     initVertexMap(root.get(), right0.get(), right1.get(), geom, src.get());
244     // let‘s run !
245     viewer.setSceneData( scene );
246     viewer.realize();
247     // 开始运行了
248     while (!viewer.done())
249     {
250         viewer.frame();
251     }
252     return 0;
253 }

时间: 2024-08-03 14:23:02

OSG动画学习的相关文章

Android动画学习(缓动动画与属性动画的区别)

前言: 在 Android动画学习(概述)中,如果你看过这篇帖子,你应该会对缓动动画和属性动画之间的区别产生疑问,因为在它们的应用中,你会感觉这两种动画有着一些相似的地方,为此,我打算把这两种动画之间的区别做一下说明 区别: 在这里先附上官方文档对于这两种动画的区别说明(我所说的缓动动画对应在下文中的英文为:View Animation,属性动画对应在下文中的英文为:Property Animation): How Property Animation Differs from View Ani

Android动画学习——Tween Animation

目录 目录 Android动画学习 Tween Animation scale动画调节尺寸 alpha动画调节透明度 rotate动画旋转 translate动画平移 Android动画学习 android中动画分为3种: Tween Animation:通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生的动画效果,即是一种渐变动画. Frame Animation:顺序播放事先做好的图像,是一种画面转换动画. Property Animation:属性动画,通过动态地改变对象的属性从而达

视图动画学习算法和数据结构(二)(&lt;Garry进阶(四)&gt;)

转载请注明: 接视图动画学习算法和数据结构(不定期更新)() 快速排序(QuickSort) 动画演示: java代码: public class QuickSort { private int array[]; private int length; public void sort(int[] inputArr) { if (inputArr == null || inputArr.length == 0) { return; } this.array = inputArr; length

绘图与动画学习笔记(一)

1. 处理图形与动画的框架有 UIKit 高层次的框架,允许开发人员创建视图.窗口.按钮和其他UI相关的组件.它还将一些低级别的API引入到易于使用的高级别API中 Quartz 2D iOS上绘图的主要引擎:UIKit就使用Quartz. Core Graphics 它支持图形上下文.加载图像.绘制图像,等等. Core Animation 顾名思义,是一个帮助开发者在IOS上实现动画的框架 2. UIColor的set方法可设置Graphical context的颜色 - (void)dra

android动画学习

android动画学习 转载自:http://www.open-open.com/lib/view/open1329994048671.html 3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation. 1. View An

Silverlight动画学习笔记(三):缓动函数

(一)定义: 缓动函数:可以将自定义算术公式应用于动画 (二)为什么要用缓动函数: 您可能希望某一对象逼真地弹回或其行为像弹簧一样.您可以使用关键帧动画甚至 From/To/By 动画来大致模拟这些效果,但可能需要执行大量的工作,并且与使用算术公式相比动画的精确性将降低. (三)实例讲解: 1 <UserControl x:Class="AnimationStudy.EasingFunctionAnimation" 2 xmlns="http://schemas.mic

ios 动画学习的套路 (二)

有它们俩你就够了! 说明:下面有些概念我说的不怎么详细,网上实在是太多了,说了我觉得也意义不大了!但链接都给大家了,可以自己去看,重点梳理学习写动画的一个过程和一些好的博客! (一) 说说这两个三方库,Canvas 和 POP 这里有详细的说明了它们俩的优缺点,我们就不在粘贴复制浪费时间了,链接在下面! iOS动画库Pop和Canvas各自的优势和劣势是什么? 下面先说说这两库的基本情况完了再说说他们的使用! Canvas -- iOS 动画库 :安装就在git上看就行,点前面的就能到git链接

绘图与动画学习笔记(四)

ContextRef 详解 Graphics Context是图形上下文,可以将其理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框. Quartz提供了以下几种类型的Graphics Context: Bitmap Graphics Context PDF Graphics Context Window Graphics Context Layer Context Post Graphics Context 先熟悉下CGConte

iOS核心动画学习整理

最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一些知识做了相应的整理,整理为demo(https://github.com/PurpleSweetPotatoes/Layer_learn).此demo中都是基于教程书籍中的编程示例,并加上了注解以方便各位iOS爱好者学习使用. 在这里利用此教程中的基础知识做了2个小demo,活动指示器效果和火焰效