Fig. 10.3: Trackball
トラックボールはキーボード・マウスにより並進・回転の6自由度を入力するヒューマンインタフェースです. トラックボールを使うことにより,カメラを注視点まわりに視点変更することができるようになります.
トラックボールを操作する方法には,APIを直接呼び出す方法と,仮想マウスにコールバック登録する方法の二通りがあります. 同様に,トラックボールの状態を取得する方法にもAPI呼び出しとコールバック登録の二通りがあります. 仮想マウスとトラックボールおよ びユーザプログラムの関係をFig. 10.3に示します.
カメラの位置と向きは,注視点,経度角,緯度角および注視点からの距離によって決まります.
HITrackballDesc | ||
Vec3f |
target |
回転中心 |
float |
longitude |
経度[rad] |
float |
latitude |
緯度[rad] |
float |
distance |
距離 |
HITrackballIf | |
Vec3f |
GetTarget() |
void |
SetTarget(Vec3f) |
void |
GetAngle(float& lon, float& lat) |
void |
SetAngle(float lon, float lat) |
float |
GetDistance() |
void |
SetDistance(float dist) |
以下の機能で角度および距離に範囲制限を加えられます.
HITrackballDesc | ||
Vec2f |
lonRange |
経度範囲 |
Vec2f |
latRange |
緯度範囲 |
Vec2f |
distRange |
距離範囲 |
HITrackballIf | |
void |
GetLongitudeRange(float& rmin, float& rmax) |
void |
SetLongitudeRange(float rmin, float rmax) |
void |
GetLatitudeRange(float& rmin, float& rmax) |
void |
SetLatitudeRange(float rmin, float rmax) |
void |
GetDistanceRange(float& rmin, float& rmax) |
void |
SetDistanceRange(float rmin, float rmax) |
HITrackballIf | |
DVKeyMouseIf* |
GetKeyMouse() |
void |
SetKeyMouse(DVKeyMouseIf*) |
void |
SetCallback(HITrackballCallback*) |
トラックボールをマウス操作するにはDVKeyMouseクラスにコールバック登録する必要があります. コールバック登録するにはSetKeyMouse,登録先の仮想マウスを取得するにはGetKeyMouseを呼びます.
また,ユーザプログラムがトラックボールにコールバック登録して状態変化に反応できるようにするには, HITrackballCallbackクラスを継承し,SetCallback関数に渡します. HITrackballCallbackは以下の単一の仮想関数を持 ちます.
HITrackballCallback | |
virtual void |
OnUpdatePose(HITrackballIf* tb) |
OnUpdatePoseはトラックボールの位置・向きに変化が生じる度に呼ばれます. 引数のtbは呼び出し元のトラックボールを示します.
HITrackballは内部でDVKeyMouseCallbackを継承します. SetKeyMouseによりDVKeyMouseにコールバック登録すると, マウスカーソルが移動するたびにOnMouseMoveイベントハンドラが呼び出 され,トラックボールの内部状態が更新されます. マウス移動時のボタン状態に応じてトラックボールのどの状態が変化するかはある程度カスタマイズが可能です. 以下に関連する機能を示します.
HITrackballDesc | ||
int |
rotMask |
回転操作のボタン割当て |
int |
zoomMask |
ズーム操作のボタン割当て |
int |
trnMask |
平行移動操作のボタン割当て |
HITrackballIf | |
void |
SetRotMask(int mask) |
void |
SetZoomMask(int mask) |
void |
SetTrnMask(int mask) |
rotMask, zoomMask, trnMaskはそれぞれ 回転操作,ズーム操作,平行移動操作に割り当てたいマウスボタンに対応する OnMouseMoveのbutton引数の値を表します. 以下に対応関係をまとめます.
マウス移動方向 |
button値 |
変化量 |
左右 |
rotMask |
経度 |
上下 |
rotMask |
緯度 |
上下 |
zoomMask |
距離 |
左右 |
trnMask |
注視点x座標 |
上下 |
trnMask |
注視点y座標 |
デフォルトのボタン割当ては以下の通りです.
rotMask |
LBUTTON |
zoomMask |
RBUTTON |
trnMask |
LBUTTON + ALT |
したがって,左ボタンドラッグで回転操作,右ボタンドラッグでズーム操作,[ALT]キー+左ドラッグで平行移動となります.
なお,現状ではマウスの移動方向との対応をカスタマイズすることはできません. また,マウスホイールの回転とトラックボールを連動させる機能も未実装です.
マウス移動量と角度変化量,距離変化量との比例係数を下記の機能で設定できます.
HITrackballDesc | ||
float |
rotGain |
回転ゲイン[rad/pixel] |
float |
zoomGain |
ズームゲイン[rad/pixel] |
float |
trnGain |
平行移動ゲイン |
HITrackballIf | |
float |
GetRotGain() |
void |
SetRotGain(float g) |
float |
GetZoomGain() |
void |
SetZoomGain(float g) |
float |
GetTrnGain() |
void |
SetTrnGain(float g) |
トラックボールの位置と向きをカメラに反映するには, 描画処理の冒頭で以下のようにします.
// given GRRenderIf* render render->SetViewMatrix(trackball->GetAffine().inv());