座標系と座標変換

Acerola3Dを利用した簡単なプログラムではキャラクタの位置やカメラの位置を指定するための仮想空間の座標だけを意識していれば十分ですが,少し高度な3DCGのプログラミングでは座標系の話は避けて通れません.Acerola3Dでは以下の4つの座標系が規定されています.

「仮想空間の座標系」は最も基本的な座標系でキャラクタやカメラの位置を指定する時に使用する物で,その名のとうり仮想空間における座標系です.Acerola3DのAPIで指定したり取得される座標のほとんどが,この座標系を利用しています.

「物理座標系」は一般にはカメラの座標系として捉えられるものです.カメラの視点を原点としてカメラの向きに合せて X,Y,Zの座標系が定められます.この座標系はアプリケーションを利用しているユーザが存在している物理空間に対していつも固定された座標系であるためのこのような名前になっています.ユーザの視点(カメラの視点でもある)で,座標計算をする場合に使用します.

「スクリーン上の座標系」はアプリケーションが表示されているウィンドウにおける座標系で,この座標系はウィンドウの左上隅を原点とし,右向きにX軸下向きにY軸が設定される2次元の座標系です.単位はピクセルであり通常のSwingなどのGUIにおけるプログラミングで使用する座標系と同じ物です.

「局所2D座標系」は3Dオブジェクトに吹き出しやラベルを表示させる時に使用する座標系で詳細は 吹き出し,ラベル,選択印のページで説明します.

Acerola3Dでは,仮想空間の座標系,物理座標系,スクリーン上の座標系の間の座標の変換のためのメソッドを提供しています.またユーザの視点を考慮した計算を行う時に便利な,仮想空間の座標系における物理座標系の単位ベクトル取得のためのメソッドがあります.

メソッド

また,バージョン2.37よりA3Objectに次のメソッドが追加されました.

これらのメソッドから得られるベクトルを使用すると,現在のキャラクタの位置や回転を基準にして計算が行えます.

デフォルトの仮想空間の座標系

Acerola3DでA3Windowなどの3Dオブジェクトを表示するためのオブジェクトを生成すると,仮想空間が構築されます.その仮想空間ではデフォルトで次のような右手座標系が使われます.

そしてカメラの位置は(X,Y,Z)=(0.0,0.0,2.0)で, Z軸の負の方向を正面として,Y軸の正の方向が上になるように配置されます.

Z軸が上となる座標系

デフォルトの座標系は上述したようにY軸が上となる座標系となるので,平面上を移動するオブジェクトの座標計算は主にXとZの値を用いた計算になります.これはJava3Dなどのデフォルトの座標系と同じ物ですが,場合によっては平面上の座標の指定を XとYを使って行いZ軸を高さ方向として扱いたい場合があります.

そのような場合は,A23クラス(jp.sourceforge.acerola3dパッケージ内) のsetDefaultUpperDirectionメソッドにA3Object.UpperDirection.Zを指定して呼び出して下さい.この呼び出しの後に A3Windowなどの3Dオブジェクトを表示するためのオブジェクトを生成すると以下のような座標系で仮想空間が生成されます.

カメラは(X,Y,Z)=(0.0,-2.0,0.0)の位置で Y軸の正の方向を正面とし,Z軸の正の方向が上となるように配置されます.

そしてAction3Dなどの3Dオブジェクトを生成して表示した時に,自動的にそのオブジェクトが X軸回りで90度回転して,Z軸が上となるようになります.さらにはオートコントロール機能を使用して自動的に回転を計算する場合の上方向ベクトルも,デフォルトでZ軸の正の方向になります.

座標変換のサンプルプログラム

サンプルプログラム

import jp.sourceforge.acerola3d.a3.*;
import java.awt.event.*;
import javax.vecmath.*;

public class CoordinateTest extends A3Adapter {
    A3Window window;
    Action3D a3;
    public CoordinateTest() throws Exception {
        window = new A3Window(300,300);
        window.setCameraLocImmediately(0.0,0.0,5.0);
        a3 = new Action3D("x-res:///axis.a3");
        window.add(a3);
        window.addA3Listener(this);
    }
    public void mousePressed(A3Event ae) {
        MouseEvent me = ae.getMouseEvent();
        Point3d p = window.canvasToVirtualCS(me.getX(),me.getY(),5.0);
        a3.setLoc(p.x,p.y,p.z);
    }
    public static void main(String args[]) throws Exception {
        new CoordinateTest();
    }
}

プログラム:CoordinateTest.java

このサンプルプログラムではA3Windowに付いている canvasToVirtualCSメソッドを用いて,Window上でクリックされた場所に3Dオブジェクトを配置しています.スクリーン座標から仮想空間の座標(または物理座標)への変換では深さの値を指定する必要がある点に気をつけて下さい.ただし,A3Windowにアバタの設定を行っている場合には,そのアバタとカメラの距離を深さとして利用して計算するメソッドも用意されています.