骨骼动画是去年打算写的部分, 但是中间因为工作太忙, 已经拖了一年了. 期间也加了其他东西, 比如对UI做了部分完善.UI对toolbar button添加了drop down 支持,
一种是dropdown menu,
一种是dropdown property sheet
实现这些控件不难, 但是要做抽象和复用, 接口设计稍微有点复杂. 现在可以把一个IConfig对象绑定到toolbar的button里了. 这样保存这些配置的时候,直接使用IConfig接口就可以了.
贴一个编辑器的配置文件, 包含了所有tool的配置, 还有界面的配置.
1 <EditorConfig value="" version="0.01 "> 2 <config name="EditorGlobalConfig" value="" version="0.01 "> 3 <config name="Transform Space" value="2"/> 4 </config> 5 <config name="ViewPort" value="" version="0.01 "> 6 <config name="Layout" value="0"/> 7 <config name="Camera0" value="" version="0.01 "> 8 <config name="Camera Move Speed" value="149"/> 9 <config name="Camera Rotate Speed" value="45"/> 10 </config> 11 <config name="Camera1" value="" version="0.01 "> 12 <config name="Camera Move Speed" value="4"/> 13 <config name="Camera Rotate Speed" value="45"/> 14 </config> 15 <config name="Camera2" value="" version="0.01 "> 16 <config name="Camera Move Speed" value="4"/> 17 <config name="Camera Rotate Speed" value="45"/> 18 </config> 19 <config name="Camera3" value="" version="0.01 "> 20 <config name="Camera Move Speed" value="4"/> 21 <config name="Camera Rotate Speed" value="45"/> 22 </config> 23 </config> 24 <config name="Tool" value="" version="0.01 "> 25 <config name="Deform" value="" version="0.01 "> 26 <config name="Brush Size" value="44"/> 27 <config name="Brush Intensity" value="39"/> 28 <config name="Brush Shape" value="media:editor_res/brushes/fade_circle.png"/> 29 <config name="Brush Color" value="(1.000,0.000,0.024,1.000)"/> 30 </config> 31 <config name="Paint" value="" version="0.01 "> 32 <config name="Brush Size" value="27"/> 33 <config name="Brush Intensity" value="64"/> 34 <config name="Brush Shape" value="media:editor_res/brushes/fade_circle.png"/> 35 <config name="Brush Color" value="(0.000,0.000,1.000,1.000)"/> 36 <config name="Terrain Texture" value="image:terrain_textures/The Fire LandsD.dds"/> 37 </config> 38 <config name="Rebuild Normal" value=""/> 39 </config> 40 </EditorConfig>
最近的更新主要是添加了memory archive, 用于统一的内存cache. 之前已经有memory stream了, 而且是个公开的接口, 用户可以直接拿来使用.
现在加上了对memory stream的管理. 以后可以使用IStream做cache, 比如打开"memory:/XXX/myfile.txt" 并写入内容, 再交给其他系统当作抽象流使用.
到目前为止, 系统内置了三个路径, cwd:/, media:/, 和 memory:/
memory stream的管理, 思路也比较简单, 使用类似prototype的共享模式, 打开相同路径的stream, 虽然是不同的stream对象, 但是共享buffer. 即每个stream有不同的stream pointer/state, 但是有相同的buffer和size.
另外需要处理的是读写锁. stream的读写是互斥的, 读-读共享. 目前简单的使用一个lock 和一个referece count实现.
前几天终于开始着手做骨骼动画的导出了. 目前使用IGameSkin (IGameObject::GetIGameSkin())来导出mehs的blend indices和blendweights. IGameSkin是modifier的封装, 内部是Physque Modifier或者Skin Modifier, 至少在导出blend weights和blend indices的时候,不需要关心其内部细节.
(http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__cpp_ref_class_i_game_object_html)
另外简单记录一下导出的流程:
1.弹出配置窗口, 收集用户指定的信息, 比如动画信息: 名字,起始帧,结束帧等.
2.enumerate scene 收集到有用的node, 并用线性方式保存:Tab<INode*>, 使用额外的表,保存所有骨骼节点;
3.使用收集到的node, 初始化IGame, 这个时候IGame有了一组对象, 这些对象是基于收集到的信息创建出来的;
4.遍历IGame中的对象, 导出mesh (IGAME_MESH) 和material. mesh中的bone weights可以通过IGameSkin取得, bone indices需要使用步骤2中的额外骨骼节点表;
5.导出骨骼信息和动画. 骨骼的导出要使用步骤2中收集到的额外骨骼表. 动画的导出要使用步骤1中的一个或者多个动画定义.
对于步骤2中骨骼节点的判断, cal3d (http://home.gna.org/cal3d/) 里面使用的是搜索modifier, 找到physque modifer或者skin modifer,就认为是骨骼节点. ogre exporter使用的是判断controller, 如果controller是biped或者biped slave,就认为是骨骼节点.
个人也不知道哪种更好, 目前两种都用了, 以后调试的时候再慢慢完善.
需要注意的是, 这里会收集到所有的骨骼, 如果骨骼没有用到, 也会被导出. 这是符合需求的. 因为角色的换装系统中可能会有多余的骨骼, 在切换mesh的时候才会真正绑定. 而无绑定骨骼的优化(不需要update transform), 以后在runtime再做. 记得Gamebryo的无绑定的骨骼并没有做优化, 所有骨骼会实时更新, 如果不使用BoneLOD,可能会有点浪费.
目前最大支持4个骨骼混合(一般这么多够了), 所以对于影响顶点的骨骼要按weight排序, 取前面最大的4个. 骨骼总量如果超了, 要拆分mesh, 这个还没仔细想怎么做, 或许可以参考别的代码.
后面继续做skeleton的导出, 主要是bone table和额外的parent-child关系, 然后再做动画的导出. 一个动画其实就是一序列的关键帧. 一个关键帧保存了当前骨骼的所有骨头的transform.
配置窗口可能需要添加一个新的控件, 用来定义/预览(只读- 编辑器端) 动画信息.
另外, 现在的导出只是收集中间信息. 数据格式和压缩等等这些再最后做, 也打算试下用X10Y10Z10W2来保存quaternion, 不使用float32x4.