前两天有朋友问,我的SlimXml有没有和RapidXml对比过效率?我是第一次听说这个库,更不用说对比效率了,于是上他们网站看了下。
好家伙,居然号称比TinyXml快30~60倍,而且是Boost.PropertyTree的默认xml解析器。
于是有点好奇,因为以前也没有特别关心过SlimXml的效率。
于是分别下载了TinyXml-2.6.1和RapidXml-1.13,迅速用vc8建立了两个测试工程,在系统中搜”*.xml”,找到了一个比较合适的测试文件。它足够大(1.5M),utf-8编码并且包含中/英文,有一定层次深度,大约3.3万行。测试文件可以从这里下载
测试对象是三个库从内存字符串解析xml的函数,这样能排除从硬盘上读文件这种不稳定因素的干扰,而且RapidXml貌似只支持从内存里解析
- slim::XmlDocument::loadFromMemory()
- TiXmlDocument::Parse()
- rapidxml::xml_document<char>::parse<flag>()
要说明的是,RapidXml的这个parse是一个模板函数,必须给一个flag的参数,我测试的时候给的是默认的0
测试结果,解析这个3.3万行,1.5M大小的xml,三个库分别花了
- SlimXml: 22ms
- TinyXml: 54ms
- RapidXml: 4ms!
Read more…

Grandpa从设计之初就定位于跨平台,渲染API无关的库。核心代码仅依赖c++标准库,理论上可以在任何平台,用任何(基本)符合c++标准的编译器编译。
但是这次还是碰到了一些问题,主要还是VC用的时间太长了,没有意识到某些特性实际上是非标准的,例如:
- hash_map头文件的位置不同。大家都知道该容器是非标准的,在vc下该头文件和其他容器在一起,而gcc下在ext子目录中
- gcc警告最后一行非空(也就是说源代码文件最后一个字符必须是回车,标准的确是这么规定的),vc不会警告
- vc允许只声明enum,gcc不允许
- gcc没有“安全版”(带_s)的字符串处理函数
另外,Mac OS X(以及Linux等其他Unix系的操作系统)是用utf-8表示unicode,而Windows则采用utf-16,这一点也引起了一些小麻烦。
还有一个很讨厌,gcc居然不认识utf-8的bom(ef,bb,bf)。导致我所有的源代码文件都要改为multibytes编码
好在这些都是小问题,花了不到一天时间就都解决了。
特别感谢张志鹏同学,帮我把原来基于d3d的Demo移植到了Opengl es上。
另外从今天开始,Grandpa SDK开放svn更新,地址为 Http://www.multi-crash.com/release
推荐使用TortoiseSVN。
上一篇遗留了一个问题没有说完,就是关于绝对变换和相对变换。我们的骨架一般是以树形结构存储的,一个骨骼会有一个父骨骼(根骨骼除外)和若干个子骨骼。所以对于骨骼的变换我们可以存储在模型空间中的绝对变换,也可以存储相对于其父骨骼的相对变换,二者是可以相互转换的。
用相对变换形式存储的好处主要是便于拆分成不同类型的变换从而使动画插值成为可能;而保存绝对变换的好处首先是效率较高,因为在蒙皮计算的时候我们真正需要的是骨骼的绝对变换,如果保存的是相对变换就需要根据骨骼的父子关系先计算出绝对变换矩阵,每块骨骼都多出一个矩阵乘法的开销。另外直接保存绝对变换还能避免因为逐层相对变换引起的累积误差。
言归正传,我们继续来看动画数据的压缩,前文已经把200k的数据压缩到60k左右,还有办法继续压缩吗?
用过Max(Maya和XSI不太熟悉,但想来也应该差不多,下文只讨论Max)的同学会发现,虽然我们的动画定的是30fps的标准,但是美术实际摆放的关键帧要远远低于这个密度,对于简单的动画,某些骨骼可能在两秒的时间内只有3~4个关键,其它时间的骨骼方位实际上是导出时Max自动插值得到的。于是小算盘就开始打了,既然我们保存的骨骼关键帧大部分都是Max自动生成的,那么我们能不能只保存真正由美术摆放的关键帧,剩下的也象Max所做的那样自动插值出来呢?如果可以的话,无疑将再次大幅减小动画文件的尺寸。

Read more…
这里说的骨骼动画数据,是指美术用Max,Maya或者XSI之类的3d工具制作的角色动画,通常要导出成引擎可以读取的特殊格式,为游戏所用。对于目前越来越强调动作感的网络游戏来说,动画资源占整个安装包尺寸的比例在不断上升,动画数据的压缩也在变得原来越重要,更不用说采用大量实时渲染过场动画的次世代Console游戏了。
每个引擎都有自己独特的动画文件格式,但里面的内容都大同小异。所谓动画,就是一系列关键帧的集合,每个关键帧可以描述了角色整个骨架的完整姿态信息,也就是每一块骨骼在3d空间中的位置和方向。
假设我们有一个包含50块骨骼的骨架,采用30fps的帧率,一个长度为两秒的动画需要占用多大的空间呢?我们来计算一下。我们知道空间的方位可以用一个矩阵来描述,一个矩阵包含4 x 4 = 16个浮点数,也就是64字节;我们有50块骨骼,那么每个关键帧就需要50 x 64 = 3200字节,另外关键帧还需要一个4字节的时间值,那么就是3204字节;两秒的30fps动画一共包含60个关键帧,于是可以算出最终的大小是3204 x 60 = 192240字节,不到200k的样子。这就是未经压缩的数据大小,当然这里忽略了一些诸如骨骼名字之类的信息,和我们要讨论的动画压缩关系不大,就不算在内了。
Read more…
名词解释:Pixel–屏幕像素;Texel–纹理像素
在使用d3d来渲染GUI元素时,可能很多人都碰到过一些让人抓狂的灵异问题,例如整个界面变模糊,边缘偏差一个像素,甚至在不同显卡上的表现还不一样……
这一般都是Pixel和Texel的对应出了问题导致的,界面元素的渲染的主要特点是一般是要求屏幕像素和纹理像素严格一一对应,这个在2d绘图中看来很自然的事,到了3d环境下似乎变得不那么简单。
d3d的特点是确定投影范围(记住渲染UI要使用正交投影)以后,“整数位置坐标”对应的是屏幕像素中心,而“整数纹理坐标”对应的却是纹理像素的边缘,这就是一切罪恶的根源。怎么理解这句话呢?请继续往下看……
一般来说渲染GUI时我们会把视口大小设置为和背缓分辨率一致,这样3d坐标的单位“1”就和屏幕上1个像素对应;而纹理坐标则用待渲染图元的像素尺寸占整张纹理像素尺寸的比例来确定。这里面有什么问题呢?

Read more…
VS 2010发布也有一阵了,五一的时候下载了一个30天Trial试了一下。当然,我只用其中的Visual c++那部分。
不出所料,界面上看变化不大,就是默认的配色更酷了一些

Read more…