﻿<?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++博客-zgpxgame</title><link>http://www.cppblog.com/zgpxgame/</link><description>像作诗一样写程序，像弹琴一样敲代码，像看小说一样读开源</description><language>zh-cn</language><lastBuildDate>Mon, 13 Apr 2026 09:41:13 GMT</lastBuildDate><pubDate>Mon, 13 Apr 2026 09:41:13 GMT</pubDate><ttl>60</ttl><item><title>Chromium编译记录</title><link>http://www.cppblog.com/zgpxgame/archive/2012/12/17/196370.html</link><dc:creator>zgpxgame</dc:creator><author>zgpxgame</author><pubDate>Mon, 17 Dec 2012 03:19:00 GMT</pubDate><guid>http://www.cppblog.com/zgpxgame/archive/2012/12/17/196370.html</guid><wfw:comment>http://www.cppblog.com/zgpxgame/comments/196370.html</wfw:comment><comments>http://www.cppblog.com/zgpxgame/archive/2012/12/17/196370.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/zgpxgame/comments/commentRss/196370.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zgpxgame/services/trackbacks/196370.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">Chromium编译：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">Visual&nbsp;Studio&nbsp;2008&nbsp;sp1</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">开发环境准备：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">1.</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">强烈建议在64位系统上进行编译调试，内存至少4G，硬盘至少20~30G，如果有SSD硬盘可以大大加快编译速度</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">2.</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">安装windows&nbsp;7&nbsp;SDK&nbsp;</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><a href="http://www.microsoft.com/en-us/download/details.aspx?id=8442"><span style="color: #0000ff; font-size: 10pt; font-family: 宋体;">http://www.microsoft.com/en-us/download/details.aspx?id=8442</span></a></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="color: #4f4f4f; font-size: 9pt; font-family: 'Segoe UI'; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial;">GRMSDK_EN_DVD.iso</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">3.</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">下载</span><a href="http://www.chromium.org/developers/how-tos/install-depot-tools"><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">depot_tools</span></a></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><a href="https://src.chromium.org/svn/trunk/tools/depot_tools.zip"><span style="color: #0000ff; font-size: 10pt; font-family: 宋体;">https://src.chromium.org/svn/trunk/tools/depot_tools.zip</span></a></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">depot_tools</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">添加到PATH环境变量</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">4.</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">下载chromium代码</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">新建文件夹</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">chromium-release</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">用于存放chromium代码，在命令行切换到这个文件夹，</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">	</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">执行命令：</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">4.1&nbsp;</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">gclient&nbsp;config</span>&nbsp;<a href="http://src.chromium.org/svn/releases/16.0.904.0"><span style="color: #0000ff; font-size: 10pt; font-family: 宋体;">http://src.chromium.org/svn/releases/16.0.904.0</span></a></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">如果想获取其他版本，在浏览器中打开</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">http://src.chromium.org/svn/releases/</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">，找到想获取的版本，将上面命令中的地址替换即可。其他版本不保证能在此步骤下成功编译</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">4.2&nbsp;编辑生成的.gclient文件，以减少下载一些测试工程</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">&nbsp;&nbsp;</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">	</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"custom_deps":&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/third_party/WebKit/LayoutTests":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/content/test/data/layout_tests/LayoutTests":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/chrome/tools/test/reference_build/chrome_win":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/chrome_frame/tools/test/reference_build/chrome_win":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/chrome/tools/test/reference_build/chrome_linux":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/chrome/tools/test/reference_build/chrome_mac":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">"src/third_party/hunspell_dictionaries":&nbsp;None,</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">},</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">4.3&nbsp;执行命令</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">gclient&nbsp;sync</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">更新代码，大约花费</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">2~3小时？如果网络不好，更新期间有可能中断，再重新执行命令</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">gclient&nbsp;sync</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">。</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">更新完成后，会</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">自动生成</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">平台相关的工程文件，如果没有生成可执行以下命令来生成</span><span style="font-family: 宋体;"><font size="2">：</font></span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">set&nbsp;GYP_MSVS_VERSION=2008</span></p><p style="margin-left:21.0000pt; text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">gclient&nbsp;runhooks&nbsp;--force</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">5.打开src/chrome/</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">chrome.sln</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">，将</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">chrome工程设置为启动项目</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">，编译</span></p><p style="margin-bottom:0pt; margin-top:0pt; "></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">其他参考：</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">http://www.wangth.com/?p=264</span></p></div><img src ="http://www.cppblog.com/zgpxgame/aggbug/196370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zgpxgame/" target="_blank">zgpxgame</a> 2012-12-17 11:19 <a href="http://www.cppblog.com/zgpxgame/archive/2012/12/17/196370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doom3源码剖析资料整理</title><link>http://www.cppblog.com/zgpxgame/archive/2012/07/07/182002.html</link><dc:creator>zgpxgame</dc:creator><author>zgpxgame</author><pubDate>Fri, 06 Jul 2012 19:25:00 GMT</pubDate><guid>http://www.cppblog.com/zgpxgame/archive/2012/07/07/182002.html</guid><wfw:comment>http://www.cppblog.com/zgpxgame/comments/182002.html</wfw:comment><comments>http://www.cppblog.com/zgpxgame/archive/2012/07/07/182002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zgpxgame/comments/commentRss/182002.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zgpxgame/services/trackbacks/182002.html</trackback:ping><description><![CDATA[<a title="DOOM3_SOURCE_CODE_REVIEW.doc" href="/Files/zgpxgame/DOOM3_SOURCE_CODE_REVIEW.doc">DOOM3_SOURCE_CODE_REVIEW.doc</a><img src ="http://www.cppblog.com/zgpxgame/aggbug/182002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zgpxgame/" target="_blank">zgpxgame</a> 2012-07-07 03:25 <a href="http://www.cppblog.com/zgpxgame/archive/2012/07/07/182002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doom3源码剖析（2）--架构简介（译）</title><link>http://www.cppblog.com/zgpxgame/archive/2012/04/25/172673.html</link><dc:creator>zgpxgame</dc:creator><author>zgpxgame</author><pubDate>Tue, 24 Apr 2012 16:07:00 GMT</pubDate><guid>http://www.cppblog.com/zgpxgame/archive/2012/04/25/172673.html</guid><wfw:comment>http://www.cppblog.com/zgpxgame/comments/172673.html</wfw:comment><comments>http://www.cppblog.com/zgpxgame/archive/2012/04/25/172673.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/zgpxgame/comments/commentRss/172673.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zgpxgame/services/trackbacks/172673.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 前段时间看到国外一博客上的几篇Doom3代码分析的文章，感觉分析得不错，就自己翻译了一下，以下是译文，有不太理解地方就直接贴了原文。大部分是按自己的理解翻译的，可能有些地方译的并不精确。有喜欢的朋友可以在这里看原文：<a href="http://fabiensanglard.net/doom3/"><font color="#ff0000">http://fabiensanglard.net/doom3/</font></a>，这里欢迎各种讨论。</p> <p>&nbsp;</p> <p><strong>简介</strong>  </p><p>&nbsp;&nbsp;&nbsp; 2011年11月23日，id Software依照惯例发布了前一代引擎的源码，这次发布的是Doom3引擎，<a href="http://en.wikipedia.org/wiki/Id_Tech_4">id Tech 4</a>。  </p><p>&nbsp;&nbsp;&nbsp; Within hours the GitHub repository was forked more than 400 times，大家在不同的平台上编译并且查看游戏的内部实现机制。我也马上开始了Mac版本代码的学习。  </p><p>&nbsp;&nbsp;&nbsp; 这份代码在清晰度和注释方面，是继id Software发布Doom iPhone代码后，最好的一份代码。我建议每一个爱好者都去读一读，并研习这份代码的实现。  </p><p><a href="http://fabiensanglard.net/doom3/doom3.txt">&nbsp;&nbsp;&nbsp; 这里</a>是我的笔记，里面记录了我理解到的一些内容。像往常一样，我将其整理地清晰了一些，我希望它能帮助一些朋友节省一些时间，并且我也希望它能促使我们阅读更多的代码，并成为更优秀的程序员。  </p><p>&nbsp; </p><p><strong>背景</strong>  </p><p>&nbsp;&nbsp;&nbsp; 拿到这份具有开创性的引擎代码是一件很令人兴奋的事情。早在2004年Doom3发行时，它确立了实时3D图形和音频的新标准。它首次使技术上允许美术创作人员像好莱坞模式那样去表达自己的想法。尽管8年过去了，首次在Delta Labs 4遇见HellKnight的情景仍然很震撼:  </p><p>&nbsp;&nbsp;&nbsp; 视频在<a href="http://v.youku.com/v_show/id_XMzg2MzM0OTMy.html" target="_blank">这里</a>  </p><p>&nbsp;&nbsp;&nbsp; 由卡马克创造的&#8220;统一的照明和阴影&#8221;概念在这个视频里表现得很有活力，我将在后面的渲染部分再介绍这部分内容。  </p><p>&nbsp; </p><p><strong>初次的接触</strong>  </p><p>&nbsp;&nbsp;&nbsp; Doom3源代码发布现在开始用github，而不再是以前的ftp server。  </p><p>&nbsp;&nbsp;&nbsp; 从TTimo发布的原始代码很容易在Visual Studio 2010上编译。不幸的是，不能用Visual Studio 2010 Express版编译，因为Doom3代码中使用了MFC，而Express版没有。  </p><p>&nbsp;&nbsp;&nbsp; windows代码在这里：git clone <a href="https://github.com/TTimo/doom3.gpl.git">https://github.com/TTimo/doom3.gpl.git</a>  </p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img style="display: inline" alt="" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/doom3_vs2010.png" width="257" height="248" />  </p><p>&nbsp; </p><p>&nbsp;&nbsp;&nbsp; 我喜欢在Mac系统下用XCode浏览代码。相比于Visual Studio，它在搜索速度和变量的高亮方面都给我很享受的体验。我想用XCode来编译程序，但是项目设置有一些问题。不过很容易通过几个<a href="http://fabiensanglard.net/doom3_macosx/index.php">简单的步骤</a>修复好。这里有一个github已包含了所有的修改。  </p><p>&nbsp;&nbsp;&nbsp; git clone https://github.com/badsector/Doom3-for-MacOSX-  </p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/doom_xcode.png" width="261" height="329" />  </p><p>这两份代码都很容易编译，可以一键完成。  </p><li>下载代码  </li><li>点F8或Command+B （译注：大概是xcode构建快捷键）  </li><li>完成  <blockquote> <p>杂记：为了运行游戏，base文件夹下需要包含Doom3 的资源。由于我的机器上没有cd驱动器，所以我下载了Steam版本。似乎id Software也做了同样的事，在Visual Studio的项目设置里仍然包含了这样的字符"+set fs_basepath C:\Program Files (x86)\Steam\steamapps\common\doom 3" ! </p></blockquote> <p><strong>架构</strong>  </p><p>&nbsp;&nbsp;&nbsp; 解决方案（solution）中项目的划分反映了整个引擎的架构 </p> <p align="left"><img src="http://www.cppblog.com/images/cppblog_com/zgpxgame/table.jpg" width="575" height="324" alt="" /><br /></p> <p align="left">&nbsp;</p> <p>&nbsp;&nbsp;&nbsp; 下面以更可视化的方式来概括这个架构 </p> <p><a href="http://www.cppblog.com/images/cppblog_com/zgpxgame/Windows-Live-Writer/f2d2c81b5ee7_13ECA/doom3_diagram2_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="doom3_diagram2" border="0" alt="doom3_diagram2" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/Windows-Live-Writer/f2d2c81b5ee7_13ECA/doom3_diagram2_thumb_1.png" width="672" height="630" /></a></p> <p>&nbsp;&nbsp;&nbsp; Doom3的大部分代码在2004年10月的时候可以通过发布的<a href="http://www.iddevnet.com/">Doom3 SDK</a>中看到，但是SDK里没有Doom3执行文件部分代码。在SDK中可以构建idLib部分和gamex86部分，核心引擎部分那时仍然是闭源的。 </p> <blockquote> <p>注意：在游戏模块(gamex86)，每一个类都是从idClass继承的，这样引擎可以执行内部RTTI，并且也可以通过类名字来实例化类。 </p> <p>杂记：你仔细观察上面的架构图，可能会发现有一些基本框架（例如FileSystem）只在Doom3.exe中。这里就会有一个问题，就是当gamex86也要加载资源的时候。 </p> <p>问：那么gamex86是如何处理的呢？ </p> <p>答：这些子系统是从Doom3.exe中动态加载到gamex86.dll中的，这也是指示箭头出现的原因。 </p></blockquote> <p>&nbsp;</p> <p>&nbsp;&nbsp;&nbsp; 如果我们使用PE explorer等工具查看gamex86.dll，我们会看到gamex86.dll导出了一个函数：GetGameAPI: <img alt="" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/gamex86.dll.export.png" width="754" height="561" />&nbsp;</p> <p>这是同Quake2加载renderer和game 动态库方式一模一样：当Doom3启动gamex86.dll的时候，会交换对象的指针 </p> <ul> <li>通过LoadLibrary将dll加载到进程的内存空间中  </li><li>通过GetProcAddress获取GetGameAPI在gamex86.dll中的地址  </li><li>调用GetGameAPI </li></ul> <blockquote> <p><font size="2" face="Courier New">gameExport_t * GetGameAPI_t( gameImport_t *import ); </font></p></blockquote> <p>&nbsp;&nbsp;&nbsp; 在最后完成&#8220;握手&#8221;时，Doom3.exe有一个指针指向idGame对象，gamex86.dll有一个指针指向gameImport_t对象，这个对象包含了gamex86.dll中没有的子系统，比如idFileSystem。 </p> <p><font size="2" face="Courier New">typedef struct { </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; int&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // API version </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idSys *&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;&nbsp;&nbsp; sys;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // non-portable system services </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idCommon *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; common;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // common </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idCmdSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmdSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // console command system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idCVarSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cvarSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // console variable system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idFileSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // file system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idNetworkSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; networkSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // network system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idRenderSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; renderSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // render system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idSoundSystem *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soundSystem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // sound system </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idRenderModelManager *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; renderModelManager;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // render model manager </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idUserInterfaceManager *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uiManager;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // user interface manager </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idDeclManager *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; declManager;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // declaration manager </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idAASFileManager *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AASFileManager;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // AAS file manager </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idCollisionModelManager *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; collisionModelManager;&nbsp;&nbsp;&nbsp; // collision model manager </font></p> <p><font size="2" face="Courier New">} gameImport_t; </font></p> <p><font size="2" face="Courier New"></font>&nbsp;</p> <p><font size="2" face="Courier New">typedef struct { </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version;&nbsp;&nbsp;&nbsp;&nbsp; // API version </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idGame *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; game;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // interface to run the game </font></p> <p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; idGameEdit *&nbsp;&nbsp; gameEdit;&nbsp;&nbsp;&nbsp; // interface for in-game editing </font></p> <p><font size="2" face="Courier New">} gameExport_t; </font></p> <p>&nbsp;</p> <blockquote> <p>注意：一个好消息是，id tech4的开发者在<a href="http://www.iddevnet.com/doom3/code.php">Doom3 SDK 文档</a>页很好的描述了各个子系统。  </p><p>&nbsp;</p></blockquote> <p><strong>C&#8230; ++ ?!</strong>  </p><ul> <li>在id Software历史上这是第一次用C++代码代替了C。关于此事我问了卡马克： </li></ul> <blockquote> <p>"  </p><p>Hello John,  </p><p>I wonder what motivated to move the team to C++ for idtech4.  </p><p>Fab  </p><p>"  </p><p>"  </p><p>There was a sense of inevitability to it at that point, but only about half the programmers really had C++ background in the beginning. I had C and Objective-C background, and I sort of "slid into C++" by just looking at the code that the C++ guys were writing. In hindsight, I wish I had budgeted the time to thoroughly research and explore the language before just starting to use it.  </p><p> </p><p>You may still be able to tell that the renderer code was largely developed in C, then sort of skinned into C++.  </p><p> </p><p>Today, I do firmly believe that C++ is the right language for large, multi-developer projects with critical performance requirements, and Tech 5 is a lot better off for the Doom 3 experience.  </p><p> </p><p>John Carmack</p> <p>"</p> <p>他也在2004年的时候有<a href="http://rome.ro/smf/index.php?topic=3086.0">评论</a>：</p> <p>"<br />Is C++ a better language for developing games than C? Today, most games are developed in C++, and I know that Doom 3 was developed in C++. Having worked with both C and C++ for quite a while, do you think C++ is really a better language for developing games? </p> <p>"  </p><p>"  </p><p>Yes, it is. I'm not a fan of the more complex features of C++, but grouping things into classes is a Good Thing.  </p><p>John Carmack  </p><p>"</p></blockquote> <ul> <li>代码中使用了大量抽象和多态。但是一个漂亮的技巧可以避免某些对象因虚函数表而带来的性能问题。  </li><li>所有的资源都使用可读性很好的文本方式存储。没有太多的二进制内容。代码中广泛地使用了Lexer/Parser的组合。  </li><li>模板被用在低层实用类中（idLib），但是从不会在高层代码中出现，不会像Google的V8代码那样刺瞎你的眼。  </li><li>在代码注释方面，它是id Software的代码中第二好的，最好的是Doom iPhone代码，可能因为它比Doom3是更近的一段时间编写的。  </li><li>看一下编码约定也是很有趣的事情，在<a href="ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc">这里</a>。 </li></ul> <p>&nbsp;</p> <p><strong>主循环概览</strong></p><p>&nbsp;&nbsp;&nbsp; 这里是主循环展开后的代码：（更详细的在<a href="http://fabiensanglard.net/doom3/doom3_unrolled.php">这里</a>）</p><p><font size="2" face="Courier New">idCommonLocal&nbsp;&nbsp;&nbsp; commonLocal;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // OS Specialized object </font> </p><p><font size="2" face="Courier New">idCommon *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; common = &amp;commonLocal;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Interface pointer (since Init is OS dependent it is an abstract method </font> </p><p><font size="2" face="Courier New">int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) </font> </p><p><font size="2" face="Courier New">{ </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_SetPhysicalWorkMemory( 192 &lt;&lt; 20, 1024 &lt;&lt; 20 );&nbsp;&nbsp; //Min = 201,326,592 Max = 1,073,741,824 </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_GetCurrentMemoryStatus( exeLaunchMemoryStats ); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_CreateConsole(); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; SetErrorMode( SEM_FAILCRITICALERRORS ); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; for ( int i = 0; i &lt; MAX_CRITICAL_SECTIONS; i++ ) { </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeCriticalSection( &amp;win32.criticalSections[i] ); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; } </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_Milliseconds(); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; common-&gt;Init( 0, NULL, lpCmdLine );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Assess how much VRAM is available (not done via OpenGL but OS call) </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_StartAsyncThread() // 开启异步线程 </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 异步线程展开（译注：异步线程中并没有找到类似的代码） </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ( 1 ) </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usleep( 16666 );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Run at 60Hz </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; common-&gt;Async();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Do the job </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sys_TriggerEvent( TRIGGER_EVENT_ONE );&nbsp;&nbsp; // Unlock other thread waiting for inputs </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_testcancel();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Check if we have been cancelled by the main thread (on shutdown). </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; } </font> </p><p><font face="Courier New"></font><font size="2">&nbsp; </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; Sys_ShowConsole </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; while ( 1 ) </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; { </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Win_Frame(); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; common-&gt;Frame(); </font> </p><p><font size="2" face="Courier New">&nbsp;&nbsp;&nbsp; } </font> </p><p><font size="2" face="Courier New">} </font> </p><p><font face="Courier New"></font>&nbsp; </p><p>&nbsp;&nbsp;&nbsp; 这是id Software引擎的标准主循环，除了Sys_StartAsyncThread函数表明Doom3是多线程的，这个线程的目的是为了处理时间敏感的功能，引擎不希望这部分被帧率限制住。  </p><ul> <li>声音处理  </li><li>用户输入处理 </li></ul> <blockquote> <p>杂记：id Tech4的高层对象都是抽象类，这将会使程序在运行时从虚函数表中查找虚函数地址而导致性能问题。但是这里有一个&#8220;技巧&#8221;来避免这个问题。所有的对象被以静态的方式实例化，如下：  </p><p><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; idCommonLocal&nbsp;&nbsp;&nbsp; commonLocal;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implementation </font> </p><p><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; idCommon *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; common = &amp;commonLocal;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Interface manipulated in the code </font> </p><p>这样编译器在编译时就可以决定被调用的函数，从而不用去查找虚函数表。这实际上是一个双赢，since the pointer does not have to be dereferenced at runtime either since its address is known at compile time.&nbsp; </p><p>杂记：已经读过6、7款id Software引擎的我发现，有一些函数名从doom1开始就一直没有改变过：负责处理鼠标和游戏杆输入的函数仍然叫IN_frame()  </p><p>&nbsp;</p></blockquote> <p><strong>渲染器</strong>  </p><p>&nbsp;&nbsp;&nbsp; Doom3中最令人兴奋的当然是渲染器部分。这里有太多的内容，所以我将这部分的笔记分到另一篇文章里了。在<a href="http://fabiensanglard.net/doom3/renderer.php">这里</a><br />&nbsp;&nbsp;&nbsp; 如果你对（场景）预处理和入口系统（portal system）很感兴趣，可以看<a href="http://fabiensanglard.net/doom3/dmap.php">这里</a>。  </p><p>&nbsp; </p><p><strong>新的标准</strong>  </p><p>&nbsp;&nbsp;&nbsp; 新的标准可以概括为一个词：Unification  </p><p>&nbsp;&nbsp;&nbsp; 前一代引擎在渲染所有元素的时候，使用的是不同的方式，经常要花费很长时间的预处理。Quake2中的基于光能传递的lightmap，在设计者能看到最终的效果前需要等很长时间。  </p><p>&nbsp; </p><p><strong>物理引擎</strong>  </p><p>（译注：原文这里没有内容，大概还没写好）  </p><p>&nbsp; </p><p><strong></strong> </p><p><strong>脚本和虚拟机</strong>  </p><p>（译注：原文这里没有内容，大概还没写好）  </p><p>&nbsp; </p><p><strong>地图加载</strong>  </p><p>&nbsp;&nbsp;&nbsp; 我记忆中，加载所消耗的时间很长，我一直想知道在加载场景的时候，程序背后都做了些什么。  </p><p>&nbsp; </p><p><strong>结语</strong>  </p><p>&nbsp;&nbsp;&nbsp; It was not always easy to focus...  </p><p><img alt="" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/hard_to_focus_small.jpg" />  </p><p>&nbsp;&nbsp;&nbsp; But overall it was very educationnal to read most of it.  </p><p><img alt="" src="http://www.cppblog.com/images/cppblog_com/zgpxgame/macPro.jpg" />  </p></li><img src ="http://www.cppblog.com/zgpxgame/aggbug/172673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zgpxgame/" target="_blank">zgpxgame</a> 2012-04-25 00:07 <a href="http://www.cppblog.com/zgpxgame/archive/2012/04/25/172673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doom3源码剖析（1）--TypeInfo</title><link>http://www.cppblog.com/zgpxgame/archive/2012/04/22/172361.html</link><dc:creator>zgpxgame</dc:creator><author>zgpxgame</author><pubDate>Sun, 22 Apr 2012 12:28:00 GMT</pubDate><guid>http://www.cppblog.com/zgpxgame/archive/2012/04/22/172361.html</guid><wfw:comment>http://www.cppblog.com/zgpxgame/comments/172361.html</wfw:comment><comments>http://www.cppblog.com/zgpxgame/archive/2012/04/22/172361.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/zgpxgame/comments/commentRss/172361.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zgpxgame/services/trackbacks/172361.html</trackback:ping><description><![CDATA[<p style="text-indent: 21pt; ">TypeInfo<span style="font-family: 宋体; ">模块是</span>Doom3<span style="font-family: 宋体; ">中用于动态类型识别（RTTI）和辅助查错的模块，可以检测类中未初始化变量、打印某种类型的对象中所有成员变量的值，或打印整个程序中所有实体对象</span>(idEntity)<span style="font-family: 宋体; ">的值。在写程序过程中，可能经常会出现一些由于未对成员变量初始化而导致的问题。而这类问题一般在</span>Debug<span style="font-family: 宋体; ">模式下没有问题，在</span>Release<span style="font-family: 宋体; ">版本中偶尔出现，这导致很难定位与问题相关的代码。</span></p><p><span style="font-family: 宋体; ">&nbsp; &nbsp; 除了检测未初始化的内存，其他方面的应用，可以从</span>TypeInfo.h<span style="font-family: 宋体; ">中的几个函数可以略窥一二。</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">&nbsp;<span style="color: #008000; ">/*<br /></span><span style="color: #008000; ">===================================================================================</span>&nbsp;<br /><br /><font color="#008000">&nbsp; &nbsp; Game&nbsp;Type&nbsp;Info</font><br /><br /><font color="#008000">===================================================================================</font><br /><span style="color: #008000; ">*/</span><br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;根据偏移取得变量名</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*&nbsp;GetTypeVariableName(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*typeName,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;offset&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;打印某个对象的信息</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;PrintType(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*typePtr,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*typeName&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;将某对象值写入文件</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;WriteTypeToFile(&nbsp;idFile&nbsp;*fp,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*typePtr,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*typeName&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;给某对象的所有变量设定一个初始值</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;InitTypeVariables(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*typePtr,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*typeName,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;value&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;列举所有类型信息</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;ListTypeInfo_f(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;idCmdArgs&nbsp;&amp;args&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;将所有游戏状态（所有idEntity信息）写入文件</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;WriteGameState_f(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;idCmdArgs&nbsp;&amp;args&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;比较游戏状态</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;CompareGameState_f(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;idCmdArgs&nbsp;&amp;args&nbsp;);<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;测试保存游戏</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;TestSaveGame_f(&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;idCmdArgs&nbsp;&amp;args&nbsp;);</div><p style="text-indent: 21pt; "><span style="font-family: 宋体; "><br />经过几天的努力，我将</span>TypfInfo<span style="font-family: 宋体; ">相关的代码提取出，单独创建了工程文件，并做了简单的代码演示。有爱好的同学可以深入研究。点击<a title="这里" href="http://www.cppblog.com/Files/zgpxgame/TypeInfo.rar">这里</a>下载。在工程（</span>
<span style="font-family: 宋体; ">vs2010）</span>&nbsp;<span style="font-family: 宋体; ">中，Example是一个简单的演示程序，idLib是对Doom3源码中idLib的删减版本。TypeInfo是生成GameTypeInfo.h类型信息的控制台工具。<br /><br />TypeInfo的用法为 typeinfo.exe [source_code_path] [out_file_name]</span></p><p>&nbsp;</p><p><span style="font-family: 宋体; ">实现：</span></p><p style="text-indent: 21pt; ">TypeInfo<span style="font-family: 宋体; ">检测未初始化内存实现原理为，对代码中所有的头文件扫描分析，并将类型中，变量名，变量类型等信息记录生成一个</span>GameTypeInfo.h<span style="font-family: 宋体; ">文件。然后在</span>new<span style="font-family: 宋体; ">一个对象时，会先将这个对象的内存初始化为</span>0xcdcdcdcd<span style="font-family: 宋体; ">。当对象构造完成时，检测对象内存中是否有某值为</span>0xcdcdcdcd<span style="font-family: 宋体; ">，如果有，就通过</span>GameTypeInfo.h<span style="font-family: 宋体; ">中记录的类型，变量名，偏移等信息将未初始化的变量信息打印出来。</span></p><p><span style="font-family: 宋体; ">将上述过程分为三段内容：</span>1.&nbsp;<span style="font-family: 宋体; ">解析</span>&nbsp;2.&nbsp;<span style="font-family: 宋体; ">生成类型信息</span>&nbsp;3.&nbsp;<span style="font-family: 宋体; ">利用类型信息</span></p><p>&nbsp;</p><p><span style="font-family: 宋体; ">1. 解析：</span></p><p style="text-indent: 21pt; "><span style="font-family: 宋体; ">基本的词法解析在</span>idLib<span style="font-family: 宋体; ">中实现，相关类为</span>idToken, idLexer, idParser<span style="font-family: 宋体; ">。</span></p><p>&nbsp;</p><p><span style="font-family: 宋体; ">2. 生成类型信息</span></p><p style="text-indent: 21pt; ">idTypeInfoGen<span style="font-family: 宋体; ">利用</span>idParser<span style="font-family: 宋体; ">来解析代码头文件，记录相关类型信息，类型信息包括：常量，枚举量和类（包括结构体）</span></p><p>&nbsp;</p><div style="padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; width: 839px; word-break: break-all; "><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;常量信息</span>&nbsp;<br />typedef&nbsp;<span style="color: #0000ff; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;type;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;value;<br />}&nbsp;constantInfo_t;<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;枚举形变量信息</span><span style="color: #008000; "><br /></span>typedef&nbsp;<span style="color: #0000ff; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;value;<br />}&nbsp;enumValueInfo_t;<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;枚举类型信息</span><span style="color: #008000; "><br /></span>typedef&nbsp;<span style="color: #0000ff; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;typeName;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;enumValueInfo_t&nbsp;*&nbsp;values;<br />}&nbsp;enumTypeInfo_t;<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;类成员变量信息</span><span style="color: #008000; "><br /></span>typedef&nbsp;<span style="color: #0000ff; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;type;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;offset;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;size;<br />}&nbsp;classVariableInfo_t;<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;类的类型信息（包括结构体）</span><span style="color: #008000; "><br /></span>typedef&nbsp;<span style="color: #0000ff; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;typeName;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*&nbsp;superType;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;size;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;classVariableInfo_t&nbsp;*&nbsp;variables;<br />}&nbsp;classTypeInfo_t;</div><p><span style="font-family: 宋体; ">所有信息记录在GameTypeInfo.h中，详细内容可以查阅源代码。<br /><br />3. 对类型信息的利用</span></p><p style="text-indent: 21pt; "><span style="font-family: 宋体; ">3.1 通过类型名创建实例。在</span>Doom3<span style="font-family: 宋体; ">程序的</span>GamePlay<span style="font-family: 宋体; ">层，主要的类都是从</span>idClass<span style="font-family: 宋体; ">继承下来的，并且在类声明和定义时，通过</span>idTypeInfo<span style="font-family: 宋体; ">记录类型信息，包括记录类之间的父子关系。在类中加入宏</span>CLASS_PROTOTYPE<span style="font-family: 宋体; ">，</span>&nbsp;CLASS_DECLARATION<span style="font-family: 宋体; ">来实现。<br />创建类实例时是这样的：</span></p><div style="padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; width: 839px; word-break: break-all; ">idTypeInfo&nbsp;*cls;<br />idClass&nbsp;*obj;<br />cls&nbsp;=&nbsp;idClass::GetClass( "idPlayer" );<br />obj&nbsp;=&nbsp;cls-&gt;CreateInstance();</div><p>&nbsp;</p><p><span style="font-family: 宋体; ">&nbsp; &nbsp; 3.2 输出未初始化变量的名称。</span></p><p>&nbsp; &nbsp; &nbsp;idClass中重载了new操作符，以便记录内存的使用量和创建的对象个数，如果需要检测未初始化的内存，还会将内存初始化为0xcdcdcdcd。<br /></p><div style="padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; width: 839px; word-break: break-all; "><span style="color: #0000ff; ">void</span>&nbsp;*&nbsp;idClass::<span style="color: #0000ff; ">operator</span>&nbsp;<span style="color: #0000ff; ">new</span>(&nbsp;size_t&nbsp;s&nbsp;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;*p;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;+=&nbsp;<span style="color: #0000ff; ">sizeof</span>(&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;(<span style="color: #0000ff; ">int</span>&nbsp;*)Mem_Alloc(&nbsp;s&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;*p&nbsp;=&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;memused&nbsp;+=&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;numobjects++;<br /><br />#ifdef&nbsp;ID_DEBUG_UNINITIALIZED_MEMORY<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000ff; ">long</span>&nbsp;*ptr&nbsp;=&nbsp;(unsigned&nbsp;<span style="color: #0000ff; ">long</span>&nbsp;*)p;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;size&nbsp;=&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;assert(&nbsp;(&nbsp;size&nbsp;&amp;&nbsp;3&nbsp;)&nbsp;==&nbsp;0&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;&gt;&gt;=&nbsp;2;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">for</span>&nbsp;(&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;&nbsp;size;&nbsp;i++&nbsp;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ptr[i]&nbsp;=&nbsp;0xcdcdcdcd;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #0000ff; ">#endif</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">return</span>&nbsp;p&nbsp;+&nbsp;1;<br />}</div><p>&nbsp;</p><p><span style="font-family: 宋体; ">&nbsp;<br />&nbsp; &nbsp; 对象创建后，调用</span>FindUninitializedMemory来检测未初始化的内存<br /></p><div style="padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; width: 839px; word-break: break-all; "><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />================<br />idClass::FindUninitializedMemory<br />================<br /></span><span style="color: #008000; ">*/</span><br /><span style="color: #0000ff; ">void</span>&nbsp;idClass::FindUninitializedMemory(&nbsp;<span style="color: #0000ff; ">void</span>&nbsp;)&nbsp;{<br />#ifdef&nbsp;ID_DEBUG_UNINITIALIZED_MEMORY<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000ff; ">long</span>&nbsp;*ptr&nbsp;=&nbsp;(&nbsp;(&nbsp;unsigned&nbsp;<span style="color: #0000ff; ">long</span>&nbsp;*&nbsp;)<span style="color: #0000ff; ">this</span>&nbsp;)&nbsp;-&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;size&nbsp;=&nbsp;*ptr;<br />&nbsp;&nbsp;&nbsp;&nbsp;assert(&nbsp;(&nbsp;size&nbsp;&amp;&nbsp;3&nbsp;)&nbsp;==&nbsp;0&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;&gt;&gt;=&nbsp;2;<br />&nbsp;&nbsp;&nbsp;&nbsp;ptr&nbsp;=&nbsp;(&nbsp;unsigned&nbsp;<span style="color: #0000ff; ">long</span>&nbsp;*&nbsp;)<span style="color: #0000ff; ">this</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">for</span>&nbsp;(&nbsp;<span style="color: #0000ff; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;size;&nbsp;i++&nbsp;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">if</span>&nbsp;(&nbsp;ptr[i]&nbsp;==&nbsp;0xcdcdcdcd&nbsp;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">const</span>&nbsp;<span style="color: #0000ff; ">char</span>&nbsp;*varName&nbsp;=&nbsp;GetTypeVariableName(&nbsp;GetClassname(),&nbsp;i&nbsp;&lt;&lt;&nbsp;2&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idLib::Warning(&nbsp;"type&nbsp;'%s'&nbsp;has&nbsp;uninitialized&nbsp;variable&nbsp;%s&nbsp;(offset&nbsp;%d)",&nbsp;GetClassname(),&nbsp;varName,&nbsp;i&nbsp;&lt;&lt;&nbsp;2&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #0000ff; ">#endif</span><br />}</div><span style="font-family: 宋体; ">&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; 这里通过</span>&nbsp;<span style="font-size: 13px; background-color: #eeeeee; ">GetTypeVariableName</span>&nbsp;在类型信息表中查找变量名称。<br /><span style="font-family: 宋体; "><br /><br />&nbsp; &nbsp; 3.3打印输出某个实例的所有成员变量值。</span><p>&nbsp;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;代码实现在TypeInfo.cpp文件中，没有仔细研究这段代码实现，就不在这里单列了。</p><img src ="http://www.cppblog.com/zgpxgame/aggbug/172361.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zgpxgame/" target="_blank">zgpxgame</a> 2012-04-22 20:28 <a href="http://www.cppblog.com/zgpxgame/archive/2012/04/22/172361.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>