カメラ¶
ICameraインターフェース¶
MoNo.Graphics.IViewインターフェースかのCameraプロパティから、カメラ情報を取得することができます。
namespace MoNo.Graphics {
public interface IView : IVewContext
{
ICamera Camera { get; }
}
}
このICameraインターフェースから一部抜粋したものを以下に示します。
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プロパティによってカメラ座標系を取得/設定できます
CodSys3d ICamera.ViewingPos { get; set; }
スクリーン座標系¶
最終的に画面に映し出されたピクセル座標系です。Windowsと同様に左上を原点とします。 右向きがX軸の正の向き、下向きがY軸の正の向きです。
ビューボリューム¶
WorldSphereとは¶
ICameraにはWorldSphereというプロパティがあります。 これはワールド座標系に定義されているモデルの境界球を表しています。 MoNo.RAILのカメラは、この境界球が視体積に含まれるように視体積の深さ(d = ViewingDepth)を決定します。
直行投影の場合¶
Perspectiveプロパティがfalseの場合、直行投影となります。
上の図は、カメラ座標系とスクリーン座標系の関係を表しています。右上のオレンジ色の矩形がカメラ座標系であり、左下の緑の矩形がスクリーン座標系です。
ViewingScaleはuv面における視体積の大きさを決めるパラメータであり、ビューの拡大/縮小に関係するパラメータです。 また、(ws, hs)はスクリーンの大きさです。(ws, hs)はスクリーンのアスペクト比を保ちつつ、s = max(w, h)を満たすように決定されます。
上の図は直交投影の視体積を横から見た図です。
直交投影の視体積は上図のようになり、OpenGL に渡される投影変換は次のようになります。
glOrtho( -w, w, -h, h, -d, d );
透視投影の場合¶
Perspective プロパティが true の場合には透視投影となり、視体積は下図のような錐台になります。
焦点距離 f = FocalDistance と視野角 α = ViewingAngle の間には次の関係が成り立ちます。
tan α = s / f
ここで分数の分子は s であり、tanα = h / f ではないことに注意してください。 gluPerspective() などに渡す fovy とは異なるので注意が必要です。
OpenGL に渡される投影変換は次のようになります。
double w2 = w * ((f - d) / f);
double h2 = h * ((f - d) / f);
glFrustum( -w2, w2, -h2, h2, f - d, f + d);