1
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?

DxLibの関数を用いて3D空間に半球(上半分)を描画

1
Last updated at Posted at 2025-12-21

球の描画

皆さんはDxLibを用いて球を描画する際どのような関数を使いますか?
多くの方は DrawSphere3D という関数を使われると思います。

DrawSphere3D

上記の関数はDxLib内の関数になっておりDxLibを用いて使うことが可能です。
この関数は 中心座標・半径・色・頂点数 を引数に持たせるだけで簡単に球を描画してくれる関数です。
私はこの関数を用いて球を描画していました。

弱点

ですがこの関数では下半分がステージ等に埋もれた時にも下のほうが描画されているということに気づきました。
そうなると見えない場所を描画するといった負荷がかかってきます。
そういう場合に半球(上半分)のみを描画したいと思いませんか。

半球だけ描画する関数なんかあるの?

結論 ありません。
ないなら作る。それがプログラマーです。

今回使う関数がこちら DrawPolygonIndexed3D

この関数は _頂点情報・ポリゴン配列情報・テクスチャハンドル_のみで使うことができます。

#include<DxLib>
#include<vector>

//関数の引数部分にあたる
struct PolygonInfo
{
    std::vector<VERTEX3D> vertex;
    std::vector<unsigned short> Indices;
}
{
    //使用する定数
    static const int VERTEX_NUM = 16;//頂点数 2のべき乗を推奨
    static const float RADIUS = 100.0f;//半径
    static const VECTOR POSITION = {0.0f,0.0f,0.0f};//中心座標
    static const float PI = 3.141592;
    
    PolygonInfo polInfo_;
	auto& vertexes = polInfo_.vertex;
	vertexes.clear();
	float radper = (360.0f / VERTEX_NUM)/180.0f *PI;
	{
        //一番上の頂点を設定する
		VERTEX3D vertex = {};
		VECTOR pos = POSITION;
		pos.y += RADIUS;
		vertex.pos = pos;
		vertex.norm = VNorm(VSub(vertex.pos, POSITION));
		vertex.dif = COLOR_U8(255, 255, 255, 255);
		vertex.spc = COLOR_U8(255, 255, 255, 255);
		vertex.u = 0.5f;
		vertex.v = 0.5f;
		vertex.su = vertex.u;
		vertex.sv = vertex.v;
		vertexes.push_back(vertex);
	}
	for (int i = 0; i < VERTEX_NUM / 4; i++)
	{
		float posY = POSITION.y + cosf((i + 1) * radper) * RADIUS;
		for (int j = 0; j < VERTEX_NUM; j++)
		{
			VERTEX3D vertex = {};
			VECTOR pos = POSITION;
			pos.x = POSITION.x + RADIUS * cosf(radper * j) * sinf((i + 1) * radper);
			pos.y =posY;
			pos.z = POSITION.z + RADIUS * sinf(radper * j) * sinf((i + 1) * radper);
			vertex.pos = pos;
			vertex.norm = VNorm(VSub(vertex.pos, POSITION));
			vertex.dif = COLOR_U8(255, 255, 255, 255);
			vertex.spc = COLOR_U8(255, 255, 255, 255);
			vertex.u = (pos.x - POSITION.x) / (RADIUS * 2) + 0.5f;
			vertex.v = (pos.z - POSITION.z) / (RADIUS * 2) + 0.5f;
			vertex.su = vertex.u;
			vertex.sv = vertex.v;
			vertexes.push_back(vertex);
		}
	}

	auto& indices = polInfo_.Indices;
	indices.clear();
	for (int i = 0; i < VERTEX_NUM; i++)
	{
		indices.push_back(0);
		indices.push_back((i + 1) % VERTEX_NUM + 1);
		indices.push_back(i + 1);
		for (int j = 0; j < VERTEX_NUM / 4 - 1; j++)
		{
			indices.push_back(j * VERTEX_NUM + i + 1);
			indices.push_back(j * VERTEX_NUM + (i + 1) % VERTEX_NUM + 1);
			indices.push_back((j + 1) * VERTEX_NUM + (i + 1) % VERTEX_NUM + 1);
			indices.push_back(j * VERTEX_NUM + i + 1);
			indices.push_back((j + 1) * VERTEX_NUM + (i + 1) % VERTEX_NUM + 1);
			indices.push_back((j + 1) * VERTEX_NUM + i + 1);
		}
	}
    DrawPolygonIndexed3D(
    vertexes.data(),
    static_cast<int>(vertexes.size()),
    indices.data(),
    static_cast<int>(indices.size())/3,
    DX_NONE_GRAPH, //画像のハンドル
    TRUE);
}

今回私はわかりやすいように画像を適用した。
Adobe Express - Test.gif

この結果を見てわかるように裏側が描画されません。これは バックカリング が行われているからです。
裏側を描画したい場合は

SetUseBackCulling(false);

をDrawする前に追加お願いします。

1
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
1
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?