3Dモデルの描画
ここでは、3Dモデルの基本的な描画方法について説明します。
目次
1. モデルの構成要素
3Dモデルは以下の3つの要素から構成されています。
- モデルデータ ( Figure )
3Dモデルの骨組みとなる部分です。MBACデータを読み込むことで取得します。 -
テクスチャデータ ( Texture )
モデルに貼り付けるテクスチャや背景などです。BMP(ビットマップ)データを読み込むことで取得します。 -
アクションデータ ( ActTable )
モデルのアニメーションについての情報です。MTRAデータを読み込むことで取得します。
2. モデルの描画手順
ここではサンプルコードを用いて3Dモデルを描画する手順を説明します。
2.1. Figure, Texture, ActionTable オブジェクトの作成
使用するデータオブジェクト(Figure, Texture, ActionTable)のインスタンスを作成します。
読み込むデータをコンストラクタに設定し、Textureの場合はさらに、第2引数にテクスチャの種類を設定してください。通常のテクスチャの場合は true、環境マップの場合はfalse を設定します。
また、1つのモデルデータに対して複数のテクスチャを使用する場合、それらのTextureオブジェクトを格納した配列を用意しておく必要があります。
次に作成した Figure オブジェクトに Texture を Figure クラス内の setTexture( Texture texture ) または setTexture( Texture[ ] texArray ) メソッドを用いて関連付けます。設定するテクスチャの数が複数ある場合はそれらを格納した配列を引数に渡してください。
* CanvasEx
* コンストラクタ(データロード等初期化)
*/
public CanvasEx(){
try{
figure = new Figure( "Dragon.mbac" );
/* アクションデータの読み込み */
actTable = new ActionTable( "Dragon.mtra" );
/* テクスチャデータの読み込み */
texArray[0] = new Texture( "Dragon.bmp", true );
texArray[1] = new Texture( "DragonBG.bmp", true );
/* Figure にTexture を設定 */
figure.setTexture( texArray );
2.2. カメラ・ライトの設定
ワールド座標からカメラ座標に設定するための変換行列とライトの設定を行う Light オブジェクトを作成します。
カメラ座標への変換行列は AffineTrans クラス内の setViewTrans( Vector3D position, Vector3D direction, Vector3D up ) メソッドを用いて作成します。
position はカメラ位置、directionはカメラの方向、up はカメラの頭頂部の向きです。Light オブジェクトは平行光源の向き・明るさおよび環境光の明るさを設定します。これは Light オブジェクトを作成したあとでそれぞれを設定するメソッドを用いて設定することも、コンストラクタを用いて設定することも可能です。
vtrans.setViewTrans( new Vector3D( 0, 1024, 8192 ),
new Vector3D( 0, 4096, 0 ));
/* ライトの設定 */>
light.setAmbIntensity( 4096 );
2.3. Effect3D オブジェクトの作成
3D グラフィックスを描画する際のさまざまな視覚効果についての設定を行います。
MEXAでは、ライト・シェーディング・半透明・環境マッピングなどの視覚効果をEffect3D オブジェクトに設定することで行います。
Effect3D クラスのコンストラクタ public Effect3D( Light light, int shading, boolean isEnabled, Texture sphereMap ) の各引数の詳細は以下の通りです。
| 引数 | 詳細 |
|---|---|
| light | ライトオブジェクトです。先程作成したlightオブジェクトを設定してください。 |
| shading | シェーディング方法を設定します。グーローシェーディング(通常のシェーディング)の場合は NORMAL_SHADING、トゥーンシェーディングの場合は TOON_SHADING を設定してください。 |
| isEnabled | 半透明機能の有無を設定します。有効にする場合は true、無効にする場合は false を設定してください。 |
| sphereMap | 環境マップを設定します。環境マップとして使う Texture オブジェクトを設定してください。設定しない場合は null を設定してください。 |
なお、これらの設定は後で Effect3D に用意されているメソッドを使って個別に設定することも可能です。
effect = new Effect3D( light, Effect3D.NORMAL_SHADING, true, null );
2.4. FigureLayout オブジェクトの作成
モデルの描画レイアウトの設定を行います。
MEXAではモデルの描画位置・向き・サイズ・投影方法などをFigureLayout オブジェクト内に設定することで行います。
FigureLayout クラスのコンストラクタ FigureLayout( AffineTrans, trans, int x_scale, int y_scale, int cx, int cy ) の各引数の詳細は以下の通りです。
| 引数 | 詳細 |
|---|---|
| trans | アフィン変換行列を設定します |
| x_scale, y_scale | x軸・y軸方向のスケールを設定します |
| cx, cy | 描画範囲内での中心のx座標・y座標を設定します |
なお、これらの設定はあとで FigureLayout に用意されているメソッドを用いて個別に設定することも可能です。また、投影方法の設定は平行投影の場合は setParallelSize( )、透視投影の場合は setPerspective( ) メソッドを設定してください。
/* 投影方法の設定 */
layout.setPerspective( 1024, 10000, 4096 * 45 / 360 );
/* 座標変換関係設定 */
layout.setAffineTrans( vtrans );
/* スクリーン設定 */
layout.setCenter( centerX, centerY );
2.5. モデルのアクションの設定
モデルにアニメーションが設定されている場合、対象となる描画時刻におけるモデルの姿勢を設定します。
モデルの姿勢はFigure.setPosture( ActionTable actable, int action, int frame ) メソッドで描画するフレームを設定することにより行います。アクションデータの最大フレーム数はActionTable.getNumFrame( int action ) で取得できます。
max_frame = actTable.getNumFrame( 0 );
/* アクション動作設定 */
frame += ( 65536 * 3 );
frame %= max_frame;
figure.setPosture( actTable, 0, frame );
2.6. モデルの描画
取得した各オブジェクトをレンダリングし、VRAMに転送します。
レンダリングにはGraphics3D 内のrenderFigure( Figure figure, int x, int y, FigureLayout layout, Effect3D effect ) メソッドを使用します。第2、第3引数のx, yは描画位置です。しかし、レンダリングは描画登録しか行いませんので、これだけではフレームバッファへの描画処理は実行されません。最後にGraphics3D.flush( ) メソッドを呼び出すことで、それまで登録されていたオブジェクトの描画処理が行われます。
なお、Graphcs3D.drawFigure( Figure figure, int x, int y, FigureLayout layout, Effect3D effect ) メソッドは renderFigure( ) と flush( ) を実行するメソッドですので、これら2つのメソッドを実行する代わりにdrawFigure( ) メソッドを実行することでも描画することができます。
また、描画の際 repaint( ) メソッドを使用すると描画速度が遅くなりますので、GameCanvas クラス内の getGraphics( ) メソッドを用いてGraphics オブジェクトを常に保持した状態にし、paint( Graphics g ) メソッドおよび flushGraphics( ) メソッドを用いて描画することを推奨します。
paint( graphics );
flushGraphics();
try{
}
/**
* paint() メソッド
* 画面クリア、クリッピング領域設定/クリア、3D描画
*
* @param g Graphicsインスタンス
*/
public void paint( Graphics g ) {
g.setColor( bgc );
g.fillRect( 0, 0, getWidth(), getHeight() );
/* Graphics3D オブジェクトの取得 */
g3d = ( Graphics3D )g;
/* Render に Figure を設定 */
g3d.renderFigure( figure, 0, 0, layout, effect );
/* VRAM に転送 */
g3d.flush();

Sample 描画結果

