龍神録C++版の3D背景について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Rittai_3D
記事: 525
登録日時: 11年前

龍神録C++版の3D背景について

#1

投稿記事 by Rittai_3D » 10年前

こんにちは。3Dです。今回はタイトルにある通り、龍神録C++版の3D背景について質問です。
東方のような3D背景を作ってみたく、3Dに手を出したのはいいのですが、何をどうしたらよいかも分からず、
龍神録プログラミングの館の3D背景を参考にしたり、龍神録C++版を参考にしたりして、勉強をしておりましたが、
分からない部分が出てきたので質問しに来ました。
// 以下、龍神録C++版のコード
Srf.h

コード:

#ifndef DEF_SRF_H

#define DEF_SRF_H

#include "DxLib.h"

typedef enum{
	eSRF_WIND,
	eSRF_FLOR,
	eSRF_DOOR,
	eSRF_LOOF,

	eSRF_DATANUM,
}eSRF;

class CSrf{

	VERTEX3D	m_Vertex[ 4 ] ;
	WORD		m_Index[ 6 ] ;
	int			m_nHdl;
	VECTOR		m_vDir;

public:
	CSrf( int z, int sHdl, unsigned uType );
	bool Process();
	void Draw();

	float GetZ();
	float GetZWid();
	void AddZ( float fZ );
};


#endif
Srf.cpp

コード:

#include "Srf.h"
#include "CommonDefine.h"

#define WIDX 40.0f
#define WIDY 40.0f
#define WIDZ 40.0f
#define SCRSPD 0.1f

#define SPACE 5
#define SPD 0.01f

const static float csDefRotaX = (-PI/5.f);
const static VECTOR vMOVE={0,5,-50};

const static VECTOR gvPos[eSRF_DATANUM][4]={
	{{0,WIDY,0},{0,WIDY,WIDZ},{0,0,WIDZ},{0,0,0}},	// eSRF_WIND?
	{{0,0,0},{0,0,WIDZ},{WIDX,0,WIDZ},{WIDX,0,0}},	// eSRF_FLOR?
	{{WIDX,WIDY,0},{WIDX,WIDY,WIDZ},{WIDX,0,WIDZ},{WIDX,0,0}},	// eSRF_DOOR?
	{{0,WIDY,0},{0,WIDY,WIDZ},{WIDX,WIDY,WIDZ},{WIDX,WIDY,0}},	// eSRF_LOOF?
};


CSrf::CSrf( int z, int sHdl, unsigned uType ){
	VECTOR vPos[eSRF_DATANUM][4]={};
	for( int i=0; i<eSRF_DATANUM; i++ ){
		for( int j=0; j<4; j++ ){
			vPos[i][j].x = gvPos[i][j].x - WIDX/2;
			vPos[i][j].y = gvPos[i][j].y - WIDY/2;
		}
	}
	unsigned Tp = uType;
	m_nHdl = sHdl;
	m_vDir = VGet( -SPD, 0.0f, -SPD );
	m_Vertex[ 0 ].pos  = VGet( vPos[Tp][0].x, vPos[Tp][0].y, vPos[Tp][0].z+WIDZ*z ) ;	//左上
	m_Vertex[ 0 ].norm = VGet( 1.0f, 0.0f, 0.0f ) ;
	m_Vertex[ 0 ].dif  = GetColorU8(255,255,255,255);
	m_Vertex[ 0 ].spc  = GetColorU8(  0,  0,  0,  0);
	m_Vertex[ 0 ].u    = 0.0f ;
	m_Vertex[ 0 ].v    = 0.0f ;
	m_Vertex[ 0 ].su   = 0.0f ;
	m_Vertex[ 0 ].sv   = 0.0f ;

	m_Vertex[ 1 ].pos  = VGet( vPos[Tp][1].x, vPos[Tp][1].y, vPos[Tp][1].z+WIDZ*(z+1) );	//右上
	m_Vertex[ 1 ].norm = VGet( 0.0f, 1.0f, 0.0f ) ;
	m_Vertex[ 1 ].dif  = GetColorU8(255,255,255,255) ;
	m_Vertex[ 1 ].spc  = GetColorU8(  0,  0,  0,  0) ;
	m_Vertex[ 1 ].u    = 1.0f ;
	m_Vertex[ 1 ].v    = 0.0f ;
	m_Vertex[ 1 ].su   = 0.0f ;
	m_Vertex[ 1 ].sv   = 0.0f ;

	m_Vertex[ 2 ].pos  = VGet( vPos[Tp][2].x, vPos[Tp][2].y, vPos[Tp][2].z+WIDZ*(z+1) );	//右下
	m_Vertex[ 2 ].norm = VGet( -1.0f, 0.0f, 0.0f ) ;
	m_Vertex[ 2 ].dif  = GetColorU8(255,255,255,255) ;
	m_Vertex[ 2 ].spc  = GetColorU8(  0,  0,  0,  0) ;
	m_Vertex[ 2 ].u    = 1.0f ;
	m_Vertex[ 2 ].v    = 1.0f ;
	m_Vertex[ 2 ].su   = 0.0f ;
	m_Vertex[ 2 ].sv   = 0.0f ;

	m_Vertex[ 3 ].pos  = VGet( vPos[Tp][3].x, vPos[Tp][3].y, vPos[Tp][3].z+WIDZ*z );	//左下
	m_Vertex[ 3 ].norm = VGet( 0.0f, -1.0f, 0.0f ) ;
	m_Vertex[ 3 ].dif  = GetColorU8(255,255,255,255) ;
	m_Vertex[ 3 ].spc  = GetColorU8(  0,  0,  0,  0) ;
	m_Vertex[ 3 ].u    = 0.0f ;
	m_Vertex[ 3 ].v    = 1.0f ;
	m_Vertex[ 3 ].su   = 0.0f ;
	m_Vertex[ 3 ].sv   = 0.0f ;


	// 2ポリゴン分のインデックスデータをセット
	m_Index[ 0 ] = 0 ;
	m_Index[ 1 ] = 1 ;
	m_Index[ 2 ] = 2 ;
	m_Index[ 3 ] = 2 ;
	m_Index[ 4 ] = 3 ;
	m_Index[ 5 ] = 0 ;
}

bool CSrf::Process(){
	for(int i=0; i<4; i++){
		m_Vertex[i].pos.z -= SCRSPD;
	}
	return true;
}

void CSrf::Draw(){
	MATRIX Matrix = MGetRotX( csDefRotaX ) ;
	VERTEX3D	tmpVertex[ 4 ];
	memcpy( tmpVertex, m_Vertex, sizeof( m_Vertex ) );
	for( int i=0; i<4; i++ ){
		tmpVertex[i].pos = VTransform( tmpVertex[i].pos, Matrix ) ;
		tmpVertex[i].pos = VAdd( tmpVertex[i].pos, vMOVE );
	}
	DrawPolygonIndexed3D( tmpVertex, 4, m_Index, 2, m_nHdl, TRUE ) ;
}

float CSrf::GetZ(){
	return m_Vertex[0].pos.z;
}

float CSrf::GetZWid(){
	return WIDZ;
}

void CSrf::AddZ( float fZ ){
	for(int i=0; i<4; i++){
		m_Vertex[i].pos.z += fZ;
	}
}
CSrfMgr.h

コード:

#ifndef DEF_SRFMGR_H
#define DEF_SRFMGR_H

#include "DxLib.h"
#include <list>

#include "Srf.h"

class CSrfMgr{
	std::list<CSrf*> m_List;
	int m_nHdl[eSRF_DATANUM];

#define START_N (-1)
#define END_N   (+7)

public:
	CSrfMgr(){
		m_nHdl[0] = LoadGraph("dat/Image/Back/廊下/襖.png");
		m_nHdl[1] = LoadGraph("dat/Image/Back/廊下/床.png");
		m_nHdl[2] = m_nHdl[0];
		m_nHdl[3] = 0;
		for( int t=0; t<eSRF_DATANUM; t++ ){
			for( int z=START_N; z<END_N; z++ ){
				m_List.push_back( new CSrf(z,m_nHdl[t],t) );
			}
		}
	}
	~CSrfMgr(){
		for(int i=0;i<eSRF_DATANUM;i++){
			DeleteGraph( m_nHdl[i] );
			m_nHdl[i] = 0;
			for(std::list<CSrf*>::iterator it=m_List.begin();it!=m_List.end();){
				delete (*it);
				it = m_List.erase( it );
			}
		}
	}
	bool Process(){
		for(std::list<CSrf*>::iterator it=m_List.begin();it!=m_List.end();it++){
			(*it)->Process();
			if( (*it)->GetZ() < (*it)->GetZWid()*(START_N-1) ){
				(*it)->AddZ( (END_N - START_N) * (*it)->GetZWid() );
			}
		}
		return true;
	}
	void Draw(){
		SetDrawMode( DX_DRAWMODE_BILINEAR );
		for(std::list<CSrf*>::iterator it=m_List.begin();it!=m_List.end();it++){
			(*it)->Draw();
		}
		SetDrawMode( DX_DRAWMODE_NEAREST );
	}
};

#endif
1. Srf.cpp 内の const static VECTOR gvPos[eSRF_DATANUM][4] の部分は一体なんの場所なのか
2. Srf.cpp 内の void CSrf::Draw() ではいったい何をしているのか(描写しているのはわかりますが、なぜ一度
tmpVertex にコピーして行列の計算や
ベクトルの足し算?をしているのか)
3. Srf.h 内の m_vDir は一体全体何なのか?(コンストラクタ、宣言以外で名前を見ないので)
4. Srf.h 内の m_Index[6] の使い方は?(これはDrawPolygonIndexed3D()のリファレンスを見ましたがよくわかりませんでしたのでついでの質問です)
5. SrfMgr.h 内の Process() 内のif分の意味が分かりません。(*it)->GetZ() ( it ごとの m_Vertex[0].pos.x? )が
(*it)->GetZWid()*(START_N-1)( = -80? )よりも小さくなるとZを320を加算しているのか

です。質問が無駄に多いですが、回答のほうよろしくお願いします。
オフトピック
3D背景について調べている時
東方の3D背景の作り方 • C言語交流フォーラム ~ mixC++ ~ - C言語何でも質問掲示板
を見つけ、内容を読んでいるとき、
Ma さんが書きました:単純に地面(画像の自由変形)を描画したいだけなら、mqoを使わずに、ここの講座にある3D背景の方法をとったほうがいいです。
私が推奨したmqoをつかう、というのは、マジな3D、つまり塔があったり、3Dな木があったり3Dな岩があったりした場合です
と書かれていて、東方のような3D背景を作るなら、いちいちmqoファイルを作成するよりもDrawPolygonIndexed3DやらDrawPolygon3Dを
使った方が楽なのでは?と思いました。
1.
2.
のメリットとデメリットを(暇ならば)教えていただけると幸いです。また、上の質問とはあまり関係がないのでofftopicにしておきます。
#コードタグに失敗があったため修正(11:44)
最後に編集したユーザー Rittai_3D on 2014年5月11日(日) 11:44 [ 編集 1 回目 ]
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 龍神録C++版の3D背景について

#2

投稿記事 by softya(ソフト屋) » 10年前

コードの中身は理解していないので解析方法だけ。
まず、疑問に思っているコードの値や、コードそのものを抜いたりして動作を確認してみてください。
1. gvPosの値を変えてみましょう。
2. 行列の計算やベクトルの足し算をやめてみましょう。
以下略。

>mqoを使わずに、ここの講座にある3D背景の方法をとったほうがいいです。

私にはどちらでも良いと思います。その時その時で調整も含めて楽だと思える方法を選択しています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 龍神録C++版の3D背景について

#3

投稿記事 by h2so5 » 10年前

3D_3D さんが書きました: 1. Srf.cpp 内の const static VECTOR gvPos[eSRF_DATANUM][4] の部分は一体なんの場所なのか
壁・床・天井を構成する長方形の頂点のx, y, z 座標ですね。
この座標が基準となって、z軸方向に8枚ずつ壁・床・天井の板が並んでいることになります。
3D_3D さんが書きました: 2. Srf.cpp 内の void CSrf::Draw() ではいったい何をしているのか(描写しているのはわかりますが、なぜ一度
tmpVertex にコピーして行列の計算や
ベクトルの足し算?をしているのか)
memcpyする意味はないですね。
3D_3D さんが書きました: 3. Srf.h 内の m_vDir は一体全体何なのか?(コンストラクタ、宣言以外で名前を見ないので)
使われていないのでよくわからないですが、移動する向きと速度のようですね。
3D_3D さんが書きました: 4. Srf.h 内の m_Index[6] の使い方は?(これはDrawPolygonIndexed3D()のリファレンスを見ましたがよくわかりませんでしたのでついでの質問です)
頂点を結ぶ順序の指定です。三角形2つで一つの長方形を構成しています。
3D_3D さんが書きました: 5. SrfMgr.h 内の Process() 内のif分の意味が分かりません。(*it)->GetZ() ( it ごとの m_Vertex[0].pos.x? )が
(*it)->GetZWid()*(START_N-1)( = -80? )よりも小さくなるとZを320を加算しているのか
オブジェクトが画面手前に消えたときにそれを画面の一番奥に戻すことで、オブジェクトが無限に奥まで続いているように見えます。

Rittai_3D
記事: 525
登録日時: 11年前

Re: 龍神録C++版の3D背景について

#4

投稿記事 by Rittai_3D » 10年前

返信ありがとうございます。

>softyaさん
softya(ソフト屋) さんが書きました:コードの中身は理解していないので解析方法だけ。
まず、疑問に思っているコードの値や、コードそのものを抜いたりして動作を確認してみてください。
1. gvPosの値を変えてみましょう。
2. 行列の計算やベクトルの足し算をやめてみましょう。
以下略。
3D背景に関係あるであろう部分を抜き出して、別のプロジェクトに移動させ、色々いじって解析してみたいと思います。
こういう解析もやってみると意外と楽しかったりしますね。理解できればの話ですが(笑)
色々数値を変えて納得がいくまでいじり倒したいとおもいます。
softya(ソフト屋) さんが書きました:>mqoを使わずに、ここの講座にある3D背景の方法をとったほうがいいです。

私にはどちらでも良いと思います。その時その時で調整も含めて楽だと思える方法を選択しています。
一度モデルで行ってみましたが、スクロールがうまくいかなかったり、その他色々ありましたので、どちらのほうがよいか聞いた次第です。
なるほど。目先のことだけでなく、先のことも考えるのですか。今の自分には出来なくても、将来は出来るように勉強します。

>h2so5さん
h2so5 さんが書きました:壁・床・天井を構成する長方形の頂点のx, y, z 座標ですね。
この座標が基準となって、z軸方向に8枚ずつ壁・床・天井の板が並んでいることになります。
ああ、なるほど。そういうことでしたか。一体全体なんの数値なんだろうと思っていました。
「この座標が基準となって」の部分なのですが、よく意味がわからなかったので解説していただけないでしょうか?
h2so5 さんが書きました:頂点を結ぶ順序の指定です。三角形2つで一つの長方形を構成しています。
ということは、
m_Index[0]とm_Index[5]は0番目に、
m_Index[1]は1番目に、
m_Index[2]とm_Index[3]は2番目に、
m_Index[4]は3番目に結ぶということでしょうか?
また、どの頂点と頂点を結ぶのでしょうか?理解力がなくて申し訳ないですが回答お願いします。
初心者です

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 龍神録C++版の3D背景について

#5

投稿記事 by h2so5 » 10年前

3D_3D さんが書きました: ああ、なるほど。そういうことでしたか。一体全体なんの数値なんだろうと思っていました。
「この座標が基準となって」の部分なのですが、よく意味がわからなかったので解説していただけないでしょうか?
8枚並ぶのでそのうちひとつの座標、ということです。
3D_3D さんが書きました: ということは、
m_Index[0]とm_Index[5]は0番目に、
m_Index[1]は1番目に、
m_Index[2]とm_Index[3]は2番目に、
m_Index[4]は3番目に結ぶということでしょうか?
また、どの頂点と頂点を結ぶのでしょうか?理解力がなくて申し訳ないですが回答お願いします。
m_Index[ 0 ] ~ m_Index[ 2 ] までが三角形1枚め、m_Index[ 3 ] ~ m_Index[ 5 ] までが三角形2枚めです。
だから頂点 0, 1, 2 を結んで三角形ひとつ、頂点 2, 3, 0 を結んでもう一つです。
頂点番号は m_Vertex[ ] の番号と同じです。

Rittai_3D
記事: 525
登録日時: 11年前

Re: 龍神録C++版の3D背景について

#6

投稿記事 by Rittai_3D » 10年前

h2so5さん、返信ありがとうございます。
h2so5 さんが書きました:
3D_3D さんが書きました: ああ、なるほど。そういうことでしたか。一体全体なんの数値なんだろうと思っていました。
「この座標が基準となって」の部分なのですが、よく意味がわからなかったので解説していただけないでしょうか?
8枚並ぶのでそのうちひとつの座標、ということです。
なるほど!一つの座標が分かれば、その座標を基準に一定の間隔で表示できますからね。解説ありがとうございます。
h2so5 さんが書きました:
3D_3D さんが書きました: ということは、
m_Index[0]とm_Index[5]は0番目に、
m_Index[1]は1番目に、
m_Index[2]とm_Index[3]は2番目に、
m_Index[4]は3番目に結ぶということでしょうか?
また、どの頂点と頂点を結ぶのでしょうか?理解力がなくて申し訳ないですが回答お願いします。
m_Index[ 0 ] ~ m_Index[ 2 ] までが三角形1枚め、m_Index[ 3 ] ~ m_Index[ 5 ] までが三角形2枚めです。
だから頂点 0, 1, 2 を結んで三角形ひとつ、頂点 2, 3, 0 を結んでもう一つです。
頂点番号は m_Vertex[ ] の番号と同じです。
そういう意味でしたか。意味がやっと分かりました。色々自分なりに考えても考えがまとまらなかったのですっきりしました!

自分が疑問に思っていたことがわかってよかったです。softyaさんに教えていただいたコードの解析方法も活用し、自分のプログラミング
技術を向上させたいです。回答してくださったsoftyaさん、h2so5さん、本当にありがとうございました。
オフトピック

コード:

#define WIDX 40.0f
#define WIDY 40.0f
#define WIDZ 40.0f
ってどこから来た数字かな?と思いましたが、

コード:

const static float csDefRotaX = (-PI/5.f);
MATRIX Matrix = MGetRotX( csDefRotaX ) ;
ってところで「(-PI/5.f)だけX軸回転すると一つのもの(たとえば襖)の幅は40になるのでは?」
と考えました。微妙に気になっていましたが、質問するほどでもないかと考えて質問しませんでした。
間違えていましたらしてくしてください。
初心者です

閉鎖

“C言語何でも質問掲示板” へ戻る