「基本技術」の編集履歴(バックアップ)一覧に戻る

基本技術 - (2012/02/03 (金) 22:19:00) のソース

*技術指南/基本技術

ここでは、MMD系のゲームを作るための基本的な技術について紹介します。
ここで紹介している関数はDXライブラリのごく一部の関数です。
必ず、[[DXライブラリ置き場>http://homepage2.nifty.com/natupaji/DxLib/]]のDXライブラリの関数リファレンスマニュアル&サンプルプログラムもあわせて確認してください。


#hr(height=2,color=#ffA500)
-&link_anchor(Model){モデルの表示}
--&link_anchor(Model_iroiro){モデルのスケーリング、向きの変更、不透明度の変更}
-&link_anchor(Camera){カメラの操作}
-&link_anchor(Light){ライトの操作}
-&link_anchor(Anime){アニメーションアタッチ}
-&link_anchor(Accessory){アクセサリの装備}
#hr(height=2,color=#ffA500)
****&aname(Model,option=nolink){モデルの表示}
MMDゲーム化計画の第一歩である、モデルの表示方法を紹介します。
今回は、アールビットさんの十六夜咲夜モデルを使用させて頂きました。
ダウンロード>モデルから配布ページのリンクがありますので、興味のある方は是非ダウンロードしてください。

DXライブラリでは、3Dモデルを表示する際、まずモデルデータをメモリ上に読み込まなければなりません。
モデルのロードにはMV1LoadModel関数または、MV1DuplicateModel関数を使います。
#highlight(cpp){int MV1LoadModel( char *FileName ) ;
int MV1DuplicateModel( int SrcMHandle ) ;}
MV1LoadModel関数は、ファイル名を指定して3Dモデルをメモリ上にロードします。
読み込むことのできるモデルファイル形式は x, mqo, mv1, pmd( + vmd ) の3種類です。
&bold(){pmxファイルは使用できないので注意してください。}

返り値がメモリ上に読み込んだ3Dモデルファイルの識別番号で int 型の数値となっていて、
この値を使って、モデルの表示や位置の調整、向きの調整などを行います。

MV1DuplicateModel関数は、1度メモリ上に読み込んだ3Dモデルデータと同じデータを複製します。
弾やモブのように同じモデルを幾つも使うときにはこちらを使ったほうが、読み込み時間が少なくなります。


モデルの表示にはMV1LoadModel関数を使います。
#highlight(cpp){int MV1DrawModel( int MHandle ) ;}


では、実際に表示してみましょう。

-ソース
#region
#highlight(linenumber,cpp){{
#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	int ModelHandle ;//モデルハンドル

	// ウインドウモードで起動
	ChangeWindowMode( TRUE ) ;
	// DXライブラリの初期化
	if( DxLib_Init() < 0 )
	{
		// エラーが発生したら直ちに終了
		return -1 ;
	}
	// 描画先を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;

	// 3Dモデルの読み込み
	ModelHandle = MV1LoadModel( "Model/Sakuya/model.pmd" ) ;
	
	// メインループ(何かキーが押されたらループを抜ける)
	while( ProcessMessage() == 0 && CheckHitKeyAll() == 0 )
	{
		// 画面のクリア
		ClearDrawScreen() ;
		// 3Dモデルの描画
		MV1DrawModel( ModelHandle ) ;
		// 裏画面の内容を表画面に反映
		ScreenFlip();
	}

	// DXライブラリの後始末
	DxLib_End() ;
	// ソフトの終了
	return 0 ;
}
}}
#endregion
-実行結果
#image(ss0.jpg)
左下にほんの僅かですが、モデルが表示されていますね。

2Dゲームとは違い、3Dゲームでは3Dモデルの位置とカメラの位置、向きの関係で見え方が異なります。
そのため、画面の中心にモデルを表示したいときは、カメラを表示したいモデルの近くに移動させて、表示したいモデルの方向に向けるか、
カメラが映している範囲に表示したい3Dモデルの位置を移動させる必要があります。

カメラの操作は次の項目で紹介するので、今回は3Dモデルをカメラの映している範囲に3Dモデルを移動させます。
3Dモデルの位置座標を設定するにはMV1SetPosition関数を使います。
#highlight(cpp){int MV1SetPosition( int MHandle, VECTOR Position ) ;}

モデルをロードした後に、この関数でモデルの位置座標を設定します。

-ソース
#region
#highlight(linenumber,cpp){{
#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	int ModelHandle ;//モデルハンドル

	// ウインドウモードで起動
	ChangeWindowMode( TRUE ) ;
	// DXライブラリの初期化
	if( DxLib_Init() < 0 )
	{
		// エラーが発生したら直ちに終了
		return -1 ;
	}
	// 描画先を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;

	// 3Dモデルの読み込み
	ModelHandle = MV1LoadModel( "Model/Sakuya/model.pmd" ) ;

	// 画面に映る位置に3Dモデルを移動
	MV1SetPosition( ModelHandle, VGet( 320.0f, 225.0f, -370.0f ) ) ;
	
	// メインループ(何かキーが押されたらループを抜ける)
	while( ProcessMessage() == 0 && CheckHitKeyAll() == 0 )
	{
		// 画面のクリア
		ClearDrawScreen() ;
		// 3Dモデルの描画
		MV1DrawModel( ModelHandle ) ;
		// 裏画面の内容を表画面に反映
		ScreenFlip();
	}

	// DXライブラリの後始末
	DxLib_End() ;
	// ソフトの終了
	return 0 ;
}
}}
#endregion
-実行結果
#image(ss1.jpg)

****&aname(Model_iroiro,option=nolink){モデルのスケーリング、向きの変更、不透明度の変更}
次にモデルを複製してスケールの変更、向きの変更、不透明度の変更を変更してみましょう。
それぞれ、MV1SetScale,MVSetRotationXYZ,MV1SetOpacityRate関数を使います。
#highlight(cpp){
int MV1SetScale( int MHandle, VECTOR Scale ) ;
int MV1SetRotationXYZ( int MHandle, VECTOR Rotate ) ;
int MV1SetOpacityRate( int MHandle, float Rate ) ;}
回転に関しては、他に回転地ではなくモデルの方向ベクトルで指定するMV1SetRotationZYAxis関数や
#highlight(cpp){int MV1SetRotationZYAxis( int MHandle, VECTOR ZAxis, VECTOR YAxis, float ZTwist ) ;}
位置、回転、スケーリングなどを行列で指定する
#highlight(cpp){int MV1SetMatrix( int MHandle, MATRIX Matrix ) ;}
などもあります。

詳しくはDXライブラリ関数のリファレンスをみてください。

-ソース
#region
#highlight(linenumber,cpp){{
#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	int i;
	int ModelHandle[4] ;//モデルハンドル配列

	// ウインドウモードで起動
	ChangeWindowMode( TRUE ) ;
	// DXライブラリの初期化
	if( DxLib_Init() < 0 )
	{
		// エラーが発生したら直ちに終了
		return -1 ;
	}
	// 描画先を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;

	// 3Dモデルの読み込み
	ModelHandle[0] = MV1LoadModel( "Model/Sakuya/model.pmd" ) ;
	//既存のモデルを複製
	for(i = 1;i < 4;i ++){
		ModelHandle[i] = MV1DuplicateModel(ModelHandle[0]) ;
	}

	// 各モデルを画面に映る位置に3Dモデルを移動
	for(i = 0;i < 4;i ++){
		MV1SetPosition( ModelHandle[i], VGet( 305.0f+i*10, 225.0f, -370.0f ) ) ;
	}

	//モデルのスケールの変更
	MV1SetScale(ModelHandle[1], VGet(0.4f,0.2f,0.4f) );

	//モデルの向きを変更
	MV1SetRotationXYZ(ModelHandle[2], VGet(0.0f,PHI_F/2,0.0f) );

	//モデルの不透明度を変更
	MV1SetOpacityRate(ModelHandle[3], 0.1f);

	// メインループ(何かキーが押されたらループを抜ける)
	while( ProcessMessage() == 0 && CheckHitKeyAll() == 0 )
	{
		// 画面のクリア
		ClearDrawScreen() ;
		// 3Dモデルの描画
		for(i = 0;i < 4;i ++){
			MV1DrawModel( ModelHandle[i] ) ;
		}
		// 裏画面の内容を表画面に反映
		ScreenFlip();
	}

	// DXライブラリの後始末
	DxLib_End() ;
	// ソフトの終了
	return 0 ;
}
}}
#endregion
-実行結果
#image(ss2.jpg)

左から順にそのまま、スケール変更、向き変更、不透明度変更したモデルです。
半透明にしたモデルは、このように服が透けてしまうので、
透明度を操作してキャラをフェードイン、フェードアウトさせたい場合などは、ある程度工夫が必要です。

詳しくはミニテクニックの3Dモデルの半透明化を参考にしてください。

また、これら以外にもモデルの表示設定、ディフューズカラー、エミッシブカラー、アンビエントカラー、
Zバッファ使用の設定、物理演算の設定などを行うことができます。
これらについては自分で必要なときに確認してください。

#hr(height=2,color=#ffA500)
****&aname(Camera,option=nolink){カメラの操作}
#hr(height=2,color=#ffA500)
****&aname(Light,option=nolink){ライトの操作}
#hr(height=2,color=#ffA500)
****&aname(Anime,option=nolink){アニメーションアタッチ}
#hr(height=2,color=#ffA500)
****&aname(Accessory,option=nolink){アクセサリの装備}
3Dのゲームとなるとキャラに武器を持たせモーションに合わせて振り回すといったことをするかと思います。
DxLibでやる場合はMV1GetFrameLocalWorldMatrix関数を使います。
#highlight(cpp){MV1GetFrameLocalWorldMatrix( int MHandle, int FrameIndex ) ;}
指定のフレームのローカル座標からワールド座標に変換する行列を得る

>キャラクターモデルのアクセサリを付けたいフレーム( ボーン )の座標変換情報である行列をMV1GetFrameLocalWorldMatrix で取得して、それを MV1SetMatrix でアクセサリモデルの座標変換情報として設定することで、アクセサリモデルの原点がキャラクターモデルのアクセサリを付けたいフレームの座標になり、その状態で描画するとそのフレームにくっついているように見えるというものです

参考:[[アクセサリの装備@DxLib掲示板>http://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=past&no=2064]]
-ソース
#region
#highlight(linenumber,cpp){{
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	// ウインドウモードで起動
	ChangeWindowMode( TRUE ) ;
	
	int CharModel ;    // キャラクターモデル
	int AccessModel ;  // アクセサリーモデル
	
	int AttachIndex ;
	float TotalTime, PlayTime ;

	if( DxLib_Init() < 0 ) return -1 ;// エラーが発生したら直ちに終了

	// 別々に読み込み
	MV1SetLoadModelUsePhysicsMode( DX_LOADMODEL_PHYSICS_DISABLE ) ;//非物理演算モードで読み込む
	CharModel = MV1LoadModel( "Char.pmd" ) ;
	AccessModel = MV1LoadModel( "Access.x" ) ;


	SetDrawScreen( DX_SCREEN_BACK ) ;
	MV1SetPosition( CharModel, VGet( 320.0f, 225.0f, -370.0f ) ) ;
	
	// 3Dモデルの0番目のアニメーションをアタッチする
	AttachIndex = MV1AttachAnim( CharModel, 0, -1, FALSE ) ;

	// アタッチしたアニメーションの総再生時間を取得する
	TotalTime = MV1GetAttachAnimTotalTime( CharModel, AttachIndex ) ;
	SetCameraNearFar( 1.0f, 150.0f ) ;
	// 再生時間の初期化
	PlayTime = 0.0f ;
	// メインループ
	while( ProcessMessage() == 0 )
	{
		ClearDrawScreen() ;

		// 再生時間を進める
		PlayTime += 0.1f ;

		// 再生時間がアニメーションの総再生時間に達したら再生時間を0に戻す
		if( PlayTime >= TotalTime )
		{
			PlayTime = 0.0f ;
		}

		// 再生時間をセットする
		MV1SetAttachAnimTime( CharModel, AttachIndex, PlayTime ) ;

		// キャラクターモデルを描画
		MV1DrawModel( CharModel ) ;


		// アクセサリモデルを、キャラクターの右手フレームの座標系にあわせてから描画

		// キャラクターモデルの右手フレームの名前からフレーム番号を取得
		//
		// ※…右手フレームの名前はモデルによって違いますので、DxLibModelViewer.exe で
		//   キャラクターモデルを開いて、名前を確認してください
		int RightHandFrameNo ;
		RightHandFrameNo = MV1SearchFrame( CharModel, "右手首" ) ;

		// キャラクターモデルの右手フレームの行列を取得
		MATRIX RightHandMatrix ;
		RightHandMatrix = MV1GetFrameLocalWorldMatrix( CharModel, RightHandFrameNo ) ;

		// キャラクターモデルの右手フレームの行列をアクセサリモデルの行列としてセットしてから描画
		MV1SetMatrix( AccessModel, RightHandMatrix ) ;
		MV1DrawModel( AccessModel ) ;

		ScreenFlip();
	}
	// DXライブラリの後始末
	DxLib_End() ;
	// ソフトの終了
	return 0 ;
}
}}
#endregion

#hr(height=2,color=#ffA500)
記事メニュー
人気記事ランキング
目安箱バナー