220 likes | 429 Views
Borland Delphi6 で 3次元プログラミング. 牧之内研究室 4年 増尾 源哉 2002 年6月13日 参考文献: Quadruple D ヘルプ DirectX SDK ヘルプ. あらすじ. Borland Delphi6 の操作法 必要なソフト・コンポーネント 設定 3次元描画用ソフトの機能の紹介 使い方 サンプル サンプルを得るまでの動作手順. なぜ Borland Delphi6 か. Windows ( Pentium マシン)の理由
E N D
Borland Delphi6 で3次元プログラミング 牧之内研究室 4年 増尾 源哉 2002年6月13日 参考文献:Quadruple Dヘルプ DirectX SDKヘルプ
あらすじ • Borland Delphi6 の操作法 • 必要なソフト・コンポーネント • 設定 • 3次元描画用ソフトの機能の紹介 • 使い方 • サンプル • サンプルを得るまでの動作手順
なぜ Borland Delphi6 か • Windows (Pentium マシン)の理由 • UNIX用の3次元描画ソフト(OpenGL等)よりも Windows 用(DirectX等)の方が使いやすいのでは無いかと考えた • Pentium マシンは,3次元グラフィックスが高速 • Borland Delphi 6 の理由 • 使う言語は,基本的には何でもよい • Borland Delphi 6 は,Windows で3次元グラフィックスを行うのが簡単
準備 • Delphi6、DirectX SDKをインストールする。 • それぞれのホームページは以下のとおり。 • Delphi6: http://www.borland.co.jp/delphi/ • DirectX SDK: http://www.microsoft.com/JAPAN/msdn/directx/ • Quadruple Dをインストールする。 • これは、DirectXをDelphi6で利用できるようにするフリーのコンポーネントである。 • Quadruple D: http://www-fu.magma.ne.jp/~hayase/ • この他のコンポーネントとして、DelphiXや、WDirectXなどもある。
設定(1) • ここでは、Delphi6をフォルダ 「....\Delphi6」 にインストールしたものとします。 • Quadruple Dのアーカイブファイルdddd.lzhを適当なフォルダに解凍します。 ここでは、 「....\Quad」 に解凍したものとします。 • フォルダ「....\Quad\LIB」内にあるファイルをすべて、「....\Delphi6\Lib」にコピーします。同様に「....\Quad\LIB\dxheader」内のファイルもコピーします。
設定(2) • 続いて、Delphi6を起動し、メニューから、「ツール-環境オプション」を選び、「ライブラリ」タブを開きます。すると、ライブラリパスという項目の右端に「...」というボタンがあるので、クリックします。 すると、上のダイアログボックスが出ますので、ここに「....\Delphi6\Lib\Delphi2」と入力し、「追加」ボタンを押します。(....はもちろんDelphi6をインストールしたフォルダパス)
設定(3) • 最後に、コンポーネントをDelphiで使えるようにインストールをします。 • メニューから「コンポーネント-コンポーネントのインストール」を選び、「既存のコンポーネントへ追加」タブを選びます。 • この「ユニットファイル名」に「....\Delphi6\Lib\QuadrupleD_install.pas」を選び、「OK」を押します。
設定(4) • すると、次のような画面が出るので、 「QuadrupleD_install.pas」を選んで、「コンパイル」ボタンを押します。その後、「インストール」ボタンを押せば設定は終わりです。
DirectX機能紹介 • DirectXは、Windowsでマルチメディアアプリケーションを作成するための高速なAPIであり、2D、3Dの描画、サウンド、入力デバイスなどを扱うためのAPIを用意している。 • 3次元プログラミングを行う場合は、3Dの描画のためのDirect3Dの機能を用いる。 • Direct3Dでは、3次元座標をスクリーン座標に変換、視点の変更や回転などの機能があります。
使い方 • Delphi6を立ち上げると、「Project1」という空のプロジェクトが開かれています。(開かれない場合は、「ファイル-新規作成-アプリケーション」を選びます) • 次に、「Quadruple D」タブを選び、DRAWボタンを選びます。そして、Form1のウィンドウ内でクリックします。すると、Form1の中にDRAWアイコンが追加されると思います。 1.Quadruple Dを選ぶ 2.DRAWを選ぶ 3.クリックする
使い方(2) • Direct3Dで利用するユニットをプログラムリスト中のuses節に加える必要があります。 uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, dddd, ddraw, d3d, d3dtypes, d3dcaps; • 最後に画面の左下にある「オブジェクトインスペクタ」から「DDDD1」を選び、「Use3D」の値を「True」にします。これは、「DDDD1というコンポーネントでDirect3Dを使います」ということを表します。 • これでDirectXを使ったプログラミングを行うことが出来るようになりました。
サンプル • 始めの一歩として三角形を描画してみようと思います。これは、「Quadruple D」のチュートリアルにあるサンプルを少し変更しただけの簡単なものです。 • 三角形を描くための手順は次のとおりです。 • ビューポートの初期化 • ビューポートとは、Direct3Dがウィンドウのどこからどこまでを描画するか、という情報のこと。 • 変換行列の設定。次の変換のための行列(4×4)を設定する。 • オブジェクト固有のローカル座標からワールド座標への変換 • ワールド座標から視点を原点とする視野座標への変換 • 視野座標から、遠近感を出すための正規化座標への変換 • マテリアル(ポリゴンの色などの情報)の設定 • 光源の設定 • 実際の描画
サンプルの出力 • マテリアルや光源の設定が適当なため、あまり立体感のある絵にはなってませんが、ひとまず3角形ポリゴンは描けました。 この2つの三角形を描いてます。
サンプルを得るまでの手順 • ビューポートの初期化 • DDDD1の初期化関数TForm1.DDDD1Init()に次のリストを加えます。 var節に追加 viewParam:D3DVIEWPORT7; 手続き部分に追加 //ビューポートの特性 with viewParam do begin dwX:= 0; dwY:= 0; dwWidth:=DDDD1.BackBuffer.Width; dwHeight:=DDDD1.BackBuffer.Height; dvMinZ:= 0; dvMaxZ:= 1.0; end; //ビューポートの特性を指定する DDDD1.D3DDevice.SetViewport(@viewParam);
var mat: D3DMATRIX; Zn, Zf:Single; q:Single; //変換行列の設定 //ワールド行列 with mat do begin _11:=1; _12:=0; _13:=0; _14:=0; _21:=0; _22:=1; _23:=0; _24:=0; _31:=0; _32:=0; _33:=1; _34:=0; _41:=0; _42:=0; _43:=0; _44:=1; end; DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_WORLD, @mat); //ビュー行列 with mat do begin _11:=1; _12:=0; _13:=0; _14:=0; _21:=0; _22:=1; _23:=0; _24:=0; _31:=0; _32:=0; _33:=1; _34:=0; _41:=-1; _42:=0; _43:=5; _44:=1; end; DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_VIEW, @mat); • 変換行列を設定します。これもTForm1.DDDD1Init()に加える
//投影行列・・・投影行列・・・画角=90度 クリッピング面(近,遠)= (1.0, 5000.0) //なお、Cot(90/2 deg.) = 1.0 Zn:= 1.0; Zf:= 5000.0; q:=Zf / (Zf - Zn); with mat do begin _11:=1.0; _12:=0; _13:=0; _14:=0; _21:=0; _22:=1.0; _23:=0; _24:=0; _31:=0; _32:=0; _33:=q; _34:=1; _41:=0; _42:=0; _43:=-q*Zn; _44:=0; end; DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_PROJECTION, @mat);
//自分で発行したりはしない with dcvEmissive do begin a:=1.0; r:=0.0; g:=0.0; b:=0.0; end; //スペキュラ強度 dvPower:=50.0; //金属っぽく、かなりきつめのハイライト end; //Direct3Dに渡す DDDD1.D3DDevice.SetMaterial(@mtrl); var節に加える mtrl:D3DMATERIAL7; 手続きの中に加える //マテリアル ZeroMemory(@mtrl, sizeof(mtrl)); with mtrl do begin //光が当たっていない部分は、 //暗いクリーム色に近づく with dcvAmbient do begin a:=1.0; r:=0.3; g:=0.3; b:=0.1; end; //地の色はクリーム色 with dcvDiffuse do begin a:=1.0; r:=1.0; g:=1.0; b:=0.5; end; //てかる部分の色 with dcvSpecular do begin a:=1.0; r:=1.0; g:=1.0; b:=1.0; end; • マテリアルの設定。TForm1.DDDD1Init()に加える
var節に追加 light:D3DLIGHT7; 手続き部分に追加 //光源・・・それぞれのパラメータとマテリアルに指定された値の積が画面に出ます。 ZeroMemory(@light, Sizeof(light)); with light do begin with dcvAmbient do begin a:=1.0; r:=1.0; g:=1.0; b:=1.0; end; with dcvSpecular do begin a:=1.0; r:=1.0; g:=1.0; b:=1.0; end; with dcvDiffuse do begin a:=1.0; r:=1.0; g:=1.0; b:=1.0; end; //平行光源 dltType:=D3DLIGHT_DIRECTIONAL; //光源の向き with dvDirection do begin x:=1.0; y:=0.0; z:= 5.0; end; • 光源の設定。TForm1.DDDD1Init()に加える //光線の届く範囲 dvRange:=10000; //適当に遠くへ end; //Direct3Dに渡す //0番のライトとしてセット DDDD1.D3DDevice.SetLight(0, @light); //0番の光源をEnableにする。 DDDD1.D3DDevice.LightEnable(0, True);
描画。ここでは、ウィンドウをクリックすることで表示をすることにするので、クリックされたときのイベントハンドラTForm1.FormClick()に次のリストを書きます。描画。ここでは、ウィンドウをクリックすることで表示をすることにするので、クリックされたときのイベントハンドラTForm1.FormClick()に次のリストを書きます。 procedure TForm1.FormClick(Sender: TObject); var Vs:Array[0..5] of D3DVertex; clearRect:D3DRect; function MakeV(_x, _y, _z, _nx, _ny, _nz, _tu, _tv:Single):D3DVertex; begin with result do begin x:=_x; y:=_y; z:=_z; nx:=_nx; ny:=_ny; nz:=_nz; tu:=_tu; tv:=_tv; end; end;
begin //画面クリア with clearRect do begin x1:=0; y1:=0; x2:=DDDD1.BackBuffer.Width; y2:=DDDD1.BackBuffer.Height; end; //頂点座標の設定…頂点と法線ベクトルをセット。テクスチャ座標は、今回は適当 // x y z nx ny nz tu tv Vs[0]:=MakeV( 1.0,0.0,0.0, -1.0,-1.0,-1.0, 0.0,0.0); Vs[1]:=MakeV( 0.0,0.0,1.0, -1.0,-1.0,-1.0, 0.0,1.0); Vs[2]:=MakeV( 0.0,1.0,0.0, -1.0,-1.0,-1.0, 1.0,0.0); Vs[3]:=MakeV( 0.0,1.0,0.0, 1.0,-1.0,-1.0, 0.0,0.0); Vs[4]:=MakeV( 0.0,0.0,1.0, 1.0,-1.0,-1.0, 0.0,0.0); Vs[5]:=MakeV( -1.0,0.0,0.0, 1.0,-1.0,-1.0, 0.0,0.0);
DDDD1.D3DDevice.Clear(1,@clearRect,D3DCLEAR_TARGET+D3DCLEAR_ZBUFFER, $FF000000, 1.0, 0); DDDD1.D3DDevice.BeginScene; DDDD1.D3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST,D3DFVF_VERTEX,@Vs,6, 0); DDDD1.D3DDevice.EndScene; DDDD1.Flip; end;
最後に • 三角形ポリゴンを描けたことで、ポリゴンを複数用いてさまざまな形のオブジェクトを描けると考えられます。 • また、私はDelphi6,DirectXプログラミングを始めて間もなく、この資料にも不備があるかもしれません。詳しくは、それぞれのヘルプも参照になったほうが良いと思います。