经过近三天的纠结,终于将《
OpenSceneGraph
三维渲染引擎编程指南》中带有的骨骼动画
osgCal
示例运行成功。写篇总结纪念这逝去的三天,同时给各位童鞋做个参考,希望大家少走弯路。
首先对 Cal3D 做一个简单地介绍。 Cal3D 是一个开源的骨骼动画引擎,它是基于关键帧的骨骼动画,数据文件分为骨骼( Skeleton )、网格( Mesh )和动画( Animation ) 3 个部分,由一个文本文件管理( cal3d.cfg) ,可以定义多个动作,但每个动画文件是相互独立的。它同时支持动作混合,即可以同时实现两个独立的动作协同一起。其中,每一个动作都有一个权重,即不同的动作优先级是不一样的,通常来说,运动类动作优先级会高于循环类动画。因此,它在渲染过程中的效果是比较好的,管理也是很方便,可以通过修改文本配置文件 (.cfg) 来管理动画制作信息。
1. 运行环境: win7+X86+vs2008( 这是我机器的运行环境,只供参考 )
2. 硬件要求:
2.1 CMake-2.8.7 (可以直接去官方下载安装版的 CMake ,只需一步 next 就可以轻易安装,下载地址: http://www.cmake.org/cmake/resources/software.html )
2.2 SVN 源码下载工具。这是一个非常常见的源码下载工具,很多开源的网站就直接提供 svn 链接,就可以轻易获取最新版本的源码;很多中小型软件开发团队也是会用到该工具,用于代码的上传更新,下载共享,实现多人维护代码。下载地址: http://tortoisesvn.net/
相关使用的教程:
http://dev.baidu.com/wiki/app/index.php?title=SVN%E6%95%99%E7%A8%8B#.E6.96.B0.E5.A2.9E.E6.96.87.E4.BB.B6.E5.92.8C.E7.9B.AE.E5.BD.95
2.3 编译好的 osg( 我用的是 OpenSceneGraph-2.8.2 ,虽然版本稍微有点老,但是不影响正常的使用,也就无所谓了。现在最新版本是,可以去中国官网下载: http://www.osgchina.org/projects/osgcn/wiki.php )
OSG 编译的教程: http://hi.baidu.com/kdlichao/blog/item/18852ad5d7cd95249a502702.html
2.4 编译好的 Cal3D 。
2.5 编译好的 osgCal 。
(下面将详细讲解 Cal3D 和 osgCal 的编译。)
3. 编译 Cal3D ,目的就是得到 cal3d_d.lib 、 cal3d_d.dll 及 cal3d.lib , cal3d.dll ,后面编译 osgCal 依赖 cal3d 库文件(本例中只用到库文件,动态库只是附属物)。
cal3d 源码获取,通过 SVN 获取最新的源码,最新源码下载地址:
http://svn.gna.org/svn/cal3d/trunk 。
下载的源码文件包含以下三个文件夹
打开 cal3d ,找到 cal3d.sln ,打开该工程,包含以下 12 个工程,
这里我们只需要build Cal3D 工程,选择该工程,右击,在弹出框中选中 build ,单击。等待几分钟就可以在 bin 文件下的 Debug 和 Releas 得到 cal3d_d.lib 、 cal3d_d.dll ( debug 模式)及 cal3d.lib 、 cal3d.dll ( release 模式)。
在 cal3d 目录下新建 lib 、 include 文件夹,将 cal3d_d.dll 、 cal3d.dll 拷贝到 bin 文件; cal3d_d.lib 、 cal3d.lib 拷贝到 lib 文件夹;将 src 的所以文件拷贝到 include 文件夹。
可以依据需要编译其他工程,如果编译
max ( maya )的 cal3d 导出插件,那么需要安装 max ( maya) 软件,并且在 Tools-Options-Projects and Solutions-C++ Directories 的包含文件添加 max(maya) 安装目录下的 include 路径,库文件添加对应的 lib 路径。其他的例子工程可以随便 build 了,但是我没有明白这些例子工程到底是干啥用的,留着以后探讨吧。
到这里编译 osgCal 的准备工作就完成了。
4. 编译 osgCal ,编译 osgCal 就是为了得到 osgCald.dll 、 osgCald.lib 及 osgCal.dll 、 osgCal.lib (后面带 d 的是在 dubeg 模式下得到的,不带的是 release 模式)。
svn 获取最新源码,最新源码获取地址:
https://osgcal.svn.sourceforge.net/svnroot/osgcal/trunk/osgCal 及
https://osgcal.svn.sourceforge.net/svnroot/osgcal/trunk/models
(本示例中只用到 osgCal ,模型 models 没有用到,具体实现什么功能,目前没有整明白)
打开 Cmake ,生成 osgCal 解决方案。
将 osgCal 文件下的 CMakeLists.txt 拖到 CMake 2.8.7 。
点击 Configure ,选择编译的环境
安装下面的要求,配置参数。
这是重点,一不小心,就在载在这里了!!
这里的 include 路径及 lib 文件几乎都是手动加过去的。
对几个重要的参数作个解释:
CAL3D_INCLUDE_DIR cal3d 的 include 文件的路径( E:/cal3d/cal3d/include )
CAL3D_ LIBRARY cal3d 的 lib 文件( E:/cal3d/cal3d/lib/cal3d_d.lib )
OPEN_THREADS_INCLUDE_DIR
OpenThreads 的 include 路径
(D:/osgSDK/OpenSceneGraph-2.8.2/include/OpenThreads)
OPEN_THREADS_LIBTARY
OpenThreads 的 lib 路径 (D:/osgSDK/OpenSceneGraph-2.8.2/lib/OpenThreads)
OSG_INCLUDE_DIR
osg 的 include 文件路径( D:/osgSDK/OpenSceneGraph-2.8.2/include )
OSG_LIBRARY
osg 的 lib 文件( D:/osgSDK/OpenSceneGraph-2.8.2/lib/osg.lib )
根据 SDK 所在的位置指定正确的路径。
参数配置完毕后,第二次点击 configure 。
确定无误后点击 Generate ,显示 Configuring done,表明配置成功,将生成解决方案。
注意:这里 include 及 lib 路径要与 osgCal 工程下的 Tools-Options-Projects and Solutions-C++ Directories 的 include 及 lib 路径相一致。要是在 CMake 中未添加这些 include 及 lib 路径(前提是 Generating done ),在工程中再添加 include 及 lib 路径也是可以的。 Cmake 中允许有警告,但是不要有错误,否则编译会通不过去。
打开 osgCal.sln 解决方案,
注意:检查Tools-Options-Projects and Solutions-C++ Directories 中的 include 及 lib 路径是否正确。
Build ALL_BUILD 。等待十几分钟,显示 6 succeeded,0 faild ,表明编译成功。
将 osgCald.dll 、 osgCal.dll 拷贝到 bin 文件; osgCald.lib 、 osgCal.lib 拷贝到 lib 文件夹。
经过千辛万苦,终于得到了所需要的 osgCald.dll 、 osgCal.dll 及 osgCald.lib 、 osgCal.lib 。下面可以开始跑例子了,检验一下生成的库文件及动态库是否正确。
5. 配置 osgCal 环境,运行 osgCal 骨骼示例。
开始 - 控制面板 - 系统和安全 - 系统 - 高级系统设置 - 高级 - 环境变量 - 用户变量 -PATH 添加 osgCald.dll 、 osgCal.dll 的路径。
新建工程 win32 控制台工程,工程命名 skeleton ,将代码粘贴至 skeleton.cpp 。代码下载地址:
http://read.pudn.com/downloads156/sourcecode/windows/opengl/695085/Cal3D%E5%8A%A8%E7%94%BB%E7%9A%84%E5%8A%A0%E8%BD%BD%E3%80%81%E6%98%BE%E7%A4%BA%E5%8F%8A%E6%8E%A7%E5%88%B6%E7%A4%BA%E4%BE%8B/osgVR/main.cpp__.htm
骨骼模型下载地址:
http://ftp.jaist.ac.jp/pub/sourceforge/o/project/os/osgcal/test_models/0.0.1/
Tools-Options-Projects and Solutions-C++ Directories 添加 osgCal 的 include 及 bin 路径。
Project-Properties-Configuration Properties-Linker-Input-Additional 添加依赖库
osg.lib
osgDB.lib
osgGA.lib
osgUtil.lib
osgViewer.lib
osgCal.lib
这里选择的是 Release 模式。
编译工程,运行。将会展示如下的
示例的骨骼动画是非常生动的。有以下几种模式:
animation=skeleton_idle.caf
animation=skeleton_strut.caf
animation=skeleton_walk.caf
animation=skeleton_jog.caf
animation=skeleton_wave.caf
animation=skeleton_shoot_arrow.caf
animation=skeleton_hiphop.caf
按“ 1 ”对应的是 idle ,按“ 2 ”对应的是 strut ,按“ 3 ”对应的是 walk , ....
好了!我们的 osgCal 例子运行成功, enjoy !!
最后附上源码:
/**********************************************************
*Write by FlySky
* zzuxp@163.com http://www.OsgChina.org
**********************************************************/
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/TrackballManipulator>
#include <osg/BoundingSphere>
#include <osgUtil/Optimizer>
#include <osgCal/CoreModel>
#include <osgCal/Model>
#include <iostream>
//加载模型
osg::Node* makeModel( osgCal::CoreModel* cm,osgCal::BasicMeshAdder* ma, int animNum = -1 )
{
osgCal::Model* model = new osgCal::Model();
//从CoreModel中创建模型
model->load( cm, ma );
if ( animNum != -1 )
{
//实现动画
model->blendCycle( animNum, 1.0f, 0 );
}
return model;
}
//动画控制事件处理器
class AnimationToggleHandler : public osgGA::GUIEventHandler
{
public:
//构造函数
AnimationToggleHandler( osgCal::Model* m,
const std::vector <std::string >& an )
: model( m )
, animationNames( an )
, currentAnimation( -1 )
{
//
}
//事件处理函数
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
if ( ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL )
{
if ( ea.getKey() >= '1' &&
ea.getKey() < '1' + (int)animationNames.size() )
{
//执行动作
model->executeAction( ea.getKey()- '1' );
}
}
else if ( ea.getKey() >= '1' &&
ea.getKey() < '1' + (int)animationNames.size() )
{
//重新初始化
if ( currentAnimation != -1 )
{
model->clearCycle( currentAnimation, 1.0 );
}
currentAnimation = ea.getKey() - '1';
//循环动作
model->blendCycle(currentAnimation, 1.0f, 1.0 );
}
//清除当前动作,重置初始动作
else if ( ea.getKey() == '0' )
{
model->clearCycle( currentAnimation, 0.0 );
currentAnimation = -1;
}
}
default: break;
}
return false;
}
private:
//动画模型
osgCal::Model* model;
//动画动作名称
std::vector <std::string > animationNames;
//当前动作
int currentAnimation;
};
//暂停或者渲染状态切换事件处理器
class ToggleHandler : public osgGA::GUIEventHandler
{
public:
ToggleHandler( bool& toggleVar,char key):
toggleVar( &toggleVar ),
key( key )
{
//
}
//事件处理函数
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
if ( ea.getKey() == key )
{
//切换状态
*toggleVar = !(*toggleVar);
}
}
default: break;
}
return false;
}
private:
//当前状态
bool* toggleVar;
//按键
char key;
};
int main()
{
//创建场景浏览器
osgViewer::Viewer* viewer = new osgViewer::Viewer();
osg::Group* root = new osg::Group();
//一系列动作名
std::vector <std::string > animationNames;
//动画模型名
std::string fn("E:\\OSG\\osgCalByflySky\\test_models\\thug\\cal3d.cfg"); //skeleton\\skeleton hero\\hero
//初始化静止模型动作
int animNum = -1;
//动画模型
osgCal::CoreModel* coreModel = new osgCal::CoreModel();
//基本网格
osgCal::BasicMeshAdder* meshAdder= new osgCal: efaultMeshAdder ();
//网格参数
osgCal::MeshParameters* p = new osgCal::MeshParameters();
//采用深度,用于减少子网被遮盖的不可见的像素
p->useDepthFirstMesh = true ;
//平滑模式
p->software = true ;
//加载外部模型文件
coreModel->load( fn, p);
//添加模型
root->addChild( makeModel( coreModel,meshAdder,animNum ) );
//得到一系列动作名称
animationNames = coreModel->getAnimationNames();
//动作切换控制
viewer->addEventHandler( new AnimationToggleHandler( (osgCal::Model*)root->getChild(0), animationNames ) );
//暂停控制
bool paused = false;
viewer->addEventHandler( new ToggleHandler( paused, 'p' ) );
//优化场景数据
osgUtil::Optimizer optimizer ;
optimizer.optimize(root);
viewer->setSceneData(root);
viewer->setCameraManipulator(new osgGA::TrackballManipulator());
viewer->realize();
//添加时间控制
osg::Timer_t startTick = osg::Timer::instance()->tick();
//初始化一个状态枚举变量,控制暂停或者渲染
//默认为渲染状态
enum PauseState { Unpaused, Paused };
PauseState pauseState = Unpaused;
osg::Timer_t pauseStartTick = 0;
double totalPauseTime = 0;
//通过控制当前帧显示时间,来控制是否暂停或者渲染
while ( !viewer->done() )
{
osg::Timer_t tick = osg::Timer::instance()->tick();
//暂停
if ( pauseState == Unpaused && paused )
{
pauseState = Paused;
pauseStartTick = tick;
}
//渲染
if ( pauseState == Paused && !paused )
{
pauseState = Unpaused;
//得到暂停时间
totalPauseTime += osg::Timer::instance()->delta_s( pauseStartTick, tick );
}
//当前时间
double currentTime = osg::Timer::instance()->delta_s(
startTick,
pauseState == Unpaused ? tick : pauseStartTick );
//继续暂停帧开始渲染
viewer->frame( currentTime - totalPauseTime );
}
return 0;
}
[/code]
再给大家提供一个cal3d格式的骨骼模型。enjoy!!
欢迎转载,转载请注明: http://www.cnkinect.com/forum.php?mod=viewthread&tid=15697&page=1&extra=
首先对 Cal3D 做一个简单地介绍。 Cal3D 是一个开源的骨骼动画引擎,它是基于关键帧的骨骼动画,数据文件分为骨骼( Skeleton )、网格( Mesh )和动画( Animation ) 3 个部分,由一个文本文件管理( cal3d.cfg) ,可以定义多个动作,但每个动画文件是相互独立的。它同时支持动作混合,即可以同时实现两个独立的动作协同一起。其中,每一个动作都有一个权重,即不同的动作优先级是不一样的,通常来说,运动类动作优先级会高于循环类动画。因此,它在渲染过程中的效果是比较好的,管理也是很方便,可以通过修改文本配置文件 (.cfg) 来管理动画制作信息。
1. 运行环境: win7+X86+vs2008( 这是我机器的运行环境,只供参考 )
2. 硬件要求:
2.1 CMake-2.8.7 (可以直接去官方下载安装版的 CMake ,只需一步 next 就可以轻易安装,下载地址: http://www.cmake.org/cmake/resources/software.html )
2.2 SVN 源码下载工具。这是一个非常常见的源码下载工具,很多开源的网站就直接提供 svn 链接,就可以轻易获取最新版本的源码;很多中小型软件开发团队也是会用到该工具,用于代码的上传更新,下载共享,实现多人维护代码。下载地址: http://tortoisesvn.net/
相关使用的教程:
http://dev.baidu.com/wiki/app/index.php?title=SVN%E6%95%99%E7%A8%8B#.E6.96.B0.E5.A2.9E.E6.96.87.E4.BB.B6.E5.92.8C.E7.9B.AE.E5.BD.95
2.3 编译好的 osg( 我用的是 OpenSceneGraph-2.8.2 ,虽然版本稍微有点老,但是不影响正常的使用,也就无所谓了。现在最新版本是,可以去中国官网下载: http://www.osgchina.org/projects/osgcn/wiki.php )
OSG 编译的教程: http://hi.baidu.com/kdlichao/blog/item/18852ad5d7cd95249a502702.html
2.4 编译好的 Cal3D 。
2.5 编译好的 osgCal 。
(下面将详细讲解 Cal3D 和 osgCal 的编译。)
3. 编译 Cal3D ,目的就是得到 cal3d_d.lib 、 cal3d_d.dll 及 cal3d.lib , cal3d.dll ,后面编译 osgCal 依赖 cal3d 库文件(本例中只用到库文件,动态库只是附属物)。
cal3d 源码获取,通过 SVN 获取最新的源码,最新源码下载地址:
http://svn.gna.org/svn/cal3d/trunk 。
下载的源码文件包含以下三个文件夹
打开 cal3d ,找到 cal3d.sln ,打开该工程,包含以下 12 个工程,
这里我们只需要build Cal3D 工程,选择该工程,右击,在弹出框中选中 build ,单击。等待几分钟就可以在 bin 文件下的 Debug 和 Releas 得到 cal3d_d.lib 、 cal3d_d.dll ( debug 模式)及 cal3d.lib 、 cal3d.dll ( release 模式)。
在 cal3d 目录下新建 lib 、 include 文件夹,将 cal3d_d.dll 、 cal3d.dll 拷贝到 bin 文件; cal3d_d.lib 、 cal3d.lib 拷贝到 lib 文件夹;将 src 的所以文件拷贝到 include 文件夹。
可以依据需要编译其他工程,如果编译
max ( maya )的 cal3d 导出插件,那么需要安装 max ( maya) 软件,并且在 Tools-Options-Projects and Solutions-C++ Directories 的包含文件添加 max(maya) 安装目录下的 include 路径,库文件添加对应的 lib 路径。其他的例子工程可以随便 build 了,但是我没有明白这些例子工程到底是干啥用的,留着以后探讨吧。
到这里编译 osgCal 的准备工作就完成了。
4. 编译 osgCal ,编译 osgCal 就是为了得到 osgCald.dll 、 osgCald.lib 及 osgCal.dll 、 osgCal.lib (后面带 d 的是在 dubeg 模式下得到的,不带的是 release 模式)。
svn 获取最新源码,最新源码获取地址:
https://osgcal.svn.sourceforge.net/svnroot/osgcal/trunk/osgCal 及
https://osgcal.svn.sourceforge.net/svnroot/osgcal/trunk/models
(本示例中只用到 osgCal ,模型 models 没有用到,具体实现什么功能,目前没有整明白)
打开 Cmake ,生成 osgCal 解决方案。
将 osgCal 文件下的 CMakeLists.txt 拖到 CMake 2.8.7 。
点击 Configure ,选择编译的环境
安装下面的要求,配置参数。
这是重点,一不小心,就在载在这里了!!
这里的 include 路径及 lib 文件几乎都是手动加过去的。
对几个重要的参数作个解释:
CAL3D_INCLUDE_DIR cal3d 的 include 文件的路径( E:/cal3d/cal3d/include )
CAL3D_ LIBRARY cal3d 的 lib 文件( E:/cal3d/cal3d/lib/cal3d_d.lib )
OPEN_THREADS_INCLUDE_DIR
OpenThreads 的 include 路径
(D:/osgSDK/OpenSceneGraph-2.8.2/include/OpenThreads)
OPEN_THREADS_LIBTARY
OpenThreads 的 lib 路径 (D:/osgSDK/OpenSceneGraph-2.8.2/lib/OpenThreads)
OSG_INCLUDE_DIR
osg 的 include 文件路径( D:/osgSDK/OpenSceneGraph-2.8.2/include )
OSG_LIBRARY
osg 的 lib 文件( D:/osgSDK/OpenSceneGraph-2.8.2/lib/osg.lib )
根据 SDK 所在的位置指定正确的路径。
参数配置完毕后,第二次点击 configure 。
确定无误后点击 Generate ,显示 Configuring done,表明配置成功,将生成解决方案。
注意:这里 include 及 lib 路径要与 osgCal 工程下的 Tools-Options-Projects and Solutions-C++ Directories 的 include 及 lib 路径相一致。要是在 CMake 中未添加这些 include 及 lib 路径(前提是 Generating done ),在工程中再添加 include 及 lib 路径也是可以的。 Cmake 中允许有警告,但是不要有错误,否则编译会通不过去。
打开 osgCal.sln 解决方案,
注意:检查Tools-Options-Projects and Solutions-C++ Directories 中的 include 及 lib 路径是否正确。
Build ALL_BUILD 。等待十几分钟,显示 6 succeeded,0 faild ,表明编译成功。
将 osgCald.dll 、 osgCal.dll 拷贝到 bin 文件; osgCald.lib 、 osgCal.lib 拷贝到 lib 文件夹。
经过千辛万苦,终于得到了所需要的 osgCald.dll 、 osgCal.dll 及 osgCald.lib 、 osgCal.lib 。下面可以开始跑例子了,检验一下生成的库文件及动态库是否正确。
5. 配置 osgCal 环境,运行 osgCal 骨骼示例。
开始 - 控制面板 - 系统和安全 - 系统 - 高级系统设置 - 高级 - 环境变量 - 用户变量 -PATH 添加 osgCald.dll 、 osgCal.dll 的路径。
新建工程 win32 控制台工程,工程命名 skeleton ,将代码粘贴至 skeleton.cpp 。代码下载地址:
http://read.pudn.com/downloads156/sourcecode/windows/opengl/695085/Cal3D%E5%8A%A8%E7%94%BB%E7%9A%84%E5%8A%A0%E8%BD%BD%E3%80%81%E6%98%BE%E7%A4%BA%E5%8F%8A%E6%8E%A7%E5%88%B6%E7%A4%BA%E4%BE%8B/osgVR/main.cpp__.htm
骨骼模型下载地址:
http://ftp.jaist.ac.jp/pub/sourceforge/o/project/os/osgcal/test_models/0.0.1/
Tools-Options-Projects and Solutions-C++ Directories 添加 osgCal 的 include 及 bin 路径。
Project-Properties-Configuration Properties-Linker-Input-Additional 添加依赖库
osg.lib
osgDB.lib
osgGA.lib
osgUtil.lib
osgViewer.lib
osgCal.lib
这里选择的是 Release 模式。
编译工程,运行。将会展示如下的
示例的骨骼动画是非常生动的。有以下几种模式:
animation=skeleton_idle.caf
animation=skeleton_strut.caf
animation=skeleton_walk.caf
animation=skeleton_jog.caf
animation=skeleton_wave.caf
animation=skeleton_shoot_arrow.caf
animation=skeleton_hiphop.caf
按“ 1 ”对应的是 idle ,按“ 2 ”对应的是 strut ,按“ 3 ”对应的是 walk , ....
好了!我们的 osgCal 例子运行成功, enjoy !!
最后附上源码:
/**********************************************************
*Write by FlySky
* zzuxp@163.com http://www.OsgChina.org
**********************************************************/
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/TrackballManipulator>
#include <osg/BoundingSphere>
#include <osgUtil/Optimizer>
#include <osgCal/CoreModel>
#include <osgCal/Model>
#include <iostream>
//加载模型
osg::Node* makeModel( osgCal::CoreModel* cm,osgCal::BasicMeshAdder* ma, int animNum = -1 )
{
osgCal::Model* model = new osgCal::Model();
//从CoreModel中创建模型
model->load( cm, ma );
if ( animNum != -1 )
{
//实现动画
model->blendCycle( animNum, 1.0f, 0 );
}
return model;
}
//动画控制事件处理器
class AnimationToggleHandler : public osgGA::GUIEventHandler
{
public:
//构造函数
AnimationToggleHandler( osgCal::Model* m,
const std::vector <std::string >& an )
: model( m )
, animationNames( an )
, currentAnimation( -1 )
{
//
}
//事件处理函数
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
if ( ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL )
{
if ( ea.getKey() >= '1' &&
ea.getKey() < '1' + (int)animationNames.size() )
{
//执行动作
model->executeAction( ea.getKey()- '1' );
}
}
else if ( ea.getKey() >= '1' &&
ea.getKey() < '1' + (int)animationNames.size() )
{
//重新初始化
if ( currentAnimation != -1 )
{
model->clearCycle( currentAnimation, 1.0 );
}
currentAnimation = ea.getKey() - '1';
//循环动作
model->blendCycle(currentAnimation, 1.0f, 1.0 );
}
//清除当前动作,重置初始动作
else if ( ea.getKey() == '0' )
{
model->clearCycle( currentAnimation, 0.0 );
currentAnimation = -1;
}
}
default: break;
}
return false;
}
private:
//动画模型
osgCal::Model* model;
//动画动作名称
std::vector <std::string > animationNames;
//当前动作
int currentAnimation;
};
//暂停或者渲染状态切换事件处理器
class ToggleHandler : public osgGA::GUIEventHandler
{
public:
ToggleHandler( bool& toggleVar,char key):
toggleVar( &toggleVar ),
key( key )
{
//
}
//事件处理函数
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
if ( ea.getKey() == key )
{
//切换状态
*toggleVar = !(*toggleVar);
}
}
default: break;
}
return false;
}
private:
//当前状态
bool* toggleVar;
//按键
char key;
};
int main()
{
//创建场景浏览器
osgViewer::Viewer* viewer = new osgViewer::Viewer();
osg::Group* root = new osg::Group();
//一系列动作名
std::vector <std::string > animationNames;
//动画模型名
std::string fn("E:\\OSG\\osgCalByflySky\\test_models\\thug\\cal3d.cfg"); //skeleton\\skeleton hero\\hero
//初始化静止模型动作
int animNum = -1;
//动画模型
osgCal::CoreModel* coreModel = new osgCal::CoreModel();
//基本网格
osgCal::BasicMeshAdder* meshAdder= new osgCal: efaultMeshAdder ();
//网格参数
osgCal::MeshParameters* p = new osgCal::MeshParameters();
//采用深度,用于减少子网被遮盖的不可见的像素
p->useDepthFirstMesh = true ;
//平滑模式
p->software = true ;
//加载外部模型文件
coreModel->load( fn, p);
//添加模型
root->addChild( makeModel( coreModel,meshAdder,animNum ) );
//得到一系列动作名称
animationNames = coreModel->getAnimationNames();
//动作切换控制
viewer->addEventHandler( new AnimationToggleHandler( (osgCal::Model*)root->getChild(0), animationNames ) );
//暂停控制
bool paused = false;
viewer->addEventHandler( new ToggleHandler( paused, 'p' ) );
//优化场景数据
osgUtil::Optimizer optimizer ;
optimizer.optimize(root);
viewer->setSceneData(root);
viewer->setCameraManipulator(new osgGA::TrackballManipulator());
viewer->realize();
//添加时间控制
osg::Timer_t startTick = osg::Timer::instance()->tick();
//初始化一个状态枚举变量,控制暂停或者渲染
//默认为渲染状态
enum PauseState { Unpaused, Paused };
PauseState pauseState = Unpaused;
osg::Timer_t pauseStartTick = 0;
double totalPauseTime = 0;
//通过控制当前帧显示时间,来控制是否暂停或者渲染
while ( !viewer->done() )
{
osg::Timer_t tick = osg::Timer::instance()->tick();
//暂停
if ( pauseState == Unpaused && paused )
{
pauseState = Paused;
pauseStartTick = tick;
}
//渲染
if ( pauseState == Paused && !paused )
{
pauseState = Unpaused;
//得到暂停时间
totalPauseTime += osg::Timer::instance()->delta_s( pauseStartTick, tick );
}
//当前时间
double currentTime = osg::Timer::instance()->delta_s(
startTick,
pauseState == Unpaused ? tick : pauseStartTick );
//继续暂停帧开始渲染
viewer->frame( currentTime - totalPauseTime );
}
return 0;
}
[/code]
再给大家提供一个cal3d格式的骨骼模型。enjoy!!
欢迎转载,转载请注明: http://www.cnkinect.com/forum.php?mod=viewthread&tid=15697&page=1&extra=