●はじめに  モデリングソフトやゲームの画面はどうやって表示されているのでしょうか?  サンプルプログラムを読みこなすのに必要なCGの知識を身に付けるのは重要です。  「何をしているか」(プログラムの流れ)を知って、「何をしたらいいか」を知りましょう!   ⇒ フレームワーク(サンプル、雛型)- アーキテクチャ、API  DirectXの場合、アプリケーションの処理の流れは次のようになっている。   (1)アプリケーション・ウインドウの作成   (2)Direct3Dの初期化   (3)デバイスの作成と設定   (4)リソースの作成   (5)メッセージ・ループの処理    (5-1)フレームの描画開始    (5-2)フレームの描画    (5-3)フレームの描画終了と表示   (6)取得したリソースやDirect3Dの開放  以下に、プログラムの中心となる(5)の部分の処理を説明する。 ●フレームアニメーションの実現方式  一定時間(1/60秒程度)ごとに行う。 シーンの描画、レンダリングループ、ゲームループと言う。  次の2つの画面表示処理を主に行う。  @フレーム描画    1フレーム分の静止画像を作成して、ディスプレイ画面へ転送する。     スクリーン座標→物理画面座標   ■2Dの場合    ・画像の切り出し - スプライト処理    ※擬似3D      擬似3D座標→スクリーン座標  ⇒正面、平面、見下ろし(正面、左斜め)   ■3Dの場合    ・3D→2D変換(透視投影) - レンダリング      ローカル座標→ワールド座標→カメラ座標→スクリーン座標      (モデル座標)(仮想空間)       (投影面)      Zバッファ  Aアニメーション    パーツ単位に「配置の要素」を時間(タイムライン)で管理する。    これを元に現在時刻でのフレームを算出して、連続した「配置」を行う。         キーフレーム法  ⇒線形補間   ■2Dの場合     スクリーン座標を算出する     ・パターン(画像データ)の選択     ・バウンディングボックスの位置確定  ⇒直線(上下左右、斜め)、円、放物線など   ■3Dの場合     ワールド座標を算出する     ・ポーズ(平行/回転/拡大・縮小、材質)      (1)単独      (2)従属 - 関節(剛体、ボーンとスキン)     ・親ユニットの位置確定  ⇒直線、円、放物線など ●移動処理の実現方式  現在時刻でのバウンディングボックスの位置を算出する。アニメーション処理と連携する。  @移動の表現    デカルト座標(直交座標)と極座標 - 速度成分と変位(向きと大きさ)  A当り判定 - バウンディングボックスの重なり  ⇒図形の方程式   ■2Dの場合     矩形、円   ■3Dの場合     直方体、球 ●高校数学 ・行列(マトリックス) ・ベクトル ・三角比、三角関数 ・座標、図形の方程式 ------------------------- 補足説明 ------------------------- アニメーションの原理  ぱらぱら漫画、映画のフィルム、セル画アニメーション、映像データ(avi,mpeg)、GIFアニメーション フレーム  ぱらぱら漫画の1枚が1フレームと考えればよい。   フレームレート  単位時間あたりのフレーム更新回数。 単位は、fps(frame per second)。  テレビは30fps、映画は24fps、8fps程度あれば動いて見える。 フリップ  画面のちらつきを抑えるしくみ。  一画面分を作成した後(バックバッファ、バック・サーフェス)、ディスプレイ(フロントバッファ、プライマリ・サーフェス)にコピーして更新する。 スプライト処理(Sprite)  描画の順番を考慮することで、「奥行き」の位置関係にあるものを重ね合わせることができる。  最近は、3D環境上で2D描画を行う。  ⇒ ビルボード(平板+テクスチャ) 擬似3D  マップ/フィールド座標、仮想スクリーン座標、論理座標 カリング、クリッピング  描画範囲 - ウインドウ(表示対象の範囲) → ビューポート(ディスプレイ上での表示する位置)        視錐台              ビュー(ビューボリューム) 3D空間の構成要素  ┌オブジェクト(物体)  ├ライト(光源) - 環境光、平行光源    ⇒ シーン  └カメラ(視点) 座標系の種類  ┌右手系 - OpenGL  └左手系 - DirectX  X軸…親指、Y軸…人差し指、Z軸…中指、指のさす方向が正(プラス)。   右手系  Y       左手系  Y Z        │            │/        ・─X          ・─X       /      Z    X軸…右方向、Y軸…高さ、Z軸…奥行き。(XZ平面は床) レンダリング・パイプライン  ジオメトリ処理+ライティング処理+ラスタライズ処理+エフェクト処理   ⇒ ビデオカードのGPUに搭載  (   頂点シェーダ   )            (ピクセルシェーダ) GPU  GeForce(nVIDIA)  RADEON(ATI) ジオメトリ処理(幾何計算)  ワールド・トランスフォーム(絶対座標変換) …ローカル座標→ワールド座標  ビュー・トランスフォーム(視点変換) …ワールド座標→ビュー座標(カメラ座標)  プロジェクション・トランスフォーム(射影変換) ┐ …ビュー座標(カメラ座標)→スクリーン座標  スクリーン・トランスフォーム(ビューポート変換)┘  ローカル座標 - 各モデル単位に各モデルを作成する座標(空間)  ワールド座標 - オブジェクト、ライト、カメラを配置するひとつだけ設けた、「シーン」を表現する座標(空間)  ビュー座標(カメラ座標) - カメラを基準にした座標(空間)  スクリーン座標 - 画像を表示する座標(平面)  ローカル座標の点(Lx,Ly,Lz)は、一連の行列の計算によって、スクリーン座標の点(Sx,Sy,Sz)に変換される。  [Sx Sy Sz 1]=[Lx Ly Lz 1] ┌ワールド┐┌ビュー ┐┌プロジェクション┐┌スクリーン  ┐ (DirectX形式)                └トランスフォーム┘└トランスフォーム┘└トランスフォーム ┘└トランスフォーム┘ 3Dライブラリ、3Dエンジン、3DCG APIの種類  DirectX(DirectX Graphics) - マイクロソフト  OpenGL - シリコン・グラフィックス  RenderWare - クライテリオン・ソフトウェア  など Zバッファ  スクリーンの各画素のZ値(深度)を算出して、陰面消去を行う。  Z値が小さければ、手前にあるので描画する。 シェーディング  ┌フラットシェーディング  └グーローシェーディング 斉次座標(同次座標)  複数の移動、回転などの組合せの変換は、行列の積による一本化が可能となる。  2次元のXY直交座標系(デカルト座標)の場合、各変換は次のように記述できる。   拡大・縮小 x'=Sx・x  回転 x'=x・cosθ-y・sinθ  平行移動 x'=x+Tx            y'=Sy・y     y'=x・sinθ+y・cosθ       y'=y+Ty  これを2×2の行列で表すと、(DirectX形式)   [x' y']=[x y]┌ Sx 0 ┐          └ 0 Sy┘   [x' y']=[x y]┌ cosθ sinθ ┐          └ -sinθ cosθ ┘   [x' y']=[x y]+[Tx Ty]  平行移動は和、拡大・縮小と回転は積で表される。  ここで平面の点[x y]は、   空間上の点[x y w]と原点を通る直線がw平面に交差する点[x/w y/w](射影となる)  と拡張すると、  w=1の場合、同座標で各変換を3×3の行列で表すと、   拡大・縮小(scale)   [x' y' 1]=[x y 1]┌ Sx 0 0 ┐ (原点を中心)            │ 0 Sy 0 │            └ 0 0 1 ┘   回転(rotation)   [x' y' 1]=[x y 1]┌ cosθ sinθ 0 ┐ (原点を中心に反時計まわり)            │ -sinθ cosθ 0 │ (※3次元的にはZ軸を中心と解釈できる)            └ 0 0 1 ┘   平行移動(translation)   [x' y' 1]=[x y 1]┌ 1 0 0 ┐            │ 0 1 0 │            └ Tx Ty 1 ┘ 3次元の変換行列(アフィン変換)(DirectX形式)  拡大・縮小(scale)   [x' y' z' 1]=[x y z 1]┌ Sx 0 0 0 ┐ (原点を中心)               │ 0 Sy 0 0 │               │ 0 0 Sz 0 │               └ 0 0 0 1 ┘  回転(rotation)   X軸まわり   [x' y' z' 1]=[x y z 1]┌ 1 0 0 0 ┐ (Y軸からZ軸へ)               │ 0 cosθ sinθ 0 │               │ 0 -sinθ cosθ 0 │               └ 0 0 0 1 ┘   Y軸まわり   [x' y' z' 1]=[x y z 1]┌ cosθ 0 -sinθ 0 ┐ (Z軸からX軸へ)               │ 0 1 0 0 │               │ sinθ 0 cosθ 0 │               └ 0 0 0 1 ┘   Z軸まわり   [x' y' z' 1]=[x y z 1]┌ cosθ sinθ 0 0 ┐ (X軸からY軸へ)               │ -sinθ cosθ 0 0 │               │ 0 0 1 0 │               └ 0 0 0 1 ┘  平行移動(translation)   [x' y' z' 1]=[x y z 1]┌ 1 0 0 0 ┐               │ 0 1 0 0 │               │ 0 0 1 0 │               └ Tx Ty Tz 1 ┘ 行列の計算  正方行列、和、差、積、逆行列 行列の計算とその性質  交換法則 AB≠BA   ※座標変換、配置を指定するとき、順番が大事!  結合法則 ABC=(AB)C=A(BC)   ※ワールド * ( ビュー * ( プロジェクション * スクリーン ) )のように半固定部分を予め計算しておける  分配法則 (A+B)C=AC+BC 行列の表記  頂点の座標を行ベクトル、列ベクトルのどちらで扱うか?  転置行列   たとえば、平行移動(translation)の場合、   DirectX形式   [x' y' 1] = [x y 1] ┌ 1 0 0 ┐                      │ 0 1 0 │                      └ Tx Ty 1 ┘   OpenGL形式   ┌ x' ┐=┌ 1 0 Tx ┐┌ X ┐           │ y' │ │ 0 1 Ty ││ Y │           └ 1 ┘ └ 0 0 1 ┘└ 1 ┘  ※数学の教科書はこちら  また、(AB)t=BtAt より、一連の行列の計算(ジオメトリ処理、関節など)も   ┌ Sx ┐=┌スクリーン  ┐┌プロジェクション┐┌ビュー ┐┌ワールド┐┌ Lx ┐ (OpenGL形式)   │ Sy │ └トランスフォーム┘└トランスフォーム ┘└トランスフォーム┘└トランスフォーム┘│ Ly │   │ Sz │  の転置   の転置    の転置   の転置  │ Lz │   └ 1 ┘                          └ 1 ┘  となり、順番が異なる。  右手座標と左手座標とは関係ありません。たまたま、OpenGLとDirectXでそう扱っているだけです。 回転の名称  回転は、XYZ軸中心の回転角で表現される。  手の親指を立て、親指が回転軸の正の方向を向くように回転軸を握ったときの他の四指の方向が回転の正方向とする。  DirectXは左手、OpenGLは右手である。  Y軸 ヨー(yaw)、ヘディング(heading)    方位角  X軸 ピッチ(pitch)             仰角  Z軸 ロール(roll)、バンク(bank)      回転角 オイラー角  軸まわりの回転が3回連続して行われるときの「3つの回転角の組み」のこと。 12通りある。 クォータニオン(Quaternion、四元数)  各軸まわりの回転(オイラー角)の不具合を避ける。 3次元の回転行列  ┌→回転行列  ←→  XYZ軸中心の回転角(オイラー角)  │  ↓↑  │ 回転軸、角度 ※外積の利用  │  ↓↑  └→クォータニオン 配置の要素  姿勢 - ┌大きさ(scale)        ┌拡大・縮小  場所  ├向き(orientation)   ⇒  ├回転        ⇒ アフィン変換      └位置(position)        └平行移動  指定は、大きさ、向き、位置の順。(大きさ、向きを決めて(パターン/ポーズ)、位置付ける)  3Dの場合、ローカル座標の点(Lx,Ly,Lz)をワールド座標の点(Wx,Wy,Wz)に変換することである。  [Lx Ly Lz 1]┌  ┐┌  ┐┌  ┐=[Wx Wy Wz 1]  (DirectX形式)        │拡大││回転││移動│        └  ┘└  ┘└  ┘  変換はフレーム描画の時、(ローカル座標の点を書き換えず)毎回行う。(浮動小数点演算の誤差防止) 人体のモデリング  各パーツの階層構造(親子関係)、繋ぎ目が関節。  腰                        頭  ├腹─胸┬頭                   │  │   ├右上腕─右前腕─右手      右上腕─胸─左上腕  │   └左上腕─左前腕─左手       │  │  │  ├右腿─右脛─右足            右前腕 腹 左前腕  └左腿─左脛─左足             │  │  │                       右手 ┌腰┐ 左手                         右腿 左腿                          │ │                         右脛 左脛                          │ │                         右足 左足 関節の表現  ┌剛体モデル  └ボーン・スキンモデル(ワンスキン、スケルトン)  ※関節部分をなめらかに接続する。 関節モデルの配置(ローカル座標→ワールド座標)  親から子へ行列を計算していく   ワールド座標での子の配置=親のローカル座標での子の配置×ワールド座標での親の配置  肩                    ┌  ┐┌  ┐┌  ┐  (DirectX形式)  上腕                 ┌ │拡大││回転││移動│                     │ └  ┘└  ┘└  ┘   各頂点 [Wx Wy Wz 1]=[Lx Ly Lz 1]┌  ┐┌  ┐                    │ A ││ E │                    └  ┘└  ┘     ※Eは繰返し処理を記述しやすくさせる。                     └────┤  前腕                 ┌[][][] │   各頂点 [Wx Wy Wz 1]=[Lx Ly Lz 1]┌  ┐┌  ┐                    │ B ││AE│                    └  ┘└  ┘     ※AE=A                     └────┤  手                  ┌[][][] │   各頂点 [Wx Wy Wz 1]=[Lx Ly Lz 1]┌  ┐┌   ┐                    │ C ││BAE│                    └  ┘└   ┘    ※BAE=BA モデリングソフト(モデラー)  ローカル座標(モデル座標)でのオブジェクトデータ(物の形状、材質)を記述する。  パーツ単位で(まとまって動く物ごとにひとつにまとめて)作成する。 形状の表現  ┌ワイヤーフレーム(稜線)  ├サーフェス(面)  └ソリッド(固体) 形状の要素  メッシュ - 頂点、辺、ポリゴン(三角形面、四角形面)   ⇒ ┌頂点の座標   ⇒ ┌ジオメトリ(幾何)                                 └辺の接続関係    └トポロジ(位相)                                 (面の表裏)  図形プリミティブと描画プリミティブ   多角形→ ・・・ → 四角形 → 三角形 に分割可能。 オブジェクトデータのファイル保存形式(拡張子)  DirectX X  LightWave3D LWO  Maya OBJ  Softimage XSI  3DStudioMax 3DS  汎用 DXF、VRML2  など 材質(マテリアル)の要素  色、テクスチャ(マッピング画像)、物体表面の光の反射・屈折の特性(光り方) モーションエディタ  パーツ単位にモーションデータ(時間ごとの配置)を記述する。  ・ローカル座標での拡大・縮小、回転   ・親との位置関係 ベクトルの計算  大きさ、正規化、位置ベクトル、和、差、スカラー倍、内積(スカラー積)、外積(ベクトル積) 図形の方程式  表記┌陽関数 y=f(x)    │陰関数 f(x,y)=0    └媒介変数(パラメータ) x=f(t) y=g(t) ------------------------- 補足説明 ------------------------- デカルト座標(直交座標)と極座標  直交座標(x,y)と極座標(r,θ)の関係は   x=r・cosθ   y=r・sinθ   r=sqrt(x*x+y*y)   θ=atan(y/x) 速度成分と変位  dx、dyを速度成分とすると、変位(移動位置)は   x'=x+dx   y'=y+dy  speedを速度、θを向きとすると、変位(移動位置)は   x'=x+speed・cosθ   y'=y+speed・sinθ バウンディングボックス  画像または頂点を内包する矩形、直方体。  座標軸に平行なバウンディングボックス(AABB - axix-aligned bounding box) 2点間の距離  点p1(x1,y1)、p2(x2,y2)の距離Rは   R=sqrt((x2-x1)^2+(y2-y1)^2) ●参考本 ・ゲーム開発のための数学・物理学入門  ソフトバンク  2,800円+税 ISBN4-7973-2907-6 ・DirectXゲームグラフィックスプログラミングVer2.0  ソフトバンク 2,800円+税 ISBN4-7973-2980-7 ・ゲームプログラミングのための3Dグラフィクス数学  ボーンデジタル  7,000円+税 ISBN4-939007-37-5 ・DirectX9シェーダプログラミング  毎日コミュニケーションズ 3,800円+税 ISBN4-8399-1247-5