[ 前へ | 目次 | 次へ ]
Japanese English

カメラワーク

ここでは、実践的なカメラワークを実現する方法について扱います。

スポンサーリンク


カメラワーク

VCSSL Graphics3D におけるカメラワークには、以下の2パターンの方式が存在します。

地球儀方式(※)のカメラワーク

最も単純なカメラワークは、ビュー座標系上に配置したワールド座標系を、 マウス操作に伴ってくるくると自転させる方式のものです。 例えるなら地球儀のような方式なので、 こでは地球儀方式(※)と呼びましょう。 この方式は、ある程度小さい立体を、 色々な角度から眺めるような場合に向いています。

※ 「地球儀方式」というのは一般的な呼称ではなく、あくまでもこのガイド内でそう呼んでいるだけです。

地球儀方式のカメラワークは非常に簡単に実装できるため (ワールド座標系をマウス操作に応じて回転させるだけです)、 ここではあまり深く扱いません。

実際、これまでに使用してきたフレームワーク(Graphics3DFramework)のデフォルトの視点操作処理でも、この方式のカメラワークを採用しています。そのため、独自に実装する必要は、通常はほとんどありません。

カメラ移動方式のカメラワーク

もう一つ、地球儀方式と共によく用いられるのが、 ワールド座標系上でカメラを動かすようなカメラワークです。 例えば3Dのアクションゲームなどでは、 主人公の背後から見下ろすような視点で、 主人公が移動するとカメラも後ろから追従していきます。 このようなカメラ移動方式のカメラワークは、 広大な立体を移動しながら眺めるような場合に向いています。

ここでは、このカメラ移動方式のカメラワークを中心に扱います。

ビュー変換

ワールド座標系からビュー座標系への座標変換は、 特別にビュー変換と呼ばれます。 カメラワークを制御する事は、 つまりはこのビュー変換を制御する事です。

座標変換の処理順序

一般に、立体の座標変換順序は

ローカル座標系
  → (ローカル変換) → ローカル座標系
  → (ワールド変換) → ワールド座標系
  → (ビュー変換)→ ビュー座標系

という流れで処理されます。

地球儀方式のビュー変換

地球儀方式のカメラワークの場合は、座標系の配置階層の順序は、 そのまま座標変換処理の順序に一致します。 即ち、ローカル座標系がワールド座標系上に配置されており、 ワールド座標系がビュー座標系上に配置されている(と見なせる)状態です。

そのため、ビュー変換は、 通常のローカル変換やワールド変換と全く変わりません。 従って、カメラワークの制御も通常と変わらず、 ワールド座標系を moveCoordinate 関数で移動させたり、 rotCoordinate 関数で回転させたりする事で制御します。

カメラ移動方式のビュー変換

カメラ移動方式のカメラワークでは、 ワールド座標系の上にビュー座標系を配置し、 ビュー座標系を動かすような制御を行う必要があります。 従ってこの場合、ビュー変換において、座標系の配置階層の順序と、 座標変換処理の順序が逆転します。 そのため、ビュー変換は、ローカル変換やワールド変換とは少し異なる変換を行う必要が生じます。

しかし VCSSL Graphics3D では、このようなカメラ移動方式の ビュー変換を制御するための関数が標準で用意されています。 プログラマは、通常の moveCoordinate 関数や rotCoordinate 関数の代わりに、 moveView 関数や rotView 関数を使うだけで、 通常の座標系操作と全く同じ感覚で、視点の操作を行う事ができます。

ビュー座標系の移動

※ 視点制御関数の引数についての注意点
これから解説する、視点を制御するための関数群は、 1つめの引数が座標系のIDでは無く、 レンダラーのIDとなっています。 この点は混同しないように注意が必要です。

ワールド座標系の座標軸を基準とした、ビュー座標系の移動には、 moveView 関数を使用します。

- 関数の形式 -

void moveView ( int rendererID, float dx, float dy, float dz )

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • dx, dy, dz: それぞれ X, Y, Z 方向のカメラの移動距離を指定します。

ビュー座標系の歩行

「ビュー座標系の座標軸を基準とした、ビュー座標系の動き」、 つまりビュー座標系の歩行には、 walkView 関数を使用します。

- 関数の形式 -

void walkView ( int rendererID, float dx, float dy, float dz )

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • dx, dy, dz: それぞれ X, Y, Z 方向のカメラの移動距離を指定します。

ビュー座標系の回転

座標軸まわりの回転

ワールド座標系の座標軸を基準とした、 ビュー座標系の回転には、 rotViewX, rotViewY, rotViewZ 関数や、 rotView 関数を使用します。

- 関数の形式 -

void rotViewX ( int rendererID, float angle )
void rotViewY ( int rendererID, float angle )
void rotViewZ ( int rendererID, float angle )

これら3つの関数は、それぞれ X, Y, Z 軸まわりの回転を行います。

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。

任意方向の軸まわりの回転

任意方向の回転軸まわりで回転させるには、 rotView 関数を使用します。

- 関数の形式 -

void rotView (
  int rendererID, float angle,
  float vx, float vy, float vz
)

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。
  • vx, vy, vz: ワールド座標系から見た回転軸の方向ベクトルを指定します。

任意の端点を通る、任意方向の軸まわりの回転

回転軸の方向と原点位置を指定するには、 rotView 関数に引数を追加して使用します。

- 関数の形式 -

void rotView (
  int rendererID, float angle,
  float vx, float vy, float vz,
  float px, float py, float pz
)

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。
  • vx, vy, vz: ワールド座標系から見た回転軸の、方向ベクトルを指定します。
  • px, py, pz: ワールド座標系から見た回転軸の、端点の位置ベクトルを指定します。

ビュー座標系の自転

座標軸まわりの回転

「ビュー座標系の座標軸を基準とした、ビュー座標系の回りこみ」、 つまりビュー座標系の自転には、 spinViewX, spinViewY, spinViewZ 関数や spinView 関数を使用します。

- 関数の形式 -

void spinViewX ( int rendererID, float angle )
void spinViewY ( int rendererID, float angle )
void spinViewZ ( int rendererID, float angle )

これら3つの関数は、それぞれ X, Y, Z 軸まわりの自転を行います。

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。

任意方向の軸まわりの回転

任意方向の回転軸まわりで自転させるには、 spinView 関数を使用します。

- 関数の形式 -

void spinView (
  int rendererID, float angle,
  float vx, float vy, float vz
)

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。
  • vx, vy, vz: 自身の座標軸基準で見た、回転軸の方向ベクトルを指定します。

任意の端点を通る、任意方向の軸まわりの回転

自転軸の方向と原点位置を指定するには、 spinView 関数に引数を追加して使用します。

- 関数の形式 -

void spinView (
  int rendererID, float angle,
  float vx, float vy, float vz,
  float px, float py, float pz
)

  • rendererID: レンダラーのIDを指定します。
  • angle: 軸まわりの回転角度(ラジアン単位)を指定します。 座標軸の向きに右ネジを進める回転方向を正とします。
  • vx, vy, vz: 自身の座標軸基準で見た、回転軸の方向ベクトルを指定します。
  • px, py, pz: 自身の座標軸基準で見た、回転軸の端点の位置ベクトルを指定します。

ビュー座標系の位置制御

ビュー座標系の位置制御(原点位置の指定)には、 setViewLocation 関数を使用します。

- 関数の形式 -

void setViewLocation ( int rendererID, float x, float y, float z )

引数は以下の通りです:

  • rendererID: レンダラーのIDを指定します。
  • x, y, z: ワールド座標系基準で、それぞれビュー座標系原点の X, Y, Z 座標を指定します。

ビュー座標系の姿勢制御

ビュー座標系の姿勢制御(X-Z-Xオイラー角指定)には、 setViewAngle 関数を使用します。

- 関数の形式 -

void setViewAngle (
  int rendererID,
  float alpha, float beta, float gamma
)

引数は以下の通りです。

  • rerndererID: レンダラーのIDを指定します。
  • alpha, beta, gamma: それぞれZ-X-Z系オイラー角の第一角α, 第二角β, 第三角γを指定します。

プログラム例

実際にビュー座標系を操作し、 3D舞台の中をゲームのように歩いてみましょう。 キー入力のイベントハンドラを作成し、 キーボードの上下左右キーによるビュー座標系の移動を実装します。 以下のように記述し、実行してみてくさい。


import graphics3d.Graphics3DFramework;
import Graphics3D;

// プログラムの最初に呼び出される関数
void onStart ( int rendererID ) {

	// 画面サイズや背景色の設定(省略可能)
	setWindowSize( 800, 600 );
	setBackgroundColor( 0, 0, 0, 255 );

	
	// 以下、カラフルなモデルで3D舞台を作成

	int box1 = newBoxModel( 1.0, 3.0, 1.0 );
	mountModel( box1, rendererID );
	setModelColor( box1, 255, 0, 0, 255 );

	int box2 = newBoxModel( 1.0, 3.0, 1.0 );
	mountModel( box2, rendererID );
	setModelColor( box2, 0, 255, 0, 255 );
	moveModel( box2, 5.0, 0.0, 5.0 );

	int box3 = newBoxModel( 1.0, 3.0, 1.0 );
	mountModel( box3, rendererID );
	setModelColor( box3, 0, 0, 255, 255 );
	moveModel( box3, -5.0, 0.0, 5.0 );

	int box4 = newBoxModel( 1.0, 3.0, 1.0 );
	mountModel( box4, rendererID );
	setModelColor( box4, 255, 255, 0, 255 );
	moveModel( box4, 5.0, 0.0, -5.0 );

	int box5 = newBoxModel( 1.0, 3.0, 1.0 );
	mountModel( box5, rendererID );
	setModelColor( box5, 0, 255, 255, 255 );
	moveModel( box5, -5.0, 0.0, -5.0 );
}


// キーが入力された際に呼び出される ( GUIライブラリのイベントハンドラ )
void onKeyDown( int id, int keyCode ){

	// レンダラーのIDを取得
	int rendererID = getRenderer();

	// 上下キーでカメラの前進後退
	if( keyCode == KEY_UP ){
		walkView( rendererID, 0.0, 0.0, -0.3 );
	}
	if( keyCode == KEY_DOWN ){
		walkView ( rendererID, 0.0, 0.0, 0.3 );
	}

	// 左右キーでカメラの方向転換
	if( keyCode == KEY_RIGHT ){
		spinViewY ( rendererID, -0.05 );
	}
	if( keyCode == KEY_LEFT ){
		spinViewY ( rendererID, 0.05 );
	}
}
Sample.vcssl

このプログラムを実行すると、黒い背景にカラフルな建物が表示されます。 キーボードの上下左右キー入力により、建物の間を歩いて移動する事ができます。

実行結果、舞台を移動するカメラの図
実行結果
カラフルな建物が表示される。キー操作で歩き回る事が可能。


この記事の著者

松井 文宏
[ RINEARN代表, 博士(理学), 応用情報技術者 ]
VCSSLやリニアングラフ3D、その他諸々を開発しています。ガイド類や記事も書いています。


スポンサーリンク



Japanese English
この階層の目次
[ 前へ | 目次 | 次へ ]
RINEARN からのお知らせ
※ VCSSL は RINEARN が開発しています。

ExevalatorのVer.2.4をリリース—MCPをサポートし、AI用の計算ツールとしても使用可能に
2025-11-15 - 式計算ライブラリExevalatorのVer.2.4をリリースしました。今回から、AIとやり取りするためのプロトコルである「MCP」をサポートし、AI用の計算ツールとしても使用可能になりました!

Exevalatorの最新版Ver.2.3をリリース、新たにPythonで使用可能に
2025-11-04 - 式計算ライブラリExevalatorのVer.2.3をリリースしました。今回から、新たにPython製のプログラムでも使用可能になりました!AI用ツール開発需要などの背景も踏まえて、詳細をお知らせします。

Exevalatorをアップデート、エラーメッセージの日本語化が手軽に
2025-10-31 - 式計算ライブラリExevalatorのVer.2.2.2をリリースしました。今回から、エラーメッセージを手軽に日本語化できるようになりました。数件のバグ修正&微調整も作んでいます。詳細をお知らせします。

関数電卓RINPn(りんぷん)オンライン版の内部構造を解説
2025-10-22 - 先日登場した、関数電卓ソフトRINPn(りんぷん)のオンライン版の内部構造を解説します。オープンソースなので、自由に改造・流用して、自分だけのWeb電卓を作る事も可能!(かもしれない)

関数電卓RINPn(りんぷん)、どこでもすぐ使えるオンライン版が登場!
2025-10-21 - フリー関数電卓ソフトRINPn(りんぷん)に、Web上でどこでもすぐ使える「オンライン版」が新登場しました!PCだけでなく、スマホでも利用可能です。詳細をお知らせします!

VCSSLのサポートAIが登場!ただし実用品質にはChatGPT有料アカウント(Plus)での利用推奨
2025-08-19 - プログラミング言語VCSSLについての質問対応や、コーディング作業を手伝ってくれるAIさんが登場しました!使用までの流れや推奨事項を解説し、実際の回答例や生成コード例などもたくさん紹介します!

各ソフトやVCSSLの英語版ドキュメント整備がほぼ完了
2025-06-30 - RINEARNでは2年前から、AIの補助による英語版ドキュメントの大幅拡充計画を進めてきました。今回、主要ドキュメント&コンテンツの英訳がほぼ完了し、一応の目標水準に達しました。詳細をお知らせします。

VCSSLの最新版をリリース:外部プログラムとの連携機能を少し強化、他
2025-05-25 - VCSSL3.4.52をリリースしました。外部プログラム(C言語製の実行ファイル等)との連携機能を少し強化し、文字化け対策やOS判別などを可能にしました。他にも細かい機能追加があります。詳細をお知らせします。

VCSSLの最新版をリリース、Java24上での非互換な挙動を対処
2025-04-22 - VCSSL3.4.50をリリースしました。Java24環境上でのネットワークドライブ関連のファイルパス解決で、従来環境とは異なる挙動が生じていたのを解消しました。詳細をお知らせします。

リニアングラフやVCSSLの最新版をリリース、目盛りの位置や内容を自由に指定可能に!
2024-11-24 - リニアングラフ3D/2Dを更新し、自由な位置に、自由な表記内容の目盛りを描けるようになりました!併せて、Java言語やVCSSLでの、プログラム制御用APIも拡張しています。詳細をお知らせします。