转自: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-10-23 05:23:59