5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

【C++】めちゃくちゃ強引にポリゴンを変動させる #1【3D】

Last updated at Posted at 2023-06-23

はじめに

この記事では、ゲーム内でプレイヤーがポリゴンを操作してステージを地形変動できるようにつくります。

カメラやプレイヤーの基本的な動作、モデルとの衝突判定等は実装済の状態で始めます。
地形を変動させるのはいろいろ方法がありますが、ひとまず強引にモデルのポリゴンの見た目と衝突判定を変える手法でやってみようと思います。

言語は C++エンジンを使わず にVisualStudioで、ライブラリは DXライブラリ で制作を進めていきます。

【記事中のコードについての注意事項】
分かりやすさのため実際のものから書き換えている部分や省略している部分があります。

長くなってしまうので、後半部分は記事を分けています。

目次

  1. モデルの情報を参照し、変数に格納
  2. ポリゴンとして表示
  3. ポリゴンを変動することができるようにする

モデルの情報を参照し、変数に格納

元々のステージの描画はこう
モデルを読み込み、大きさを少し変えて描画しています。
before_Stage.png
ちなみにプレイヤーモデルはMixsamoから拝借しています。

このステージモデルの情報を参照して変数格納します。
これはDXライブラリの関数でMV1GetReferenceMeshを使います。
データ取得前に参照用メッシュの構築(MV1SetupReferenceMesh)を忘れずに。
リファレンス通りに進めていきます。

Stage.h
class Stage 
{
//~省略~
private:
    //モデル情報
    int modelId_;

	//格納先変数
	MV1_REF_POLYGONLIST polygonList_;
};
Stage.cpp
void Stage::Init(void)
{
	//~省略~

	// モデル全体の参照用メッシュを構築
	MV1SetupReferenceMesh(modelId_, -1, TRUE);

	// 参照用メッシュ情報の取得
	polygonList_ = MV1GetReferenceMesh(modelId_, -1, TRUE);
}

void Stage::Draw(void)
{
	// ポリゴンの数だけ繰り返し
	int i;
	for (i = 0; i < polygonList_.PolygonNum; i++)
	{
		// ポリゴンを形成する三頂点を使用してワイヤーフレームを描画する
        // 色は黄色
		DrawLine3D(
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[0]].Position,
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[1]].Position,
			GetColor(255, 255, 0));

		DrawLine3D(
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[1]].Position,
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[2]].Position,
			GetColor(255, 255, 0));

		DrawLine3D(
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[2]].Position,
			polygonList_.Vertexs[polygonList_.Polygons[i].VIndex[0]].Position,
			GetColor(255, 255, 0));
	}
}

こうすると
after_Stage.png
こうなります。

今はまだメッシュ表示になっていますが、うまくモデル情報の参照ができていそうです。

ポリゴンとして表示

情報が取れたので、DrawPolygon3Dを使ってポリゴン表示をし、元々のステージのように描画していきたいと思います。

変数を変換

ここで問題が出てきます。DrawPolygon3Dの引数は、

DrawPolygon3D( VERTEX3D *Vertex, int PolygonNum, int GrHandle, int TransFlag ) 

ですが、先ほどモデル情報を格納した変数はMV1_REF_POLYGONLIST polygon_;

この MV1_REF_POLYGONLIST もDXライブラリの構造体で

MV1_REF_POLYGONLIST
struct MV1_REF_POLYGONLIST
{
    // ポリゴンの数
    int    PolygonNum ;

    // 頂点の数
    int    VertexNum ;

    // 頂点座標の最小値
    VECTOR    MinPosition ;

    // 頂点座標の最大値
    VECTOR    MaxPosition ;

    // ポリゴン構造体の配列へのポインタ
    MV1_REF_POLYGON    *Polygons ;

    // 頂点構造体の配列へのポインタ
    MV1_REF_VERTEX    *Vertexs ;
} ;

になっており、さらに頂点情報を持っている構造体の MV1_REF_VERTEX

MV1_REF_VERTEX
struct MV1_REF_VERTEX
{
    // 位置
    VECTOR    Position ;

    // 法線
    VECTOR    Normal ;

    // テクスチャ座標
    UV    TexCoord[ 2 ] ;

    // ディフューズカラー
    COLOR_U8    DiffuseColor ;

    // スペキュラカラー
    COLOR_U8    SpecularColor ;
} ;

になっています。
もう一度DrawPolygon3Dの引数を確認してみます。

DrawPolygon3D( VERTEX3D *Vertex, int PolygonNum, int GrHandle, int TransFlag ) 

第2~4引数はMV1_REF_POLYGONLISTやMV1_REF_VERTEXで設定できそうですが、実際にやってみても、第1引数の VERTEX3D *Vertex はエラーが出ます。

DrawPolygon3Dをするためには、先ほどの変数から一部の情報をVERTEX3D *Vertexへ変換する必要があるようです。

Stage.h
class Stage 
{
//~省略~
private:
    //~省略~
    //頂点情報の格納
    std::vector<VERTEX3D> vertexes_;
};
Stage.cpp
void Stage::Init(void)
{
    //~省略~
    //頂点情報へ変換
    for (auto& v : vertexes_)
    {
    	for (int i = 0; i < polygonList_.VertexNum; i++)
    	{
                //頂点情報に変換
    			v.pos = polygonList_.Vertexs[i].Position;
    			v.dif = polygonList_.Vertexs[i].DiffuseColor;
    			v.spc = polygonList_.Vertexs[i].SpecularColor;
    			v.norm = polygonList_.Vertexs[i].Normal;
    			v.u = polygonList_.Vertexs[i].TexCoord[0].u;
    			v.v = polygonList_.Vertexs[i].TexCoord[0].v;

                //動的配列に格納
    			vertexes_.emplace_back(v);
    	}
    }
}

void Stage::Draw(void)
{
    //~省略~
	//ポリゴン描画
	DrawPolygon3D(vertexes_.data(), polygonList_.PolygonNum, DX_NONE_GRAPH, FALSE);
}

変換することでDrawPolygon3Dで描画することができました。
bfrPoly_Stage.png
うまく表示できていそうですが、左奥のほうをよく見てみると
bfrPoly_Stage1.png
bfrPoly_Stage2.png
意図しないものも描画されてしまっています。

「ポリゴン」として表示

原因はVERTEX3D *Vertexにあります。VERTEX3Dは 頂点座標情報 をもつ構造体です。
vertex.png
VERTEX3Dはモデルから読み込んできた頂点座標情報を保有しているだけで、どの頂点がポリゴンを形成しているのかの情報が欠けています。
vertex1.png

ポリゴンは頂点を時計回りに指定し描画します。

欠けているポリゴン情報をVERTEX3Dに指定する必要があります。MV1_REF_POLYGONLISTから取得して指定します。

Stage.cpp
void Stage::Init(void)
{
    //~省略~

	int num = polygonList_.PolygonNum;
	for (int i = 0; i < num; i++)
	{
		auto poly = polygonList_.Polygons[i];

		for (int p = 0; p < 3; p++)
		{
			//頂点の要素番号を取得
			int vIndex = poly.VIndex[p];

			//取得した頂点の要素番号を使って、頂点情報を取得
			auto verRef = polygonList_.Vertexs[vIndex];

			//頂点情報へ変換
			VERTEX3D v;
			v.pos = verRef.Position;
			v.dif = verRef.DiffuseColor;
			v.spc = verRef.SpecularColor;
			v.norm = verRef.Normal;
			v.u = verRef.TexCoord[0].u;
			v.v = verRef.TexCoord[0].v;

			//動的配列に格納
			vertexes_.emplace_back(v);
		}
	}
    //~省略~
}

書き換えたあとの出力結果は、
complate_Stage.png
complate_Stage1.png
complate_Stage2.png
うまくポリゴン描画ができていそうです。

ポリゴンを変動させる

こちらへ続きます。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?