57 章

DXライブラリは2D専用ライブラリです。

しかし、1つだけ3Dが利用出来る関数があります。


(→DXライブラリがver3になって、完全3D対応になりました。現在では、3Dプログラムはこんな手間なことをしなくても可能になっています)

DrawPolygon3Dという関数です。(関数の仕様について、出来るだけまずはリンクから本家リファレンスをご覧下さい)

この関数を使ってDXライブラリでも擬似3D背景を作ってやろう!というのがこの章のテーマです。

なお、今回も新しいプロジェクトを使用します。自分で準備する方は準備したプロジェクトに、57章の「mydat/img」にある画像を持ってきてください。


では、3Dについての解説に入っていきたいと思います。

まず今まで使ってきた矩形の画像はこのままでは使えません。「四角形」という形が無いのです。



今まで使ってきたこんな形は、「三角形2つ」で表現します。



三角形2つで四角形を表現したら、どんな形の四角形も表現出来ますね。

三角形abcと三角形defに分けて描画してみましょう。



さて、座標はどうなるでしょう。

ここで注意して欲しいのが「
3Dでは原点が左下になる」ということです。今までは下に行くほどyは増えていたと思います。原点は左上でしたよね。

3Dでは左下が原点となる為、yが増えると上に行くということに注意して下さい。



ですから、例えばaの座標は、中心点を(u,v)とすれば、(u-x/2, v+y/2)となるわけです。

また、
画像は2の乗数サイズしか使用出来ないことに注意して下さい。

2,4,8,16,32,64,256,512...そういうサイズの画像しか扱えません。※1

もし90x120のような画像を使いたい時は、128x128の画像の中に90x120の画像を入れ、

「画像中の90x120の部分だけ使う」と言った使用方法が必要です。

なお、(128x256)や(512x32)のように、2の乗数なら、縦と横のサイズが異なっても大丈夫です。



では具体的にプログラムの話をしていきましょう。

DXライブラリで使う3D座標1つの情報は、以下のような構造体で管理します。


struct VECTOR
{
  float x, y, z ;
} ;

struct VERTEX_3D
{
  VECTOR pos ;
  unsigned char b, g, r, a ;
  float u, v ;
} ;


座標一つの為にエラく沢山の変数がいるんだなと思うかもしれません。

必要な情報は(x,y,z)の座標データの他に、r,g,bといった色情報、透過率を表すa、

※1で話した画像のどの部分を使うかを示すu,vです。

随分多い変数がポリゴン一つに必要なものですね。

でも座標一つ一つに色や透過色が指定出来るということは画像の中で虹色を表現したり、

画像の端っこだけ段々透過にしていく表現をしたりと、凝った事が出来そうですね。



ここで、u,vがイマイチどんなものか良く解らない人もいるかと思います。

u,vは0.0f〜1.0fの値をセットするもので、画像のどこを使用するかを示すものです。uがxに相当し、vがyに相当します。

例えば先ほどの例で言うと、画像が128x128であり、使いたい部分が90x120なのだったら、
aは(u,v)=(0.0f, 0.0f)となりますが、
bは(u,v)=(90.0f/128.0f, 0)となるのです。横幅128ピクセルあるうちの90まで使いたければ90/128のように指定し、いずれも0〜1の値で指定します。
ということで、例えば
dは(u,v)=(90.0f/128.0f, 120.0f/128.0f)となるわけです。

こういう情報を座標一つ一つに持たせないといけないので少々面倒ですね。

先ほどのVERTEX_3Dを使って6つの点をVertex[6]として用意した場合、それぞれどうやって格納したらいいでしょうか。

([0]をa、[1]をb....、[5]をfとする)

今、中心点が(320,240)で、画像の横幅が100、縦幅が100であり、奥行きZである画像を描画する為、

aの位置に必要な情報を代入する場合は以下のように代入されます。


// 画面の中央に幅・高さ100で描画
Vertex[0].pos.x = 320.0F - 50.0F ;      Vertex[0].pos.y = 240.0F + 50.0F ;      Vertex[0].pos.z = Z ;
Vertex[0].u = 0.0F ;                    Vertex[0].v = 0.0F ;


これを踏まえた上で、DXライブラリのリファレンスにあるサンプル(一部修正)を見てみましょう。

これは、上に書いた通りの内容で2つの三角形を四角形になるようにくっつけて描画し、Zの位置を遠ざけたり近づけたりして、

画像を動かしているサンプルです。

※ こちらのソースコードはDXライブラリ本家のリファレンスからお借りしています。

--- main.cpp --- 

#include "../../../include/DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
             LPSTR lpCmdLine, int nCmdShow )
{
    int GrHandle ;
    float Z, ZAdd ; 
    VERTEX_3D Vertex[6] ;    // ポリゴン2枚なので、頂点は6個
    
    ChangeWindowMode(TRUE);

    // DXライブラリ初期化処理
    if( DxLib_Init() == -1 )    
         return -1 ;    // エラーが起きたら直ちに終了

    // 描画先を裏画面にする
    SetDrawScreen( DX_SCREEN_BACK ) ;

    // テクスチャの読み込み
    GrHandle = LoadGraph( "mydat/img/kabe.png" ) ;

    // Z値の初期化
    Z = 0.0F ;

    // Z値の加算値を初期化(最初は近づける)
    ZAdd = -1.0F ;

    // 何かキーが押されるまでループ
    while( CheckHitKeyAll() == 0 )
    {
        // メッセージ処理
        if( ProcessMessage() != 0 ) break ;

        // 画面の初期化
        ClearDrawScreen() ;

        // Z値の処理
        Z += ZAdd ;

        // 一定のラインを越えていたら進行方向を反転する
        if( Z < -300.0F || Z > 300.0F ) ZAdd = -ZAdd ;

        // 頂点情報のセット
        {
            // 画面の中央に幅・高さ100で描画
            Vertex[0].pos.x = 320.0F - 50.0F ;    Vertex[0].pos.y = 240.0F + 50.0F ;    Vertex[0].pos.z = Z ;
            Vertex[0].u = 0.0F ;
            Vertex[0].v = 0.0F ;

            Vertex[1].pos.x = 320.0F + 50.0F ;    Vertex[1].pos.y = 240.0F + 50.0F ;    Vertex[1].pos.z = Z ;
            Vertex[1].u = 1.0F ;
            Vertex[1].v = 0.0F ;
    
            Vertex[2].pos.x = 320.0F - 50.0F ;    Vertex[2].pos.y = 240.0F - 50.0F ;    Vertex[2].pos.z = Z ;
            Vertex[2].u = 0.0F ;
            Vertex[2].v = 1.0F ;

            Vertex[3].pos.x = 320.0F + 50.0F ;    Vertex[3].pos.y = 240.0F - 50.0F ;    Vertex[3].pos.z = Z ;
            Vertex[3].u = 1.0F ;
            Vertex[3].v = 1.0F ;

            Vertex[4].pos.x = 320.0F - 50.0F ;    Vertex[4].pos.y = 240.0F - 50.0F ;    Vertex[4].pos.z = Z ;
            Vertex[4].u = 0.0F ;
            Vertex[4].v = 1.0F ;

            Vertex[5].pos.x = 320.0F + 50.0F ;    Vertex[5].pos.y = 240.0F + 50.0F ;    Vertex[5].pos.z = Z ;
            Vertex[5].u = 1.0F ;
            Vertex[5].v = 0.0F ;

            // 輝度は全要素100%
            Vertex[0].r = Vertex[0].g = Vertex[0].b = 255 ;
            Vertex[1].r = Vertex[1].g = Vertex[1].b = 255 ;
            Vertex[2].r = Vertex[2].g = Vertex[2].b = 255 ;
            Vertex[3].r = Vertex[3].g = Vertex[3].b = 255 ;
            Vertex[4].r = Vertex[4].g = Vertex[4].b = 255 ;
            Vertex[5].r = Vertex[5].g = Vertex[5].b = 255 ;

            // a も最大値
            Vertex[0].a = 255 ;
            Vertex[1].a = 255 ;
            Vertex[2].a = 255 ;
            Vertex[3].a = 255 ;
            Vertex[4].a = 255 ;
            Vertex[5].a = 255 ;
        }

        // ポリゴンを透過色無しで2枚描画
        DrawPolygon3D( Vertex, 2, GrHandle, TRUE ) ;

        // 裏画面の内容を表画面に反映
        ScreenFlip() ;
    }

    // DXライブラリ使用の終了処理
    DxLib_End() ;

    // ソフトの終了
    return 0 ;
}

実行結果


良く解らない人はこのサンプルをじっくり見て、色々納得するまでサンプルプログラムをいじくり倒してください。


- Remical Soft -