﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-组件工厂</title><link>http://www.cppblog.com/flashboy/</link><description>------3D游戏研发</description><language>zh-cn</language><lastBuildDate>Sun, 05 Apr 2026 15:52:01 GMT</lastBuildDate><pubDate>Sun, 05 Apr 2026 15:52:01 GMT</pubDate><ttl>60</ttl><item><title>MMORPG游戏服务器框架的可行性报告 (提高生产效率)</title><link>http://www.cppblog.com/flashboy/archive/2010/07/09/119837.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Fri, 09 Jul 2010 02:45:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2010/07/09/119837.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/119837.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2010/07/09/119837.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/119837.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/119837.html</trackback:ping><description><![CDATA[纵观游戏服务器技术框架,&nbsp; 以运行在Linux操作系统上的居多, 为什么要运行在Linux上呢? 相信很多人会给出肯定的答案, Linux操作系统是开源的，而且是免费的，那叫做专业！是的，不错，是专业。但有一个问题让我们值得思考的是，虽然是免费的，但Linux工具比较贫乏，在某种程度上大大加在了开发成本及后期调试时间，所以我们不得不研究出一种代码可以运行在Linux，但又要节省开发成本，提高生产效率的可行性方案。<br><br>在Linux上，古老的Linux C程序员一般会采用一个文本编辑工具，比如：VI等，由于我以前是在windows下生活的，对VS.net这一类的工具颇为喜爱，它的开发方便快捷，又有开发辅助插件的支持，使你可以尽情使用智能提示，快捷键，代码模板等高效生产代码。可以说编码更多的是依靠可视化工具查错，快速跳转代码等。反正我的意思就是开发相当愉悦。但Linux下的C程序员则不然，我也曾经问过他们为什么要采用VI等编辑工具来编代码，首先，他们给到我的第一答案是"专业", 其实我也不太懂他们说的专业是什么，是传统意义上的，还是习惯性必须的；然后他们说：&#8220;使用makefile文件来编译代码很爽，速度很快&#8221;，这一点我是赞同的，但有个问题是程序员的入门门槛比较高，要求大家都要会这东西，还是麻烦，从HR招聘处可以看到，本来投C++程序员的人就比较少了，因为C++应用的领域基础是应用软件，游戏啊，电信啊，还是一些MFC界面性的东西，而且要求功底比较好，确实有时候招人还是挺难的，更不用说还要有Linux开发经验的人了。最后，我问了linux开发不员说那你们的调试用什么工具，他们说：&#8220;gdb&#8221;, 又是一个"手打牛肉丸"，自我感觉很痛苦，心里想&#8220;为什么有那么先进的工具，比方说：Eclipse CDT， 你们不用呢?&#8221;，其实他们心中也是有答案的，&#8220;编码要养成一种好习惯，而不是依靠于某种工具&#8221;，显然Linux程序员在编码上大体要比windows上的程序员来得严格，也感觉到他们的代码比较有质量。但很显然的，由于开发环境的布署比较麻烦，对于大规模生产是否能够每个人都有那么高素质的编程能力，那就是个"谜"！------ &#8220;猜不准!&#8221;<br><br>针对上面的情况，我也自己分析了一下，软件开发的三大要素是什么，成本，质量，进度， 只有这三项东西控制得好，那才能控制好项目。<br>那软件编程的基础是什么？ 当然是调用操作系统的API了，很显然的， 不同操作系统有不同的API，除非你有一个跨平台的开发框架，或者叫类库也行。<br>接下来软件架构在不同领域是否通用？比方说：通信框架，很显然的，还是有区别的，比方说电信系统与游戏系统，那显然还是不一样的。<br>最后，软件编码与接口(API)是不是应该更多人常用的，而且容易上手的(友好第一！)，这样才可以减少开发成本及协调工作。<br><br>总结一下，我心中已有答案了，必须采用一种大多数程序员可以接受的，而且是他们熟悉的（不要DIY的），而且开发速度快速的开发方式那才是真道理。<br>以下是我的基本方案：<br>&nbsp;
<p><span><span>一、<span>&nbsp;&nbsp; 跨平台</span></span></span><span>框架的基础设施</span><span> (</span><span>组件图</span><span>)</span></p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>MySQL</span><span>数据库操作组件</span></p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>线程池</span><span> </span><span>及</span><span> </span><span>读写锁</span></p>
<p><span><span>3.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>基础数据类型，容器，内存池，环形缓冲区</span></p>
<p><span><span>4.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>IOCP</span><span>及</span><span>Epoll</span><span>跨平台的面向对象通信框架</span></p>
<p><span><span>5.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>集成</span><span>LuaTinker</span><span>脚本交互模块等</span></p>
&nbsp;
<p><span><span>二、<span>&nbsp;&nbsp; </span></span></span><span>开发方式与调试环境</span></p>
<p><span>本框架的初步设想是前期在</span><span>Windows</span><span>下使用</span><span>VS.net 2008</span><span>进行开发调试，争取在</span><span>Windows</span><span>下解决</span><span>80%</span><span>左右的逻辑错误。之后由主程序员把代码移植到</span><span>Linux</span><span>，并使用</span><span>Eclipse CDT</span><span>可视化开发环境进行后期的调试工作。这样也大大降低招聘人员的知识要求</span><span>(</span><span>不用懂</span><span>Linux)</span><span>，在某一程度降低了人员成本和加快了开发效率。<br><br><br></span></p>
<img src ="http://www.cppblog.com/flashboy/aggbug/119837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2010-07-09 10:45 <a href="http://www.cppblog.com/flashboy/archive/2010/07/09/119837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MMORPG服务器组集群方案</title><link>http://www.cppblog.com/flashboy/archive/2010/07/09/119830.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Fri, 09 Jul 2010 02:05:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2010/07/09/119830.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/119830.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2010/07/09/119830.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/119830.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/119830.html</trackback:ping><description><![CDATA[<img src="http://www.cppblog.com/images/cppblog_com/flashboy/serverGroupDesign2.JPG" border=0><br><br><img height=726 src="http://www.cppblog.com/images/cppblog_com/flashboy/serverGroupDesign.JPG" width=720 border=0><br><br><br>&nbsp;
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>LoginApp</span></p>
<p><span>即登录服务器</span><span>, </span><span>它主要完成玩家帐号的验证</span><span>, </span><span>同时它通过</span><span>BaseAppMgr</span><span>并向玩家发送一个</span><span>SessionKey</span><span>作为基础服务器</span><span>(BaseApp)</span><span>的登录密钥；同时</span><span>LoginServer</span><span>还向玩家发送服务器列表信息。</span></p>
<p><span>2. BaseApp</span></p>
<p><span>&nbsp;&nbsp;<span>&nbsp;&nbsp;&nbsp;</span></span><span>即基础服务器，</span><span> </span><span>也称连接服务器，它还维持着一个客户端连接列表</span><span>(</span><span>用户列表</span><span>), </span><span>这样它可以实现区域消息广播及通过</span><span>BaseAppMgr</span><span>实现世界聊天</span><span>, </span><span>玩家信息查看等功能；它还负责消息的分发到</span><span>CellApp</span><span>进行处理，并把结果返回到客户端。</span></p>
<p><span>3. CellApp</span></p>
<p><span>即游戏服务器，它负责世界数据的加载，游戏逻辑的处理及世界对象的管理。在本架构中当为支线服务器。</span></p>
<p><span>4. DBMgr</span></p>
<p><span>用户服务器，它负责用户相关数据的存取。一般是用户登录选择角色后就获得角色所有相关数据给到</span><span>MapServer, </span><span>并由</span><span>MapServer</span><span>定时保存角色的相关数据。</span></p>
<p><span>5. BaseAppMgr</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>基础服务器管理器，主要负责分配基础服务器给到客户端连接，同时它采用某种策略可以实现用户的均衡负载等。</span></p>
<p><span>6. CellAppMgr</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>支线服务器管理器</span><span>, </span><span>它主要根据支线</span><span>ID</span><span>为基础代理对象分配支线服务器实体</span><span>, </span><span>这样就可以实现与客户端的通信了。</span></p>
<p><span>7. DB</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>数据库服务器主要分为三个库来存取，</span><span>AccountDB</span><span>为玩家账户信息，</span><span>CharacterDB</span><span>为玩家角色相关信息，</span><span>WorldDB</span><span>为所胡的世界数据。</span></p>
<img src ="http://www.cppblog.com/flashboy/aggbug/119830.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2010-07-09 10:05 <a href="http://www.cppblog.com/flashboy/archive/2010/07/09/119830.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编程常用快捷键</title><link>http://www.cppblog.com/flashboy/archive/2009/12/15/103252.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Tue, 15 Dec 2009 06:12:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/12/15/103252.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/103252.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/12/15/103252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/103252.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/103252.html</trackback:ping><description><![CDATA[<p>1. 调试快捷键<br>2. 编辑快捷键<br>3. 代码快捷键<br>4. 窗口快捷键</p>
<p><br>Ctrl+Tab 切换编辑主窗口中的代码选项页</p>
<p>Esc键关闭当前的非模式窗口 (比方说 查找窗口, 切误用 Alt + F4, 这样会连VS.net2005都关掉)</p>
<p>F5: 启动调试<br>Ctrl+F5: 开始执行(不调试)</p>
<p>Shift+F5: 停止调试<br>Ctrl+Shift+F5: 重启调试</p>
<p>F7: 生成解决方案<br>Ctrl+U: 生成当前项目</p>
<p>F11: 独句调试<br>F10: 过程调试</p>
<p>F9: 打断点 或 取消断点<br>Alt+F9: 显示断点窗口</p>
<p>F12: 定位到函数的实现体<br>???: 定位到函数的声明, 只能用右键---&gt;选择A</p>
<p>Shift+Alt+Enter: 切换全屏编辑</p>
<p>Ctrl+F: 查找<br>Ctrl+Shift+F: 在文件中查找</p>
<p>F3: 查找下一个<br>Shift+F3: 查找上一个</p>
<p>Ctrl+H: 替换<br>Ctrl+Shift+H: 在文件中替换</p>
<p>Ctrl+左右箭头键: 一次可以移动一个单词<br>Ctrl+上下箭头键: 滚动代码屏幕，但不移动光标位置。</p>
<p>Ctrl+L: 删除当前行</p>
<p><br>Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态<br>Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态 或者 右键 + L + O<br>Ctrl+M,P: 停止大纲显示 或者再按一次Ctrl+M,L&nbsp; 或者 右键 + L + O</p>
<p>Ctrl+G: 转到指定行<br>Shift+Alt+箭头键: 选择矩形文本<br>Alt+鼠标左按钮: 选择矩形文本<br>Ctrl+Shift+U: 全部变为大写<br>Ctrl+U: 全部变为小写</p>
<p>//有点难度的:<br>Ctrl+K, Ctrl+C: 注释&nbsp;&nbsp;&nbsp; <br>Ctrl+K, Ctrl+U: 解除注释</p>
<p>Ctrl+Shift+A: 添加新项<br>//----------------------------------------<br>VAssistX: 操作<br>1. 定义标准的代码段, 并设置快捷键<br>2. Alt+M, 再打上函数名的前几个字母, 就会过滤掉很多函数, 最后按Enter定位到当前文件所查找的函数体<br>3. Shift+Alt+O, 查找文件, 输入文件名的前几个字母, 就会过滤掉很多文件, 最后按Enter定位到当前文件所查找的文件<br>4. Alt+O: 切换到.h和.cpp文件<br>5. 右键+查看所有引用 或 VassistX菜单中的Find References, Find References in Files : 查看函数引用的所有地方<br>6. Shift+Alt+S: 查找全局变量<br>//----------------------------------------<br>F7: 查看代码<br>Shift+F7: 查看窗体设计器</p>
<p>Windows键+E&nbsp;打开资源管理器。<br>Windows键+D&nbsp;显示桌面。<br>Windows键+M&nbsp;最小化所有被打开的窗口。<br>Alt+Tab&nbsp;&nbsp;切换任务栏中的激活窗口</p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/flashboy/aggbug/103252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-12-15 14:12 <a href="http://www.cppblog.com/flashboy/archive/2009/12/15/103252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WOW地形Shader分析(转)</title><link>http://www.cppblog.com/flashboy/archive/2009/12/11/102960.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Fri, 11 Dec 2009 02:04:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/12/11/102960.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/102960.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/12/11/102960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/102960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/102960.html</trackback:ping><description><![CDATA[<p>SPXG // 标识<br>// 用到5张图片:<br>{<br>&nbsp;&nbsp; blendTexture&nbsp; = 0<br>&nbsp;&nbsp; layer0Texture = 1<br>&nbsp;&nbsp; layer1Texture = 2<br>&nbsp;&nbsp; layer2Texture = 3<br>&nbsp;&nbsp; layer3Texture = 4<br>}<br>!!ARBfp1.0<br>// 定义常量:<br>PARAM c[1] = { { 1, 0.30000001, 0.69999999 } };<br>// 声明3个寄存器:<br>TEMP R0;<br>TEMP R1;<br>TEMP R2;<br>// 开始混合:<br>// 一.第0层和第1层使用第4张图的x通道作为alpha进行混合:<br>TEX R1, fragment.texcoord[0], texture[0], 2D;<br>TEX R0, fragment.texcoord[1], texture[1], 2D;<br>ADD R2, R0, -R1;<br>// r2=Tex1-Tex0<br>TEX R0, fragment.texcoord[4], texture[4], 2D;<br>MAD R2, R0.x, R2, R1;<br>// r2 = Tex4.x*r2+Tex0<br>// 说明:<br>// 其中的Tex4.x是对应第1层alpha值, 下面把Tex4.x当a1看<br>// 即 r2 = a1 * (Tex1-Tex0) + Tex0<br>// 转换一下即是: Tex0*(1-a1)+a1*Tex1, 呵呵,看到了吧,这就是混合公式!<br>// 二.第2层和前面结果使用第4张图的y通道作为alpha进行混合:<br>TEX R1, fragment.texcoord[2], texture[2], 2D;<br>ADD R1, R1, -R2;<br>// r1=Tex2-r2<br>MAD R2, R0.y, R1, R2;<br>// r2 = Tex4.y*r1+r2, 即 a2*r1+r2 = a2*(Tex2-r2)+r2, 即r2*(1-a2)+Tex2*a2, 其中r2即是上次0和1层混合后的结果<br>// 三.第3层和前面结果使用第4张图的z通道作为alpha进行混合:<br>TEX R1, fragment.texcoord[3], texture[3], 2D;<br>ADD R1, R1, -R2;<br>// r1=Tex3-r2<br>MAD R1, R0.z, R1, R2;<br>// r1=a3*r1+r2 , 即 a3*r1+r2 = a3*(Tex3-r2)+r2, 即r2*(1-a3)+Tex3*a3<br>// 这样r1就保存了最终的混合结果<br>// 四.让阴影地表光泽系数为0(Tex4.w即a通道代表地形的阴影,0为阴影,1为正常.而每层贴图中的a通道是光泽通道,所以R1.w保存的是最终的光泽通道值):<br>MUL R0.x, R1.w, R0.w;<br>// r0.x = r1.w(光泽)*Tex4.w(阴影值, 是阴影则=0,否则=1)<br>// 计算削减系数?<br>MAD R0.w, R0, c[0].y, c[0].z; // r0乘上0.3(削减了30％)再加上一个常量0.69999999<br>// 反射高光 = secondary_color(反射光)*光泽:<br>MUL R0.xyz, R0.x, fragment.color.secondary; <br>// 贴图最终color = 最终贴图混出的color*削减系数:<br>MUL R1.xyz, R1, R0.w; <br>// 贴图最终color * primary_color(光照色或是顶点色) + 反射高光:<br>MAD result.color.xyz, R1, fragment.color.primary, R0; <br>// alpha:<br>MOV result.color.w, c[0].x; <br>END<br>&nbsp;&nbsp; <br>&nbsp;&nbsp; </p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/flipcode/archive/2008/03/03/2143452.aspx">http://blog.csdn.net/flipcode/archive/2008/03/03/2143452.aspx</a></p>
<img src ="http://www.cppblog.com/flashboy/aggbug/102960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-12-11 10:04 <a href="http://www.cppblog.com/flashboy/archive/2009/12/11/102960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RedLight引擎原型初成</title><link>http://www.cppblog.com/flashboy/archive/2009/12/05/102609.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Sat, 05 Dec 2009 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/12/05/102609.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/102609.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/12/05/102609.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/102609.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/102609.html</trackback:ping><description><![CDATA[一直都没勇气去写一个游戏引擎，也许是太懒了，也许是太大了。虽然写了些零零碎碎的Test Case! 但你知道的，这始终不成气候！<br>最近我被安排到一个小组中，做的项目是一个体感游戏，之前考虑过用ogre开源引擎来做，可惜我对这东西又不熟的，听人家说还要用第三方类库CEGUI, 还要配置一些东西，一听头都大了，光学习理想都用半个月了，我们的工程只给两个月的时间，唉呀！算了吧，自己不是还有些乱七八糟的代码可用吗？狠下决心，决定干它一把！哪怕辛苦一点，做下来一个游戏引擎以后就容易干事了。<br>经过和另外一个同事两个月的时间奋斗，一路中虽说遇到些困难，也常加班的，项目终于也做完了。<br><img src="http://www.cppblog.com/images/cppblog_com/flashboy/6771/he3.JPG" border=0><br><br><img src="http://www.cppblog.com/images/cppblog_com/flashboy/6771/he0.JPG" border=0><br><br><img src="http://www.cppblog.com/images/cppblog_com/flashboy/6771/he1.JPG" border=0><br>一个游戏引擎原型基本蛋生了，我们命名它为 RedLight，它基本实现了<br><br>(0) Win32程序渲染框架<br>(1) UI的基本消息交互流程，XML窗体配置管理，UI皮肤配置管理，基本的UI控件库，多分辩率无缝UI拼图<br>(2) 室外场景管理<br>(3) 摄相机路径摄像<br>(4) 3D Max8模型及骨骼动画导出插件<br>(5) 模型渲染, 关键帧动画及骨骼动画控制<br>(6) 基本的水面反射效果<br>(7) 简单的面粒子系统<br>(8) 声音控制接口<br><br>这是一个单机游戏引擎的原型，功能有限，但它总算不辱使命完成了一个项目了，以后再扩展使它日益强大吧！
<img src ="http://www.cppblog.com/flashboy/aggbug/102609.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-12-05 17:36 <a href="http://www.cppblog.com/flashboy/archive/2009/12/05/102609.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>超级工具-----NVPerfHUD分析Beijing 2008</title><link>http://www.cppblog.com/flashboy/archive/2009/12/05/102607.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Sat, 05 Dec 2009 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/12/05/102607.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/102607.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/12/05/102607.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/102607.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/102607.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/flashboy/archive/2009/12/05/102607.html'>阅读全文</a><img src ="http://www.cppblog.com/flashboy/aggbug/102607.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-12-05 17:06 <a href="http://www.cppblog.com/flashboy/archive/2009/12/05/102607.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WOW字体研究报告</title><link>http://www.cppblog.com/flashboy/archive/2009/12/01/102347.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Tue, 01 Dec 2009 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/12/01/102347.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/102347.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/12/01/102347.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/102347.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/102347.html</trackback:ping><description><![CDATA[我喜欢玩WOW的UI风格，尤其是它的高清字体-------任务窗口的内容总感觉十分舒畅。这是从魔兽世界中任务窗口的游戏截图<br><img src="http://www.cppblog.com/images/cppblog_com/flashboy/6771/finish.jpg" border=0>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.cppblog.com/images/cppblog_com/flashboy/font.JPG" border=0>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.cppblog.com/images/cppblog_com/flashboy/6771/font2.jpg" border=0><br><br>经研究， 其实，上面的字体是用方正楷体(不是windows楷体)字体来做的， 用Freetype类库得到每个字符的对应图，并组装排版到一张预先创建好的空纹理中(256*256),&nbsp; 组成一张灰度图，这样可以防止重复字符贴图两遍，提高效率，就像活字印刷术一样灵活组合。<br>渲染的时候，采用字体颜色RGB + 灰度图合成最终效果。<br><br>也许你会发现，左图为什么这么清晰，右图好像稍差一点。对了，其实人的眼睛很奇怪，对颜色的识别是通过对比的，wow正是利用这一点，背景色采用以黄色为主色调，夹杂一些噪声，然后再渲上黑色的文字，这样可以给人感觉到很清晰。<br><br>其实wow中还是其他一些文字效果，比方说：阴影文字，原理是渲染两次同一字符，并在第二次遍渲染作偏移即可。当然，还有那种字体外边包起来的效果，不过这种我还没研究它的算法。<br><br>怎么说呢？一个游戏世界中，字体我觉得相当重要，丰富的字体表现会给人相当美满的效果，带给人美好的印象，所以还是相当重要的。我也在做我的文字配置系统，祝福我早日完成吧！ 谢谢！ 
<img src ="http://www.cppblog.com/flashboy/aggbug/102347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-12-01 17:13 <a href="http://www.cppblog.com/flashboy/archive/2009/12/01/102347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BigWorld引擎初识大观</title><link>http://www.cppblog.com/flashboy/archive/2009/11/14/100914.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Sat, 14 Nov 2009 05:16:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/11/14/100914.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/100914.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/11/14/100914.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/100914.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/100914.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/flashboy/archive/2009/11/14/100914.html'>阅读全文</a><img src ="http://www.cppblog.com/flashboy/aggbug/100914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-11-14 13:16 <a href="http://www.cppblog.com/flashboy/archive/2009/11/14/100914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>D3D与OpenGL常用API对译</title><link>http://www.cppblog.com/flashboy/archive/2009/11/14/100912.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Sat, 14 Nov 2009 04:49:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/11/14/100912.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/100912.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/11/14/100912.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/100912.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/100912.html</trackback:ping><description><![CDATA[<p>作为一个3D程序员, 我用了OpenGL两年多, 最近在搞一个项目, 从OpenGL转到D3D, 虽然工程外在的框架都封装得不错, 但想完全地从OpenGL转换到D3D, 看起来还是有难度的, 花了我两个星期的时间, 我终于转换过来了。<br>D3D与OpenGL的几点比较明显不同的地方:<br>(一)、正交投影时：OpenGL以屏幕左上角为(0,0), 而D3D却以屏幕中心为(0,0)<br>(二)、OpenGL使用右手坐标系， 而D3D使用左手坐标系<br>(三)、OpenGL使用旋转操作等转入的角度参数是 角度, 而D3D是 弧度，所以注意要PI * Angle / 180<br><br>下面我把具体地API对照关系列出来(不是很全，以后添加中.......)<br><br><br>1. 坐标变换<br>&nbsp;pos = D3DXVECTOR3(0,2,-1.5);<br>&nbsp;at&nbsp; = D3DXVECTOR3(0,0,0);<br>&nbsp;up&nbsp; = D3DXVECTOR3(0,1,0);<br>&nbsp;D3DXMatrixLookAtLH(&amp;view,&amp;pos,&amp;at,&amp;up);<br>&nbsp;pd3dDevice-&gt;SetTransform(D3DTS_VIEW,&amp;view);</p>
<p>2. 绘制<br>&nbsp;pd3dDevice-&gt;SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);</p>
<p>&nbsp;&nbsp;&nbsp; DrawPrimitive()<br>&nbsp;DrawIndexedPrimitive()<br>&nbsp;<br>&nbsp;DrawPrimitiveUP()<br>&nbsp;DrawIndexedPrimitiveUP()<br>3. 颜色</p>
<p><br>4. 片段测试</p>
<p>&nbsp;(1) 深度测试<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ZENABLE, TRUE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//glEnable(GL_DEPTH_TEST);&nbsp;&nbsp; <br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);&nbsp;&nbsp;&nbsp;&nbsp;//glDepthFunc(GL_LEQUAL);<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//glEnable(GL_CULL_FACE);</p>
<p>&nbsp;<br>&nbsp;(2) Alpha测试<br>&nbsp;//--------------------------------------------------------------------------------------------------------&nbsp;<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //glEnable(GL_ALPHA_TEST);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);&nbsp;&nbsp;&nbsp;&nbsp;//glAlphaFunc(GL_GREATER, 0.1f);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ALPHAREF, 0.1 * 255); //取值范围 0 ~ 255<br>&nbsp;<br>&nbsp;(3) 剪裁测试 (平面剪切)<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;// Enable clip plane for reflection map<br>&nbsp;CMatrix44f pWorldViewProjIT=m_pWorldViewProj; <br>&nbsp;//pWorldViewProjIT.Transpose();<br>&nbsp;pWorldViewProjIT.Invert();&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;// Transform plane to clip-space<br>&nbsp;float pClipSpacePlane[4];<br>&nbsp;float pClipPlane[]= { 0, 0, 1, 0};&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;// Check if camera is below water surface, if so invert clip plane<br>&nbsp;CVector3f pEye=(CVector3f)m_pCamera.GetPosition();<br>&nbsp;if(-pEye.m_fZ&lt;0.0)<br>&nbsp;{<br>&nbsp;&nbsp;pClipPlane[2]=-pClipPlane[2];<br>&nbsp;}</p>
<p>&nbsp;MatrixTransformPlane(pClipSpacePlane, pClipPlane, pWorldViewProjIT);</p>
<p>&nbsp;// enable clip plane now<br>&nbsp;g_pDevice-&gt;SetClipPlane(0, pClipSpacePlane);&nbsp;&nbsp; <br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_CLIPPLANEENABLE, 1);<br>&nbsp;<br>&nbsp; <br>&nbsp;<br>&nbsp;(4) 模板测试<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_STENCILENABLE, TRUE);<br>&nbsp;&nbsp;&nbsp; g_pDevice-&gt;SetRenderState(D3DRS_STENCILFUNC, 3DCMP_ALWAYS);<br>&nbsp;&nbsp;&nbsp; g_pDevice-&gt;SetRenderState(D3DRS_STENCILREF, 0x1); //取值范围 0 ~ 255<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Device-&gt;SetRenderState(D3DRS_STENCILPASS,&nbsp; D3DSTENCILOP_KEEP);<br>&nbsp;<br>5. 纹理操作<br>&nbsp;<br>&nbsp;g_pDevice-&gt;SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);<br>&nbsp; &nbsp;g_pDevice-&gt;SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);<br>&nbsp; &nbsp;g_pDevice-&gt;SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);<br>&nbsp; &nbsp;<br>&nbsp;g_pDevice-&gt;SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);<br>&nbsp;&nbsp;g_pDevice-&gt;SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);</p>
<p>6. 缓冲区操作<br>&nbsp;&nbsp;<br>&nbsp;(1) 颜色缓冲<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_COLORWRITEENABLE, 0x000000F);<br>&nbsp;<br>&nbsp;(2) 深度缓冲<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ZENABLE, TRUE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//glEnable(GL_DEPTH_TEST);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ZWRITEENABLE, TRUE);&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//glDepthMask(GL_TRUE);</p>
<p>&nbsp;(3) 模板缓冲<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;<br>&nbsp;(4) 渲染到纹理<br>&nbsp;//--------------------------------------------------------------------------------------------------------<br>&nbsp;// Render targets<br>&nbsp;IDirect3DSurface9 *m_plD3DBackbufferSurf,<br>&nbsp;&nbsp;*m_plD3DDepthStencilSurfAA, <br>&nbsp;&nbsp;*m_plD3DDepthStencilSurf;</p>
<p>&nbsp;CRenderTarget *m_pRTRefraction, *m_pRTReflection; //(自定义纹理类)</p>
<p>&nbsp;//-----------------------------------------------------------------------------------</p>
<p>&nbsp;// Get backbuffer<br>&nbsp;g_pDevice-&gt;GetRenderTarget(0, &amp;m_plD3DBackbufferSurf);<br>&nbsp;<br>&nbsp;// Get depthstencil <br>&nbsp;g_pDevice-&gt;GetDepthStencilSurface(&amp;m_plD3DDepthStencilSurfAA);<br>&nbsp;</p>
<p>&nbsp;// Restore previous states<br>&nbsp;g_pDevice-&gt;SetRenderTarget(0, m_plD3DBackbufferSurf);<br>&nbsp;g_pDevice-&gt;SetDepthStencilSurface(m_plD3DDepthStencilSurfAA);<br>&nbsp;<br>&nbsp;// (1)折射图--------------------------------------------------------------------------<br>&nbsp;<br>&nbsp;//下面的语句调用了 g_pDevice-&gt;CreateRenderTarget(iWidth, iHeight, (D3DFORMAT) iFormat, (D3DMULTISAMPLE_TYPE)iAASamples, 0, 0, &amp;m_plD3Surf, 0));<br>&nbsp;if(FAILED(m_pRTRefraction-&gt;Create(m_fWidth&gt;&gt;1, m_fHeight&gt;&gt;1, D3DFMT_A8R8G8B8)))<br>&nbsp;{<br>&nbsp;&nbsp;return APP_ERR_INITFAIL;<br>&nbsp;}<br>&nbsp;<br>&nbsp;// Create depthstencil withouth multisampling<br>&nbsp;g_pDevice-&gt;CreateDepthStencilSurface(m_fWidth, m_fHeight, D3DFMT_D24X8, (D3DMULTISAMPLE_TYPE)0, 0, 0, &amp;m_plD3DDepthStencilSurf, 0);<br>&nbsp;<br>&nbsp;<br>&nbsp;g_pDevice-&gt;SetRenderTarget(0, m_pRTReflection-&gt;GetSurface());<br>&nbsp;<br>&nbsp;g_pDevice-&gt;StretchRect(m_plD3DBackbufferSurf, 0, m_pRTRefraction-&gt;GetSurface(), 0, D3DTEXF_NONE); <br>&nbsp;<br>&nbsp;// (2)反射图-----------------------------------------------------------------------------------<br>&nbsp;m_pRTReflection=new CRenderTarget;<br>&nbsp;if(FAILED(m_pRTReflection-&gt;Create(m_fWidth&gt;&gt;2, m_fHeight&gt;&gt;2, D3DFMT_A8R8G8B8))) <br>&nbsp;{<br>&nbsp;&nbsp;return APP_ERR_INITFAIL;<br>&nbsp;}<br>&nbsp;<br>&nbsp;g_pDevice-&gt;SetRenderTarget(0, m_pRTReflection-&gt;GetSurface());<br>&nbsp; <br>&nbsp;<br>&nbsp;//-----------------------------------------------------------------------------------<br>&nbsp;g_pDevice-&gt;SetRenderTarget(0, m_pRTReflection-&gt;GetSurface());<br>&nbsp;g_pDevice-&gt;SetDepthStencilSurface(m_plD3DDepthStencilSurf);<br>&nbsp;g_pDevice-&gt;Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 0, 0, 128), 1.0f, 0);&nbsp;&nbsp; <br>&nbsp;SetViewport(m_pRTReflection-&gt;GetWidth(), m_pRTReflection-&gt;GetHeight());<br>&nbsp;//-----------------------------------------------------------------------------------<br>&nbsp;<br>&nbsp;D3DXSaveTextureToFile("imageTex.jpg",D3DXIFF_JPG,(IDirect3DTexture9*)m_pWavesBump-&gt;GetTexture(),NULL); <br>&nbsp;<br>7. 混合操作<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); &nbsp;&nbsp;&nbsp;//glDisable(GL_BLEND);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);&nbsp;&nbsp;//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);<br>&nbsp;</p>
<p>8. 灯光与材质<br>&nbsp;g_pDevice-&gt;SetRenderState(D3DRS_LIGHTING, FALSE);&nbsp;//glDisable(GL_LIGHTING);<br>&nbsp;<br>&nbsp;D3DMATERIAL9 mtrl;<br>&nbsp;mtrl.Ambient&nbsp; = a;<br>&nbsp;mtrl.Diffuse&nbsp; = d;<br>&nbsp;mtrl.Specular = s;<br>&nbsp;mtrl.Emissive = e;<br>&nbsp;mtrl.Power&nbsp;&nbsp;&nbsp; = p;<br>&nbsp;Device-&gt;SetMaterial(&amp;mtrl); &nbsp;//在设置纹理前设定<br>&nbsp;//设置当前使用的纹理<br>&nbsp;</p>
<img src ="http://www.cppblog.com/flashboy/aggbug/100912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-11-14 12:49 <a href="http://www.cppblog.com/flashboy/archive/2009/11/14/100912.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>wmo(wow map object) research</title><link>http://www.cppblog.com/flashboy/archive/2009/09/25/97235.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Fri, 25 Sep 2009 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/flashboy/archive/2009/09/25/97235.html</guid><wfw:comment>http://www.cppblog.com/flashboy/comments/97235.html</wfw:comment><comments>http://www.cppblog.com/flashboy/archive/2009/09/25/97235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flashboy/comments/commentRss/97235.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flashboy/services/trackbacks/97235.html</trackback:ping><description><![CDATA[wmo(wow map object) research<br>The wmo是一个非常有趣的设计，wow中比较小的物体使用doodad，而building使用wmo，<br>这里的building可以是桥梁、了望台、简单的小房子、复杂点的旅馆这样的房屋、非常<br>复杂的建筑群（例如地下城场景），本文对wmo场景文件进行简单的介绍，关于wmo文件的具<br>体信息请参考wowmapview的source code，这里非常感谢ufoz所做的贡献。<br>1、命名规则<br>wmo保存在以.wmo结尾的文件中，这个文件使用数据块来保存数据。一个wmo通常由一个或多个<br>group组成，而group数据也保存在以.wmo结尾的文件中，不过文件名称存在不同，例如一个wmo<br>保存在name.wmo文件中，那么group文件名就为name_001.wmo name_002.wmo......<br>2、结构<br>wmo就组织结构来说包含两个层次，group和batch。一个group通常包含多个batch，其中group包含<br>一个AABB。batch是wmo最小的渲染单元，它保存了顶点索引列表，可以直接调用DP进行渲染。group<br>内保存一个标志位，可以将group分为indoor/outdoor两类，这一个信息非常重要，通过它wmo就将<br>building分成了内外两部分，outdoor group就是building的外壳，他通过portal与室内场景连接<br>在一起。<br>3、portal<br>wmo文件中保存了portal信息，在wmo中规定group必须通过portal进行连接，portal由PVS和PRS<br>两部分组成，PVS记录portal顶点信息，PRS记录portal和group的连接信息，PRS结构如下：<br>struct WMOPR {<br>int portal;<br>int group;<br>int dir;<br>};<br>需要注意的是dir，这个成员只有两个值-1或1，由于portal的顶点信息按照顺时针记录，因此group<br>位于portal的正面时dir为1，否则为-1，通过dir可以快速确定group到底位于portal的哪一侧。<br>通过wmo中记录的portal信息可以使用portal culling来检查group的可见性，但是这里还是有一些<br>难度，主要是指portal的记录方式。由于一个group可能有多个portal，而查找连接的portal只能<br>通过PRS，这样在大的场景中非常不方便。而且在wmo中竟然没有记录portal的plane信息，如何确定<br>camera到底是位于portal的正面还是反面呢？（现在wmo文件由于没有完全破解，存在一些wowmapview<br>未读入的数据块，例如MVER、MOPT、MOVV、MOVB等，其中MVER应该是wmo文件的版本号，MOPT怀疑是保<br>存所有plane信息，而MOVV可能是保存包围体顶点信息，而MOVB保存包围体信息，MOVV、MOVB应当用于<br>碰撞检测，这些暂时没有验证）我的做法是在载入时计算portal的plane信息，并将PRS信息转换为类似<br>Q3 BSP中portal的结构。<br>struct portal_t {<br>int othergroup;<br>int pvs;//pvs index<br>int dir;<br>};<br>struct group_t {<br>int firstportal;<br>int numportals;<br>};<br>4、碰撞检测<br>在wmo中并没有使用BSP、OC TREE这样的结构来进行场景管理，可能所有人都感觉非常困惑。<br>场景管理的功能主要是为了加速渲染和方便碰撞检测，由于存在portal，这样第一个功能已经完成。<br>而对于碰撞检测，我的想法应当是AABB TREE。仔细观察WOW的场景可以发现在indoor场景中曲面、斜面<br>这样的几何物体非常少，大多数是规则物体，因此可以判断在wmo中所有的物体都是严格按照轴对齐<br>方式进行建模，也就是对规则性物体AABB=OBB。由于MOVV和MOVB信息并没有完全研究透彻，因此关于<br>这一部分只能是我的猜测。<br>5、渲染<br>对wmo的渲染由于batch的存在从而变的简单化，但还有可以优化的地方。由于wmo中使用portal将其分割<br>成group，因此有大量的材质相同的model被分割成不同的batch，在渲染时将材质相同的batch合并到一起<br>渲染可以避免一些无谓的DP调用。wmo一个令人诟病的地方是使用vertex light，为了减少图元数量从而<br>使顶点数量降低，造成渲染的时候出现色带效果，应当加入lightmap，由于wmo的场景通常不大，预处理<br>时做radiosity的时间也不会太长。<br>6、动态载入<br>对于只包含几个group的小场景的wmo，由于载入时间不是太长，在动态载入时一次性载入对程序影响<br>并不会太大。但是对于超大场景的wmo就需要考虑载入策略，这样场景典型的就是wow中的地下城场景，<br>它一个wmo中包含了几百个group，一次性载入时间非常长，需要分段进行载入。此时就显示出wmo分<br>文件保存group的优势了，为了实现动态载入wmo场景，一种可能的做法是在载入wmo后需要根据camera<br>所在的group快速的建立group连接层次图，这个图通过PRS数据建立，建立流程如下：<br>一、将camera所在group作为当前group，获得所有相连的protal；<br>二、将protal连接的group保存到第一层列表中，遍历第一层列表中所有的group；<br>三、获得第一层列表中group的portal，检查portal所连接的group是否保存在第一层列表中，如果没有<br>&nbsp;&nbsp;&nbsp; 将其保存到第二层列表中；<br>四、重复上述过程，直到整个层次图建立。<br>这个层次图可以预先建立然后保存到文件中运行时载入，这样wmo就是分层载入而不需要一次性载入。<br>（这里我考虑是否在wmo中也可以建立类似bsp的pvs数据呢？虽然pvs现在已经开始淘汰，但是如果<br>存在pvs就可以方便确定哪些group需要立即载入，只是不知被portal分割后的group到底是不是convex<br>hull，如果是的话可以建立pvs，但对建模时限制更加明显，两难的选择！！！）<br>7、建模<br>由于wmo是按照group对场景进行保存，因此为了建立wmo需要设计一个强力的模型构建工具，这个工具<br>主要功能就是对从建模工具（3DS MAX）中建立的场景模型进行分组和处理。美工在制作模型时需要非常<br>小心，所有的模型要严格的轴对齐（轴对齐的原因是需要模型的AABB=OBB），然后将模型导入工具中。<br>模型构建工具有以下功能：分组（group）功能、group选择、group显示/隐藏、指定portal，portal对<br>齐（考虑门、窗户这样天然的portal，手动指定portal时肯定无法与外表墙壁对齐，需要程序自动对齐）<br>、batch操作（分割、选择、显示/隐藏等）、图元级操作（triangle拣选，用于batch分割）、光照运算<br>（产生vertex light数据）、放置光源、放置doodad（场景中的道具，如桌子、椅子等）。可能还需要其<br>他一些功能，但是对比其他引擎的场景建模工具（hammer、sandbox）明显简单化许多。<br>8、优势及不足<br>当前处理室内场景的主流技术依然是bsp，但是随着硬件的发展bsp的优势在慢慢地丧失，bsp赖以生存的<br>预处理PVS现在已经完全被实时的portal culling所取代，bsp优势只剩下对图元排序（用于透明物体的<br>渲染）和基于brush的快速碰撞检测上，但是对比建模工具的复杂化和场景的限制，采用bsp的开销确实<br>显得太大。而基于纯portal引擎的结构开始流行，例如cryengine中处理室内场景时就完全抛弃bsp，<br>场景完全由一块块固定大小的墙壁组成，一块墙壁基本和bsp中brush类似，这样做的好处是建模工具变<br>的简单（不需要进行CSG运算），而且非常容易的产生portal，同时由于场景使用brush构成也兼具了<br>bsp方便进行碰撞检测的优势。wmo有些类似cryengine，但是在某些方面更具优势。<br>首先在建模方面，wmo的场景完全可以通过成熟的建模工具来构建，这样对于美工不需要重新学习新的<br>建模工具，可以节约大量的时间。其次模型构建工具需要的功能非常少，减少了程序的复杂性，缩短了<br>编写相关工具的时间。再次，场景管理简单化，相应代码量大幅度减少，同时由于portal的存在，可以方便<br>的与其他引擎相对接。可以说wmo是一种可以进行快速开发的场景结构。 
<img src ="http://www.cppblog.com/flashboy/aggbug/97235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flashboy/" target="_blank">RedLight</a> 2009-09-25 16:39 <a href="http://www.cppblog.com/flashboy/archive/2009/09/25/97235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>