.. :tocdepth:2 ============================ カメラ ============================ ICameraインターフェース ============================ MoNo.Graphics.IViewインターフェースかのCameraプロパティから、カメラ情報を取得することができます。 .. code-block:: csharp namespace MoNo.Graphics { public interface IView : IVewContext { ICamera Camera { get; } } } このICameraインターフェースから一部抜粋したものを以下に示します。 .. code-block:: csharp public interface ICamera { bool Perspective { get; set; } double ViewingAngle { get; set; } CodSys3d ViewingPos { get; set; } double ViewingScale { get; set; } double FocalDistance { get; } Size2i ScreenSize { get; } double ViewingDepth { get; } Size2d ViewingSize { get; } Box3d ViewingVolume { get; } Sphere3d WorldSphere { get; } ... } この中にビューポート変換や東映変換に必要な情報が全て入っています。 3つの座標系 ============================ 次の3つの座標系の関係を理解する必要があります。 * ワールド座標系 * カメラ座標系 * スクリーン座標径 ワールド座標系 ---------------------------- ワールド座標系は幾何モデルが描画される座標系です。 MoNo.RAILではこの座標系をグローバルな座標系と考えます。 カメラ座標系 ---------------------------- カメラ座標系は、カメラ(視点)に固定された座標系です。幾つか注意すべきポイントがあります。 * カメラ座標系は、ワールド座標系から見た局所座標系として表現されます。 * カメラ座標系とワールド座標系との間にスケール変換はかかっていません。 * カメラ座標系の原点は、カメラの注視点(ビューボリュームの中心)です。カメラの位置(視点)ではありません。 * カメラ座標系はワールド座標系と同じ右手系です。つまりカメラ座標系のZ軸は注視点から視点に向かう方向です。左手系が使われることもありますがMoNo.RAILにおいて座標系は右手座標系が使われます。 次のViewingPosプロパティによってカメラ座標系を取得/設定できます .. code-block:: csharp CodSys3d ICamera.ViewingPos { get; set; } スクリーン座標系 ---------------------------- 最終的に画面に映し出されたピクセル座標系です。Windowsと同様に左上を原点とします。 右向きがX軸の正の向き、下向きがY軸の正の向きです。 ビューボリューム ============================ WorldSphereとは ---------------------------- ICameraにはWorldSphereというプロパティがあります。 これはワールド座標系に定義されているモデルの境界球を表しています。 MoNo.RAILのカメラは、この境界球が視体積に含まれるように視体積の深さ(d = ViewingDepth)を決定します。 直行投影の場合 ---------------------------- Perspectiveプロパティがfalseの場合、直行投影となります。 .. image:: camera_screen.png 上の図は、カメラ座標系とスクリーン座標系の関係を表しています。右上のオレンジ色の矩形がカメラ座標系であり、左下の緑の矩形がスクリーン座標系です。 ViewingScaleはuv面における視体積の大きさを決めるパラメータであり、ビューの拡大/縮小に関係するパラメータです。 また、(w\ :sub:`s`\, h\ :sub:`s`\ )はスクリーンの大きさです。(w\ :sub:`s`\ , h\ :sub:`s`\ )はスクリーンのアスペクト比を保ちつつ、s = max(w, h)を満たすように決定されます。 .. image:: camera_ortho.png 上の図は直交投影の視体積を横から見た図です。 .. image:: camera_volume.png 直交投影の視体積は上図のようになり、OpenGL に渡される投影変換は次のようになります。 .. code-block:: csharp glOrtho( -w, w, -h, h, -d, d ); 透視投影の場合 ---------------------------- Perspective プロパティが true の場合には透視投影となり、視体積は下図のような錐台になります。 .. image:: camera_perspective.png 焦点距離 f = FocalDistance と視野角 α = ViewingAngle の間には次の関係が成り立ちます。 tan α = s / f ここで分数の分子は s であり、tanα = h / f ではないことに注意してください。 gluPerspective() などに渡す fovy とは異なるので注意が必要です。 OpenGL に渡される投影変換は次のようになります。 .. code-block:: csharp double w2 = w * ((f - d) / f); double h2 = h * ((f - d) / f); glFrustum( -w2, w2, -h2, h2, f - d, f + d);