doom3 commentary

55
Doom3 コココココ ( コココココココココココココ RTTI) @DADA246

Upload: dada246

Post on 30-Jul-2015

2.810 views

Category:

Technology


0 download

TRANSCRIPT

Doom3 コード解説( イベントシステムとカスタム

RTTI)@DADA246

自己紹介• 名前:多田 航 @DADA246

• ゲームプログラマやってます

• 得意分野 C++,C#,GPU,javascript,PHP• 描画関係とか CI とか

自己紹介• 海外ゲーム歴PC9801 版 Test Drive が最初?その後 Doom 、 Diablo 、 StarCraft 、 NetStorm から始まり、今ではSteam 、 Origin 、 iPhone で海外ゲームを遊んでいます

秋葉原で輸入ゲームも良く買ってます

アジェンダ• Doom3 ゲーム概要• Doom3 コード概要• idLib• エンティティ• カスタム RTTI• イベントシステム• まとめ

Doom3 とは?• id software が開発した FPS• 2004/8 発売• マルチプラットフォーム

(Windows 、 Mac 、 Linux)• メインプログラマは John Carmack

• 2011/10 にソースコードが公開されたhttps://github.com/TTimo/doom3.gpl

Doom3 の特徴• 狭い通路• 懐中電灯と武器を切り替えるスタイル• ステンシルシャドウ• いくつかのカットシーン• スクリプトドリブンのレベルデザイン• コンソールウィンドウによるパラメータ

調整→id の伝統

John Carmack

• id Software 設立者の一人で、 FPS の生みの親

• wolfenstein 、 Doom 、 Quake、 Rage など数々のゲームを開発

• id Software のゲームはほとんど John Carmack が一人で書いていると言われている

Doom3 のコードを読んでみる• Visual Studio で開く→neo\doom.sln

• Visual Studio Express でビルドするためにはコードからATL を外す必要がある

→ チャレンジしてみましたがビルド出来ませんでした…

• ソースコードは GPL でもテクスチャなどのリソースは公開されていません。 Doom3 を買う必要があります

コーディングスタイル• C++• stl 、 boost は不使用• 例外、標準 RTTI は不使用• シンプルなテンプレート

→2004 年のコンパイラ事情や、 John Carmack が書いたコードということで、移植性と処理速度を重視していると思われる ( なにしろ Doom を書いたプログラマーであり…そもそも Quake3 までは C 言語だった )

コーディングスタイル• C++ の基本を押さえた書き方→const の徹底→ 最低限の virtual→ プリコンパイル済みヘッダー→ クラスの前方宣言

• レガシーな書き方も残っている→ 変数宣言を関数の先頭で行っている→ 名前空間を使っていない

全体構成• Game→ 機種共通コード。別ver として Game-d3xp がある

• DoomDll→ 機種依存コード。exe が出力されるのはコレ

idLib

• ゲームタイトルに依存しない処理を集めたライブラリ

• エンディアンスワップ• 色定義• タイマー• Key/value dictionary• ローカライズ用辞書• 汎用ファイルフォーマット

idLib

• ハッシュ (CRC32,MD4,MD5)• テキスト (CmdArgs,Base64)• コンテナ (2 分探索 ,btree, ハッシュテーブ

ル , リスト , リンクリスト , キュー , スタック , 文字列リスト , Vector Set …)

→STL の代わり

数学• ベクトル• 行列• 角度• クォオータニオン• 複素数• 乱数 ( 線形合同法 )• Lcp(Box Constrained Mixed Linear Complementarity

Problem solver)• Polynormal(Polynomial of arbitrary degree with real

coefficients)

ジオメトリ• DrawVert• JointTransform• Surface• Surface_Patch(Bezier patch surface)• Surface_Polytope( 多面体 )• Surface_SweptSpline• TraceModel( コリジョン用モデル )• Winding( 任意凸形状 )• Winding2D

ODE( 常微分方程式 )

• Euler 法• 4次のルンゲクッタ法

衝突形状• AABB,OBB, 視錐台 ,球• operator オーバーロードを活用したシンプ

ルなコード

プリュッカー座標系• a way to assign six homogenous coordinates

to each line in projective 3-space(wikipedia)らしいですが、詳細は理解していません。

• 衝突判定に 6次元座標を使う?

SIMD

• Simd_Generic で C++ の汎用実装をしつつ、一部関数を SIMD に置き換えている

• 以下の実装がある• 3DNow!• AltiVec• MMX• SSE• SSE2• SSE3(2004 年 Doom3 発売年 )

SIMD

• 処理負荷を計測する「テスト」が関数ごと用意されている

• 四則演算の他に TransformVerts などの描画演算や、 UpSamplePCMTo44kHz などのサウンド処理が実装されている

アロケータ• MemoryBlock• DynamicAllocator• ページアロケータ

→大きめのメモリ確保はページ単位小さめのメモリ確保はメモリプール(MemoryBlock) で行う

TypeInfo プロジェクト• Type Info Generator→NoGameTypeInfo.h を生成する

CurlLib

• Daniel Stenberg の cURL( クライアントサイド URL転送ライブラリ )

• http://curl.haxx.se

• ファイルシステムで使われている

アジェンダ• Doom3 ゲーム概要• Doom3 コード概要• idLib• エンティティ• カスタム RTTI• イベントシステム• まとめ

エンティティ• ゲームオブジェクトはエンティティと呼ばれ、以下の種類がある

• idAnimatedEntity( アニメーションするもの。 Actor や Player)• idTestModel• idEntityFx• idAFAttachment(Articulated figure :多関節形状 )• idAFEntity_Generic• idCursor3D• idWeapon( 武器 )• idLight(光源 )• idBeam• idFuncEmitter• …

エンティティの例• idWeapon( 武器制御 )

• 武器の On/Off や、サウンドなどの他のモジュールの処理を行っている

idTypeInfo

• カスタム RTTI• idClass で static な情報を扱うために存在する

• 他のクラスからは直接触られず、 idClass経由で利用される

idTypeInfo主なフィールド• クラス名→ 文字列版と int 版が用意されている→int 版は通信対戦時のパケットに使う

• 継承元のクラス名• イベント ( メソッドを関数ポインタにしたも

の。後述 )• セーブ、ロード時に使う関数ポインタ

idTypeInfo の使い道• クラス名の管理→ クラス名からインスタンスを生成する→ デバッグ表示、エラー表示にクラス名を入れる

• 他のクラスと基底クラスが同じかどうか判別

• イベントの管理

idClass

• idTypeInfo を static で所持している• イベントを実行する• セーブ、ロードもある

idClass主なメソッド• CreateInstance• GetClassname• ListClasses_f→ “Classname”, “Superclass”, “Type”, “Subclasses” の表示

• Spawn→ エンティティ出現時に呼ばれる

idClass イベント関連• PostEventMS( const idEventDef *ev, int time )• PostEventSec( const idEventDef *ev, float time )• ProcessEvent( const idEventDef *ev )

→各種イベント ( 関数ポインタ ) の実行。後述

idClass static フィールド• static int idClass::memused→ クラスインスタンスの総メモリ使用量

• static int idClass::numobjects→ クラスインスタンスの総数

フィールド初期化忘れ対策• idClass::CreateInstance→new するときにメモリ領域に 0xcdcdcdcd を書いておく

→ コンストラクタが走った後、メモリ領域に0xcdcdcdcd があるかどうかを調べて、フィールドの初期化忘れを見つける

Debug ビルドでのみ上記チェックを行う

idEntity• 様々な処理が集まっている

• thinking(物理更新や Update 処理など )• visuals( 描画処理 )• animation• sound• entity binding( エンティティの親子関係 )• physics• damage( 体力を減らしたり )• scripting( スクリプトの処理、シグナル管理 )• gui(GUI に命令を出す )• targets( 別のエンティティのシグナルを送る )

idAnimatedEntity

• idEntity にアニメーション (idAnimator) を加えたもの

• idAnimator→ 複数チャンネルのモーションブレンドや、親子構造が書いてあるが、詳細は割愛

おさらい• idWeapon

他のエンティティ• idLight(光源制御クラス )• 光源の方向や色を保持している• On/Off やフェードも出来る

• クラス階層がシンプル

エンティティの一括管理• エンティティは idGameLocal で一括管理さ

れている• idGameLocal では全エンティティを所持す

る他、エンティティの作成、削除、検索ができる

idGameLocal• 様々なモジュールの集合クラス

• Entity( 全エンティティの管理 )• Random• Program( スクリプト )• Clipping• Physics• PVS(potential visible set)• MultiPlayerGame• SmokeParticles• カメラ• ゲームの種類などの汎用情報• …

idGameLocal

• 様々なメソッドを持つ

• Entity の出現、削除、検索• ネットワーク対戦情報• セーブ、ロード• ユーザー情報• Draw• ゲームのリセット• Printf• マップのロード• AAS(area system)

エンティティの検索• 名前で検索

• Key Value Dictionary で検索

const char * name;idEntity* ent = gameLocal.FindEntity( name );

const char * key;gameLocal.GetTargets(Key Value Dictionary, Entity, key );

エンティティの検索• クリッピング結果の取得

trace_t tr;// トレース結果用変数gameLocal.clip.TracePoint( tr, 線分の開始地点 , 線分の終了地点 , …);

idEntity* ent = gameLocal.GetTraceEntity( tr );// エンティティの取得

ent->Signal( SIG_TOUCH );// シグナルの発行ent->ProcessEvent( &EV_Touch, …);// イベントの実行

エンティティ生成• idTypeInfo で型指定してエンティティを生

成できる

worldModel = static_cast< idAnimatedEntity * > ( gameLocal.SpawnEntityType( idAnimatedEntity::Type, NULL ) );

アジェンダ• Doom3 ゲーム概要• Doom3 コード概要• idLib• エンティティ• カスタム RTTI• イベントシステム• まとめ

イベントシステム• C++ の関数をスクリプトから呼ぶためのも

の• idEvent と idEventDef で構成されている

イベントを使った処理• idWeapon で直接関数を呼ばずにイベント(idClass::ProcessEvent) を経由している

イベントの登録• 各種エンティティの先頭で idEventDef を宣

• その後マクロで関数をイベントに登録する

const idEventDef EV_Weapon_Next( "nextWeapon" ); …

CLASS_DECLARATION( idAnimatedEntity, idWeapon )

EVENT( EV_Weapon_Next,idWeapon::Event_Next )

END_CLASS

イベントの呼び出し• idClass::ProcessEvent を呼ぶと、イベント登録された関数が呼ばれる

idEntity *other;other->ProcessEvent( &EV_Touch, this, &collision );

スクリプト• イベントはスクリプトクラスでも使われて

いる• Script_Compiler• Script_Interpreter• Script_Program• Script_Thread

スクリプトからのイベント呼び出し

• スクリプトから idInterpreter::CallEvent でイベントを呼べる

• idWeapon::Event_Clear といったメソッドを直接呼び出さないでイベントを経由しているのはスクリプトのため?

まとめ• Doom3 を読んでみました• 海外ゲームの基礎システムに興味を持って頂ければ幸いです

解説していないコード• スクリプトコンパイラ• ファイルシステム• 物理• アニメーション• Dedicated Server• 描画 (renderEntity,qgl)• …

Question?

ご清聴ありがとうございました