東方のような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
#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;
}
}
#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
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言語何でも質問掲示板
を見つけ、内容を読んでいるとき、
使った方が楽なのでは?と思いました。
1.
2.
のメリットとデメリットを(暇ならば)教えていただけると幸いです。また、上の質問とはあまり関係がないのでofftopicにしておきます。
東方の3D背景の作り方 • C言語交流フォーラム ~ mixC++ ~ - C言語何でも質問掲示板
を見つけ、内容を読んでいるとき、
と書かれていて、東方のような3D背景を作るなら、いちいちmqoファイルを作成するよりもDrawPolygonIndexed3DやらDrawPolygon3DをMa さんが書きました:単純に地面(画像の自由変形)を描画したいだけなら、mqoを使わずに、ここの講座にある3D背景の方法をとったほうがいいです。
私が推奨したmqoをつかう、というのは、マジな3D、つまり塔があったり、3Dな木があったり3Dな岩があったりした場合です
使った方が楽なのでは?と思いました。
1.
2.
のメリットとデメリットを(暇ならば)教えていただけると幸いです。また、上の質問とはあまり関係がないのでofftopicにしておきます。