OSG动画学习
2015-06-08 13:40
369 查看
OSG动画学习
转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9
学习动画,看了osganimationskinning这个例子,感觉OSG的动画实现的太灵活了.
一个简单的模型节点变换动画过程如下:
好的东西写不出来,只把这个程序的一些理解记录一下.
这个例子来自OSG的代码中的Example->osganimationskinning
View Code
转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9
学习动画,看了osganimationskinning这个例子,感觉OSG的动画实现的太灵活了.
一个简单的模型节点变换动画过程如下:
1.定义一些变换位置
2.定义动画关键帧,包含了时间,位置,旋转等数据
这里可以设置受变化作用的节点
3.给节点设置一个动画管理器,这个动画管理器是继承自Osg::NodeCallback,所以其实是个Callback类.
4.把定义的关键帧的数据,送给动画管理器
5.创建一个等待变化的节点
6.把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
7.开始动画
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,0,6)); 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 = 0; i < nsplit; i++) { float x = -1 + 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 (0,0,0); c[i%3] = 1; 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 = 0; i < nsplit - 1; i++) { int base = i * 4; array->push_back(base); array->push_back(base+1); array->push_back(base+4); array->push_back(base+1); array->push_back(base+5); array->push_back(base+4); array->push_back(base+3); array->push_back(base); array->push_back(base+4); array->push_back(base+7); array->push_back(base+3); array->push_back(base+4); array->push_back(base+5); array->push_back(base+1); array->push_back(base+2); array->push_back(base+2); array->push_back(base+6); array->push_back(base+5); array->push_back(base+2); array->push_back(base+3); array->push_back(base+7); array->push_back(base+6); array->push_back(base+2); array->push_back(base+7); } 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 = 0; i < (int)array->size(); i++) { float val = (*array)[0]; std::cout << val << std::endl; // 把每个顶点的变换分配给变换节点 if (val >= -1 && val <= 0) (*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,1)); else if ( val > 0 && val <= 1) (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1)); else if ( val > 1) (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1)); } 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(-1,0,0)); root->setName("root"); root->setDefaultUpdateCallback(); } osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone; right0->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0)); right0->setName("right0"); right0->setDefaultUpdateCallback("right0"); osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone; right1->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0)); 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(0,0,1)); // osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))中第一个参数是时间点,单位是秒,第二个参数就是这个时间点,要旋转到的位置,本例中是旋转,也可以换成其它变换方式 keys0->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))); keys0->push_back(osgAnimation:uatKeyframe(3,rotate)); keys0->push_back(osgAnimation:uatKeyframe(6,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(0,0,1)); keys1->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))); keys1->push_back(osgAnimation:uatKeyframe(3,osg:uat(0,0,0,1))); keys1->push_back(osgAnimation:uatKeyframe(6,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(1,0,0))); // 把创建的线条指示放到变换节点中,主要是一个指示作用 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, 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 0; }
View Code
相关文章推荐
- (图片处理)Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解
- c/c++ define用法
- 运行FIRE FOX无法正常启动
- Cocos2d-x项目的游戏框架搭建
- Ubuntu环境下Hadoop的安装与配置步骤
- 前瞻性_个人经历
- windows2012R2-工作文件夹:服务器及客户端设置(win8&7)
- poj 3278 Catch That Cow
- 我的java web登录RSA加密
- C API向MySQL插入批量数据的快速方法——关于mysql_autocommit
- HTTP请求头和响应头注释
- JS过滤url参数中的特殊字符
- Linux ./configure && make && make install 编译安装和卸载
- 赛门铁克加速NSX安全化编排,或将拥抱ACI
- SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
- 记Handler机制中的一个小点
- Ngnix 安装、信号量、虚拟主机配置
- Rectangle Area || LeetCode
- ndk入门基础demo
- OpenVSwitch简单容易入门