原文地址 http://fabiensanglard.net/doom3/

2012年6月8日

DOOM3源代码评测:简介(第1部分,共6部分)>>

2011年11月23日,id软件保持传统,并发布了其以前引擎的源代码。这一次是轮到了idTech4,使用它,创造出Prey,quake4,当然是Doom 3.在几个小时之内,GitHub上的源代码被下载了400多次,人们开始看游戏内部机制/在其他平台上引导引擎。我也跳上它,并及时完成了Mac OS X的Intel版本 约翰·卡马克。

在清晰度和评论方面,这是 Doom iPhone代码库(这是更新的,因此更好的评论)的id软件最好的开源代码。我强烈建议大家阅读,编译和实验。

下面是我的笔记就我的理解。像往常一样,我已经清理了它:我希望它会节省一个人几个小时,我也希望它会激励我们中的一些人的代码,并成为更好的程序员。

第1部分:概述
第2部分:Dmap
第3部分:渲染器
第4部分:剖析
第5部分:脚本
第6部分:访谈(包括与约翰·卡马克的问答)

从笔记到文章...

我注意到我正在使用越来越多的绘图和越来越少的文本来解释代码库。到目前为止,我已经使用gliffy绘制,但这个工具有一些令人沮丧的限制(如缺乏alpha通道)。我正在考虑编写一个专门用于使用SVG和Javascript绘制3D引擎的工具。我想知道这样的事情是否已经存在?无论如何,回到代码...

背景

掌握这样一个突破性引擎的源代码是令人兴奋的。Doom III于2004年发布,为实时引擎设定了新的视觉和音频标准,最为显着的是“统一照明与阴影”。这项技术首次允许艺术家以好莱坞的规模表达自己。即使8年后,在Delta-Labs-4中与HellKnight的第一次遭遇仍然看起来非常棒:

第一次联系

源代码现在通过Github进行分发,这是一件好事,因为来自id Software的FTP服务器几乎总是关闭或重载。

来自TTimo的原始版本与Visual Studio 2010 Professional编译良好。不幸的是Visual Studio 2010“Express”缺少MFC,因此无法使用。这是令人失望的释放,但有些人已经删除了依赖。

Windows 7的 :===========git clone https://github.com/TTimo/doom3.gpl.git


对于代码阅读和探索,我更喜欢在Mac OS X上使用XCode 4.0:SpotLight的搜索速度,变量亮点和“命令点击”达到定义使得体验优于Visual Studio。XCode项目在发布时被破坏,但是很容易解决几个步骤,现在有一个Github存储库由“坏扇区”,在Mac OS X Lion上运行良好。

   MacOS X:=========git克隆https://github.com/badsector/Doom3-for-MacOSX-

注意:安装 Visual Studio 2010生产力电动工具后,Visual Studio 2010中也可以看到“变量hightlights”和“Control-Click”。我不明白为什么这不是香草安装的一部分。

两个代码库现在都处于最佳状态:一次点击可执行文件!

  • 下载代码
  • 击中F8 / Commmand-B。
  • 跑 !

琐事:为了运行游戏,您将需要base包含Doom 3游戏的文件夹。因为我不想浪费时间从Doom 3 CD中提取它们并更新它们:我下载了Steam版本。似乎id软件团队做的一样,因为Visual Studio项目发布仍然包含"+set fs_basepath C:\Program Files (x86)\Steam\steamapps\common\doom 3"在调试设置!

琐事:引擎是用Visual Studio .NET开发的。但代码不具有单行的C#,发布的版本需要Visual Studio 2010 Professional才能编译。

琐事: Id软件团队似乎是Matrix电影系列(黑客帝国)的粉丝:Quake III的工作题目是“Trinity”,Doom III的工作题目是“Neo”。(都出自黑客帝国电影中)

建筑

该解决方案分为反映引擎整体架构的项目:

项目 构建 意见
  视窗 MacO SX  
游戏 gamex86.dll gamex86.so Doom3游戏
游戏d3xp gamex86.dll gamex86.so Doom3 eXPension(Ressurection)游戏
MayaImport MayaImport.dll - 资产创建工具链的一部分:在运行时加载,以打开Maya文件并导入怪物,摄像头路径和地图。
毁灭战士 Doom3.exe Doom3.app Doom 3引擎
所属类别 TypeInfo.exe - 内部RTTI帮助器:生成GameTypeInfo.h:具有每个成员大小的所有Doom3类类型的映射。这允许通过TypeInfo类进行内存调试。
CurlLib CurlLib.lib - HTTP客户端用于下载文件(Staticaly链接到gamex86.dll和doom3.exe)。
伊德利卜 idLib.lib idLib.a id软件库。包括解析器,词法分析器,字典...(Staticaly链接到gamex86.dll和doom3.exe)。

像idTech2的每个引擎一样,我们找到一个封闭的源代码二进制(doom.exe)和一个开放源代码的动态库(gamex86.dll):


自2004年10月以来,大多数代码库已经通过Doom3 SDK访问:只有Doom3可执行源代码失踪。模式能够构建idlib.agamex86.dll但发动机的核心仍然是封闭源。

注意:引擎不使用标准C ++库:所有容器(映射,链接列表...)都被重新实现,但libc被广泛使用。

注意:在游戏模块中,每个类都扩展了idClass。这允许引擎执行内部RTTI,并通过类名实例化类。

琐事:如果你看图纸,你会看到几个基本框架(如Filesystem)在Doom3.exe项目中。这是一个问题,因为gamex86.dll也需要加载资源。这些子系统由doom3.exe中的gamex86.dll动态加载(这是图中箭头实现的)。如果我们用PE Explorer中的DLL我们可以看到,gamex86.dll导出一个方法:GetGameAPI

一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL:交换对象的指针:

当Doom3.exe启动它:exe(这是图中箭头实现的)。如果我们用PE Explorer中的DLL我们可以看到,gamex86.dll导出一个方法: :一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL:交换对象的指针:当Doom3.exe启动它:exe(这是图中箭头实现的)。如果我们用PE Explorer中的DLL我们可以看到,gamex86.dll导出一个方法: :一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL:交换对象的指针:当Doom3.exe启动它:

  • 通过DLL加载其进程内存空间LoadLibrary
  • GetGameAPI使用win32来获取dll中的地址GetProcAddress
  • 打电话GetGameAPI
        gameExport_t * GetGameAPI_t(gameImport_t * import);

在“握手”结束时,Doom3.exe具有指向idGame对象的指针,Game.dll具有指向gameImport_t包含对所有缺少子系统的其他引用的对象的指针,例如idFileSystem

Gamex86对Doom 3可执行对象的看法:

        typedef struct {int                          版本;               // API版本 idSys * sys;                   //非便携式系统服务 idCommon * common;                // common idCmdSystem * cmdSystem               // console command system idCVarSystem * cvarSystem;            //控制台变量系统 idFileSystem * fileSystem;            //文件系统 idNetworkSystem * networkSystem;         //网络系统 idRenderSystem * renderSystem;          // render system idSoundSystem * soundSystem;           // sound system idRenderModelManager * renderModelManager;    //渲染模型管理器 idUserInterfaceManager * uiManager; //用户界面管理器 idDeclManager * declManager; //声明管理器 idAASFileManager * AASFileManager; // AAS文件管理器 idCollisionModelManager * collisionModelManager; //碰撞模型经理 //渲染模型管理器 idUserInterfaceManager * uiManager; //用户界面管理器 idDeclManager * declManager; //声明管理器 idAASFileManager * AASFileManager; // AAS文件管理器 idCollisionModelManager * collisionModelManager; //碰撞模型经理 //渲染模型管理器 idUserInterfaceManager * uiManager;             //用户界面管理器 idDeclManager * declManager;           //声明管理器 idAASFileManager * AASFileManager;        // AAS文件管理器 idCollisionModelManager * collisionModelManager; //碰撞模型经理 // AAS文件管理器 idCollisionModelManager * collisionModelManager; //碰撞模型经理 // AAS文件管理器 idCollisionModelManager * collisionModelManager; //碰撞模型经理} gameImport_t;

游戏/ Modd对象中的Doom 3的视图:

typedef结构 {int             版本;     // API版本 idGame *game;        //界面运行游戏 idGameEdit * gameEdit;    //界面进行游戏内编辑
} gameExport_t;

注意:了解更好的每个子系统的一个很好的资源是Doom3 SDK文档页面(该页面现在需要翻墙人机验证后打开):它似乎是在2004年深入了解代码的人写的(所以可能是开发团队的成员)。

代码

在挖掘之前,一些统计数据来自cloc

        ./cloc-1.56.pl新2180个文本文件。2002独特文件。                                          626个文件被忽略。http://cloc.sourceforge.net v 1.56 T = 19.0 s(77.9 files / s,47576.6 lines / s)-------------------------------------------------- -----------------------------语言文件空白评论代码-------------------------------------------------- -----------------------------C ++ 517 87078 113107 366433C / C ++标头617 29833 27176 111105C 171 11408 15566 53540Bourne Shell 29 5399 6516 39966使43 1196 874 9121m4 10 1079 232 9025HTML 55 391 76 4142Objective C ++ 6 709 656 2606Perl 10 523 411 2380yacc 1 95 97 912Python 10 108 182 895目标C 1 145 20 768DOS批次5 0 0 61Teamcenter def 4 3 0 51Lisp 1 5 20 25awk 1 2 1 17-------------------------------------------------- -----------------------------SUM:1481 137974 164934 601047-------------------------------------------------- -----------------------------

代码行的数量通常不是一个很好的指标,但是在这里,为了评估引擎的理解力度可能非常有帮助。与Quake III相比,601,047行代码使引擎两倍“难”。关于id的历史的几个统计软件引擎#代码行:

#代码线 厄运 idTech1 idTech2 idTech3 idTech4
发动机 39079 143855 135788 239398 601032
工具 341 11155 28140 128417 -
39420 155010 163928 367815 601032


注意:对于工具来说,idTech3的巨大增长来自lcc代码库(用于生成QVM字节码的C编译器)。
注意:由于Doom3被集成到引擎代码库中,所以没有任何工具被归结为Doom3。

从高层来看,这里有几个有趣的事实:

  • 在第一次在软件历史上,代码是C ++而不是C.约翰·卡马克在我们的问答中阐述了这一点。
  • 抽象和多态在代码中使用很多。但是一个好的技巧避免了一些对象的vtable性能。
  • 所有资产都以人类可读的文本形式存储。没有更多的二进制该代码正在广泛使用词法分析器/解析器。约翰·卡马克(John Carmack)在我们的问答中阐述了这一点。
  • 模板用于低级实用程序类(主要是idLib),但从来没有在上层看到,所以他们不会让你的眼睛流血的方式谷歌的V8源代码。
  • 在代码评论方面,它是来自id软件的第二好的代码库,唯一一个更好的是Doom iPhone,可能是因为它比Doom3更新。30%的评论仍然很出色,很少找到一个很好的评论的项目!在代码的某些部分(参见dmap页面)实际上比语句更多的注释。
  • OOP封装使代码清洁,易于阅读。
  • 低级装配优化的时代已经过去了。这里有一些技巧idMath::InvSqrt和空间本地化优化,但大多数代码只是尝试在可用时使用这些工具(GPU着色器,OpenGL VBO,SIMD,Altivec,SMP,L2优化(R_AddModelSurfaces每个模型处理)...) 。

查看由John Carmack定义的idTech4编码标准(镜像)也很有意思(我特别赞赏关于const布局的评论)。

展开循环

这是主要循环展开引擎最重要的部分:

        idCommonLocal commonLocal;                   // OS专用对象  idCommon * common =&commonLocal;         //接口指针(因为Init是依赖于操作系统的,它是一种抽象的方法int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){Sys_SetPhysicalWorkMemory(192 << 20,1024 << 20);   //最小= 201,326,592最大= 1,073,741,824Sys_CreateConsole();//由于引擎是多线程的互斥体在这里初始化:每个“关键”(并发执行)代码的一个互斥体。for(int i = 0; i <MAX_CRITICAL_SECTIONS; i ++){InitializeCriticalSection(&win32.criticalSections [i]);}common-> Init(0,NULL,lpCmdLine);              //评估VRAM有多少(不是通过OpenGL完成但OS调用)Sys_StartAsyncThread(){                           //下一个查找运行是一个单独的线程。而(1){usleep(16666);                         //运行在60Hz common-> Async();                         //做工作 Sys_TriggerEvent(TRIGGER_EVENT_ONE);   //解锁其他线程等待输入 pthread_testcancel();                    //检查主线程是否被取消(在关机时)。}}Sys_ShowConsole而(1){Win_Frame();                                 //显示或隐藏控制台共>框架(){session-> Frame()                          //游戏逻辑{for(int i = 0; i <gameTicsToRun; i ++)RunGameTic(){game-> RunFrame(&cmd);      //从这一点起,执行跳转到GameX86.dll的地址空间。for(ent = activeEntities.Next(); ent!= NULL; ent = ent-> activeNode.Next())ent-> GetPhysics() - > UpdateTime(time);  //让实体思考}}session-> UpdateScreen(false); //正常的,按序屏幕更新{renderSystem-> BeginFrameidGame :: Draw             // Renderer前端。实际上并没有与GPU沟通!renderSystem-> EndFrameR_IssueRenderCommands    //渲染器后端。将GPU优化的命令发布到GPU。}}}}        

有关详细信息,请参阅阅读代码时作为地图使用的完全展开循环。

它是id软件引擎的标准主循环。除了Sys_StartAsyncThread表示Doom3是多线程的。此线程的目标是处理引擎不希望限制帧速率的时间关键功能:

  • 声音混合
  • 用户输入生成。

琐事: idTech4高级对象都是具有虚拟方法的抽象类。这通常会涉及性能问题,因为每个虚拟方法地址在运行时调用之前都必须在vtable中查找。但是有一个“伎俩”来避免这种情况。所有对象都静态实例化:

        idCommonLocal commonLocal;                   //实现 idCommon * common =&commonLocal;         //指针for gamex86.dll

由于在数据段中静态分配的对象具有已知类型,编译器可以commonLocal在调用方法时优化远程执行vtable查找。接口指针在握手期间使用,因此doom3.exe可以交换对象引用,gamex86.dll但在这种情况下,vtable的成本未被优化。

琐事:从id软件中读取大多数引擎,我发现一些方法名称自从doom1引擎以来就没有改变:负责抽取鼠标和操纵杆输入的方法仍然被称为:IN_frame()

渲染

两个重要部分:

  • 由于Doom3使用门户系统,所以预处理工具dmap完全脱离了传统的bsp构建器。我在一个专门的页面上深入审查了它。
  • 运行时渲染器具有非常有趣的体系结构,因为它在前端和后端分为两部分:更多的专用页面。

剖析

我使用Xcode的仪器来检查CPU周期在哪里。结果和分析在这里。

脚本和虚拟机

在每个idTech产品中,VM和脚本语言从以前的版本都完全改变了,他们再次做到了: 细节在这里。

面试

在阅读代码时,几个新奇使我感到困惑,所以我写信给约翰·卡马克,他很高兴回复深入的解释:

  • C ++。
  • 渲染器分为两块。
  • 基于文本的资产。
  • 解释的字节码

我还编辑了关于idTech4的所有视频和新闻采访。这些都在采访页面。

推荐读数

像往常一样你可以享受的书,如果你喜欢的代码:

还有一件事

夏天来了,并不总是很容易集中

...但总的来说,这是一个大部分的阅读。由于idTech5源代码将不会很快被发布(如果有的话),这让我与idTech3(Quake III)尚未被审查。也许如果有足够的人有兴趣,我会写一些关于它的内容。

注释

doom3 源代码评测 1相关推荐

  1. 代码之美——Doom3源代码赏析2

    http://www.csdn.net/article/2013-01-17/2813778-the-beauty-of-doom3-source-code/2 摘要:Dyad作者.资深C++工程师S ...

  2. QUAKE 3源代码评测:架构

    QUAKE 3源代码评测:架构(第1部分,共5部分)>> 由于我在下一个合同前一个星期,我决定完成我的"循环ID".后末日,末日iPhone,Quake1,Quake2 ...

  3. 转:代码之美——Doom3源代码赏析

    背景介绍: Doom3是id Software于2004年开发的第一人称射击游戏,目前以GPL v3协议开源.其采用游戏引擎的是id Tech 4,由id Software创始人.首席程序员John ...

  4. 代码之美——Doom3源代码赏析

    摘要:Dyad作者.资深C++工程师Shawn McGrathz在空闲时翻看了Doom3的源代码,发出了这样的惊叹:"这是我见过的最整洁.最优美的代码!""Doom 3的 ...

  5. 代码之美——Doom3源代码赏析1

    http://www.csdn.net/article/2013-01-17/2813778-the-beauty-of-doom3-source-code/1 摘要:Dyad作者.资深C++工程师S ...

  6. 在线评测系统设计与实现

    资料说明 南 阳 理 工 学 院 本 科 毕 业 设 计(论文) 在线评测系统设计与实现 Design and Implementation of Online Judge System Nanyan ...

  7. 基于SSH的可扩展的程序代码源码Web在线评测系统

    文档+任务书+开题报告+可行性分析报告+项目源码 摘 要 程序语言课程是计算机相关专业的核心教学内容之一,要提高程序语言设计能力必须通过大量的实践练习与交流.在传统的学习过程中,往往通过人工方式对程序 ...

  8. 编好c语言网上自动评测,C语言程序自动评测系统的设计与实现

    摘要: 随着计算机技术的发展和提高,计算机辅助评价(CAA)已成为当前计算机教育应用的热点研究问题之一.已有的研究成果已能很好的解决客观题测评问题,而主观题的评测问题则仍处于发展阶段.C语言程序设计课 ...

  9. 不可不看 真正专业显卡技术分析评测

    近年来图形卡产品有了爆炸式的增长,专业图形卡产品和娱乐图形卡产品的界限越来越模糊.许多DIYer通过RivaTuner等工具轻易的修改Geforce为Quadro.修改Radeon为FireGL.但是 ...

最新文章

  1. 全面解析微服务系统监控分层,啃透服务治理核心!
  2. 斯坦福:「目标检测」深度学习全面指南
  3. WCF版的PetShop之一:PetShop简介[提供源代码下载]
  4. MFC文件打开和保存
  5. java读取frp_【原创】FRP初探(函数式编程部分)
  6. 【直播回看】「EDGE X Kubernetes · 云原生在边缘的实践与应用」
  7. 论文中常用的几个Word2010技巧
  8. SVN提交,提示“remains in conflict”错误
  9. linux下永久添加静态路由
  10. java 分布式事务_Java核心知识 Spring原理十五 JPA 原理
  11. MaxCompute Hash Clustering介绍
  12. mac mongodb可视化工具_MongoDB从立地到成佛(介绍、安装、增删改查)
  13. 解线性方程组的迭代法(高斯-塞德尔迭代法)
  14. idea 2019最新版无法打开报错问题,Error occurred during initialization of VM Initial heap size set to a larger va
  15. 服务器系统日志保留时间设置,服务器行为操作日志
  16. python爬取网易云音乐评论分析_Python爬取网易云音乐评论(附加密算法)
  17. SpringCloud Gateway API接口安全设计(加密 、签名)
  18. 信奥中的数学学习资料汇总(2022.10.31)
  19. 没有找到libgcc_s_sjlj-1.dll
  20. 计算机在黑板前面英语怎么写,计算机多媒体在英语教学中的运用

热门文章

  1. C#使用随机数模拟器来模拟世界杯排名(三)
  2. jvm 内存溢出的多种原因及优化方法
  3. USB转串口芯片 FT232RL/CH9101/PL2303/CY7C65213同类型芯片参数对比
  4. 今年元宵月52年来最圆最大
  5. centos7源代码编译安装heartbeat
  6. 一个SAPer的网络日志-连载二-说说MM的倒爷们
  7. IT门户的电子产品报价不再准确
  8. 判断用户输入的是否是正确电话号码
  9. java利用pol导出excel
  10. Xftp 传文件到虚拟机一直显示状态错误,传不进去