QUAKE 3源代码评测:架构

📅 2026/7/17 22:54:44 👁️ 阅读次数 📝 编程学习
QUAKE 3源代码评测:架构

QUAKE 3源代码评测:架构(第1部分,共5部分)>>

由于我在下一个合同(翻译可能有误)前一个星期,我决定完成我的“循环ID”。

Doom,DoomiPhone,Quake1,Quake2中,德军iPhone和毁灭战士

我决定读最后一个代码库我还不审查:

idTech3的3D引擎,Quake III,quakelive

引擎主要是idTech2的演变,但有一些有趣的新奇。重点可归纳如下:

  • 第2部分:新的双核渲染器与基于物料的着色器(构建在OpenGL固定管道上)。
  • 第3部分:基于快照的新的网络模型。
  • 第4部分:新型虚拟机在引擎中扮演重要角色,
  • 将Quake1 可移植性/安全性与 Quake2速度 (此处翻译可能有误……)相结合。
  • 第5部分:机器人的新人工智能。

我特别印象深刻:

  • 虚拟机系统 和 相关的工具链 总共占发布的 代码 的 30%。
  • 在这种观点下,idTech3是一个小型操作系统,可以提供三个进程的系统调用。
  • 基于快照和内存自省的优雅网络系统。

像往常一样,我写了许多笔记,

我已经清理并合成了图纸。

我希望能节省时间给一些人,

但也鼓励别人的代码,成为更好的工程师。

第一次联系

由于最近ftp.idsoftware.com最近退役,

代码可以在id的GitHub帐户中找到 :

git clone https://github.com/id-Software/Quake-III-Arena.git

当谈到一个巨大的 代码库,

我更喜欢使用 XCode:SpotLight速度,

Command-click 查找 定义和字符串 高亮使得 该工具 比 Visual Studio 更强大。

但是打开Quake III项目表明,

代码腐烂 并不总是 关于代码,

还涉及到 这些工具:

XCode 4.0无法 打开 Quake III XCode 2.0项目。

最后我在 Windows 8 上 使用 Visual Studio 2010 Professional:

安装Visual Studio 2010生产力电动工具后 ,工具集实际上很愉快。

第一个引人注目的是Visual Studio工作区不是由一个项目组成的,

而是八个。

如果构建是DEBUG或RELEASE(特别gamecgameq3_ui虚拟机项目),

则不是全部使用它们。一些项目永远不会使用(splinesui)。

一个表格最好总结什么项目对哪个模块做出贡献:

项目类型DEBUG构建RELEASE构建注释
botlib静态库botlib.libbotlib.libAI
在CGame动态的Libary / Bytecodecgamex86.dll-
game动态的Libary / Bytecodeqagamex86.dll-
q3_ui动态的Libary / Bytecodeuix86.dll-
QUAKE3可执行文件quake3.exe

quake3.exe

render静态库renderer.librenderer.lib

基于OpenGL的

splines

样条

曲线

静态库Splines.libSplines.lib使用NOWHERE!
UI动态的Libary / Bytecodeuix86_new.dll-用于Quake III Arena。

琐事:idTech3的工作题目是“三位一体”。

由于idTech4被称为“Neo”,

我认为它是从“Matrix”专营权...(电影中 取得 灵感 )

但是id软件在接受firingsquad.com的采访时指出,它以“达拉斯的三一河”命名:

约翰:就研究而言,我有几件引擎的事情正在进行中。FS:那是三位一体呢?我认为“三位一体”有点混乱。约翰:我从来没有真的确定这是如何像所有人…………(此处有待进一步考察原文和重新翻译), 何时我开始使用新的渲染技术和一切, 每个人都称之为“下一个引擎” 不用太在意 。迈克尔·阿布拉斯(Michael Abrash)建议, 我们只是采取英特尔在一条河附近命名您的下一个项目 您。 我们在达拉斯拥有三一河(地名),所以就像“三位一体引擎”一样,下一步。约翰:就研究而言,我有几件引擎的事情正在进行中。FS:那是三位一体呢?我认为“三位一体”有点混乱。约翰:我从来没有真的确定这是如何像所有人一样混乱。震后,(此处翻译可能有误……) 何时 我开始使用新的渲染技术和一切,每个人都称之为“下一个引擎” 不用太在意。迈克尔·阿布拉斯(Michael Abrash)建议, 我们只是采取英特尔在一条河附近命名您的下一个项目 您。我们在达拉斯拥有三一河,所以就像“三位一体引擎”一样,下一步。

编辑(2012年7月7日):Jeremiah Sypult在发表本文后联系了我:

他用“XCode 4.0”项目为“Quake3”Mac OS X构建“不动”。(此处 可能有误……)

我已经进一步修复了,

你可以在github上得到它。

您将需要Quake III Arenabaseq3(而不是演示版),

并确保 使用参数"+set vm_game 0 +set vm_cgame 0 +set vm_ui 0"以使用dylib虚拟机。

打开/code/quake3.xcworkspace它建立在一个点击!

架构

了解架构的一个方便的方法是首先将软件视为 接收输入(左上箭头)

和生成输出(底部箭头)的 黑盒子:

然后查看输入如何以白盒方式与6个模块流向输出

quake3.exerenderer.libbot.libgamecgameq3_ui)的交互如下:

两个重要的事情要理解设计:

    1. 每个单个输入(键盘,win32消息,鼠标,UDP套接字)
    2. 都转换成一个event_t集中的事件队列(sysEvent_t eventQue[256])。
    3. 这允许其他事情记录(记录)每个输入,
    4. 以重新创建错误。

      1998年10月14日在约翰·卡马克的“计划”中
    5. 详细讨论了这一设计决策。
  1. 客户端和服务器的显式拆分(我在John Carmack的Q&A中概述了):
    Fabien Sanglard:您认为如何总结idTech3的主要创新之外: - 机器人IA - 虚拟机:结合QuakeC可移植性和Quake2 dll速度。 - SMP&着色器渲染器。 - 新的网络代码。约翰·卡马克:明确将网络划分为客户端演示端和服务器逻辑端, 这是真的对要做的事。 我们退出了在Doom3和大部分 Rage, 但我们正在迁移回去。 所有的Tech3 许可证持有者被迫做更多的工作, 以分析 架构实现单人效应, 但事实证明 执法纪律确实有一个有价值的回报。Fabien Sanglard:您认为如何总结idTech3的主要创新之外: - 机器人IA - 虚拟机:结合QuakeC可移植性和Quake2 dll速度。 - SMP&着色器渲染器。 - 新的网络代码。约翰·卡马克:明确将网络划分为客户端演示端和服务器逻辑端,这是真的对 要做的事。我们退出了在末日3和大部分愤怒,但我们正在迁移回去。所有的Tech3 许可证持有者被迫做更多的工作,以分裂架构实现单人效应,但事实证明 执法纪律确实有一个有价值的回报。
    • 服务器端负责维护游戏状态,确定客户需要什么,
    • 并通过网络传播。
    • 它是静态联系的,bot.lib因为它是一个单独的项目,
    • 因为它的《doom启示录 》第275页提到的混乱的发展历史:

      更糟糕的是,游戏的一个基本要素 - 漫游器 - 失踪了。

    • bot 机器人 是由电脑控制的字符。

    • 一个好的机器人会与动作和 模型 相融合

      像机器人的额外的场景,以及与玩家的互动。

    • 对于Quake III,终结 只有游戏,

    • 机器人是单人游戏动作所必需的。

    • 它们是隐含的复杂因为它们 不得不像“游戏中玩家”一样行事。

    • 卡马克决定第一次将创建这些机器人的工作委托给另一个机器人

      程序员在公司。但他没有跟进。卡马克再次错了

      每个人都像自己一样自我激励和擅长。他错了

      当Graeme努力控制工作时,发现机器人完全无效。

      他们根本不喜欢人类。他们的行为基本上就像机器人一样。工作人员开始恐慌。

      到1999年3月,他们有理由害怕。

      [..]

      最后,机器人已经被种植到荷兰知名的模具制造商,

    • 英国人带来了这个制造商 他们生活

    • (Fab的注释:这是Mr.Elusive:Jan Paul van Waveren)。

    • 客户端负责预测实体在哪里(延迟补偿)并呈现视图。
    • 它与renderer项目静态链接:一个单独的项目,
    • 允许Direct3D甚至软件渲染器被非常容易地插入。

代码

从代码的角度来看,这是一个部分展开的循环,用于说明客户端和服务器的事件生产和消耗:

int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { Com_Init NET_Init 而(1) { //通用代码 IN_Frame() //将Win32操纵杆和鼠标输入作为event_t添加到统一的事件队列中。 { IN_JoyMove IN_ActivateMouse IN_MouseMove } Com_Frame { //通用代码 Com_EventLoop //将win32消息,UDP套接字和控制台命令的泵送到队列(sysEvent_t eventQue [256]) Cbuf_Execute //服务器代码 SV_Frame { SV_BotFrame //在bot.lib中跳转 VM_Call(gvm,GAME_RUN_FRAME,svs.time) //在游戏虚拟机中跳转,执行游戏逻辑 SV_CheckTimeouts SV_SendClientMessages //向连接的客户端发送快照或增量快照 } //通用代码 Com_EventLoop Cbuf_Execute //客户端代码 CL_Frame { CL_SendCmd //泵送事件队列并发送命令到服务器。 SCR_UpdateScreen VM_Call(cgvm,CG_DRAW_ACTIVE_FRAME); //发送消息到客户端虚拟机(做预测)。 要么 VM_Call(uivm,UI_DRAW_CONNECT_SCREEN); //如果菜单可见,则会将消息发送到UI虚拟机。 S_Update //更新声音缓冲区 } } } }

这是一个完全展开的循环,我在挖掘源代码时使用了一个地图。

一个有趣的事情要注意到,这完全说明了虚拟机的重要性:

没有任何地方可以看到RE_RenderScene:执行剔除和发出OpenGL命令的功能。

相反,发生的是:

  1. Quake3.exe向 客户端VM 发送 消息:CG_DRAW_ACTIVE_FRAME哪个表示需要刷新。
  1. 虚拟机执行一些 实体剔除 和 预测,
  1. 然后通过Quake3系统调用(CG_R_RENDERSCENE)调用OpenGL再现。
  1. Quake3.exe接收系统调用,实际调用RE_RenderScene
OpenGL Quake3.exe客户端虚拟机 -------- ---------- ---------------------- | | | | | | | VM_Call(CG_DRAW_ACTIVE_FRAME)-----------------> CG_DrawActiveFrame | | CG_DrawActive | | trap_R_RenderScene | | 系统调用(CG_R_RENDERSCENE,fd) | RE_RenderScene <-------------------------------------- | | | | | <---------------------- | | | | |

统计

这里有一些来自cloc的统计资料:

-------------------------------------------------- --------------------------------------------- 文件空白评论代码 -------------------------------------------------- --------------------------------------------- cloc-1.56.exe代码共享559 48630 73501 233952 cloc-1.56.exe lcc 116 2270 1513 28067 cloc-1.56.exe q3asm q3map 44 4987 5565 22877 cloc-1.56.exe q3radiant 206 11870 13113 54922 -------------------------------------------------- --------------------------------------------- 共计919 68293 95509 341994 -------------------------------------------------- ---------------------------------------------

在 饼图上,我们可以生动地看到这个比例是多么 的不寻常,

因为30%的代码库专门用于工具:


部分原因是 因为idtech3具有ANSI C编译器:开源Little C Compiler(LCC)用于为虚拟机生成字节码。

内存分配

两个定制分配器在这里工作:

  • 区域分配器:负责运行时,小型和短期内存分配。
  • Hunk分配器:负责从pak文件(几何,地图,纹理,动画)的级别负载,
  • 大型和长期分配。

更美好的明天

有了这个代码审查,似乎我跑出了伟大的3D引擎源代码阅读。

但是CG世界正在走很多伟大的事情。

我特别期待着Occulus Rift VR工具包:

构建,编码和 理解测试台将会很有趣。它应该在7月下旬直到那时止:快乐的技巧 !