Edited at
DxLibDay 24

DXライブラリで五芒星を描こう!

この記事はDxLib Advent Calendar 2018 24日目の記事です。

<<23日目 画像前処理で描画速度とメンテナンス性を両立する | 25日目 Seitenさんの誕生日です!数字だけ等幅にするライフハック……?>>


はじめに

みなさんはじめまして。lego hasiriといいます。

DirectXを簡単に扱えるライブラリとしてはこのDXライブラリと(Open)Siv3Dがありますね。

Siv3Dは図形の描画などがこのDXライブラリよりも幅広くサポートされていますね。ですが個人的にはDXライブラリのほうが細かいところまで自分でできるので、Siv3Dの機能をDXライブラリでも使えるようにしたい。

ということで今回は手始めに五芒星の描画から始めていきたいと思います。

完成予定図↓

image.png


ソース


Vec2.cpp

struct Vec2 {

Point x = 0;
Point y = 0;

Vec2(Point x, Point y)
:x(x), y(y) {
}
}



GetPositionBy4Point.cpp

VERTEX2D GetPositionBy4Point(Vec2 p1, Vec2 p2, Vec2 p3, Vec2 p4) {

auto s1 = ((p4.x - p2.x)*(p1.y - p2.y) - (p4.y - p2.y)*(p1.x - p2.x)) / 2;//面積S1 = {(P4.X - P2.X) * (P1.Y - P2.Y) - (P4.Y - P2.Y) * (P1.X - P2.X)} / 2
auto s2 = ((p4.x - p2.x)*(p2.y - p3.y) - (p4.y - p2.y)*(p2.x - p3.x)) / 2;//面積S2  = { (P4.X - P2.X) * (P2.Y - P3.Y) - (P4.Y - P2.Y) * (P2.X - P3.X) } / 2
auto c1 = Vec2(p1.x + (p3.x - p1.x)*s1 / (s1 + s2), p1.y + (p3.y - p1.y)*s1 / (s1 + s2));//C1.X= P1.X + (P3.X - P1.X) * S1 / (S1 + S2), C1.Y = P1.Y + (P3.Y - P1.Y) * S1 / (S1 + S2)
VERTEX2D c = { 0 };
c.pos.x = c1.x;
c.pos.y = c1.y;
c.rhw = 0.0f;
return c;
}


DrawStar.cpp

int DrawStar(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int x5, int y5, unsigned int color, int FillFlag) {

UINT r = color >> 16;
UINT g = color << 8;
UINT b = color << 16;
g = g >> 16;
b = b >> 16;
COLOR_U8 fillColor = GetColorU8(r, g, b, 225);
VERTEX2D PosVertex[10] = { 0 };

PosVertex[1] = GetPositionBy4Point(Vec2((Point)x1, (Point)y1), Vec2((Point)x2, (Point)y2), Vec2((Point)x3, (Point)y3), Vec2((Point)x5, (Point)y5));
PosVertex[3] = GetPositionBy4Point(Vec2((Point)x1, (Point)y1), Vec2((Point)x2, (Point)y2), Vec2((Point)x3, (Point)y3), Vec2((Point)x4, (Point)y4));
PosVertex[5] = GetPositionBy4Point(Vec2((Point)x2, (Point)y2), Vec2((Point)x3, (Point)y3), Vec2((Point)x4, (Point)y4), Vec2((Point)x5, (Point)y5));
PosVertex[7] = GetPositionBy4Point(Vec2((Point)x1, (Point)y1), Vec2((Point)x3, (Point)y3), Vec2((Point)x4, (Point)y4), Vec2((Point)x5, (Point)y5));
PosVertex[9] = GetPositionBy4Point(Vec2((Point)x1, (Point)y1), Vec2((Point)x2, (Point)y2), Vec2((Point)x4, (Point)y4), Vec2((Point)x5, (Point)y5));

PosVertex[0].pos.x = (float)x1; PosVertex[0].pos.y = (float)y1;
PosVertex[2].pos.x = (float)x2; PosVertex[2].pos.y = (float)y2;
PosVertex[4].pos.x = (float)x3; PosVertex[4].pos.y = (float)y3;
PosVertex[6].pos.x = (float)x4; PosVertex[6].pos.y = (float)y4;
PosVertex[8].pos.x = (float)x5; PosVertex[8].pos.y = (float)y5;

if (FillFlag) {

USHORT IndexNum[24] = { 0 };

IndexNum[0] = 0;
IndexNum[1] = 1;
IndexNum[2] = 9;

IndexNum[3] = 2;
IndexNum[4] = 3;
IndexNum[5] = 1;

IndexNum[6] = 4;
IndexNum[7] = 5;
IndexNum[8] = 3;

IndexNum[9] = 6;
IndexNum[10] = 7;
IndexNum[11] = 5;

IndexNum[12] = 8;
IndexNum[13] = 9;
IndexNum[14] = 7;

IndexNum[15] = 3;
IndexNum[16] = 1;
IndexNum[17] = 9;

IndexNum[18] = 3;
IndexNum[19] = 5;
IndexNum[20] = 7;

IndexNum[21] = 7;
IndexNum[22] = 3;
IndexNum[23] = 9;

for (auto& i : PosVertex) {
i.dif = fillColor;
i.rhw = 1.0f;
}
if(DrawPrimitiveIndexed2D(PosVertex, 10, IndexNum,24,DX_PRIMTYPE_TRIANGLELIST, DX_NONE_GRAPH, TRUE) != 0) return -1;
}
else {
if(DrawLine(PosVertex[0].pos.x, PosVertex[0].pos.y, PosVertex[1].pos.x, PosVertex[1].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[1].pos.x, PosVertex[1].pos.y, PosVertex[2].pos.x, PosVertex[2].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[2].pos.x, PosVertex[2].pos.y, PosVertex[3].pos.x, PosVertex[3].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[3].pos.x, PosVertex[3].pos.y, PosVertex[4].pos.x, PosVertex[4].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[4].pos.x, PosVertex[4].pos.y, PosVertex[5].pos.x, PosVertex[5].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[5].pos.x, PosVertex[5].pos.y, PosVertex[6].pos.x, PosVertex[6].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[6].pos.x, PosVertex[6].pos.y, PosVertex[7].pos.x, PosVertex[7].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[7].pos.x, PosVertex[7].pos.y, PosVertex[8].pos.x, PosVertex[8].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[8].pos.x, PosVertex[8].pos.y, PosVertex[9].pos.x, PosVertex[9].pos.y, color) != 0) return -1;
if(DrawLine(PosVertex[9].pos.x, PosVertex[9].pos.y, PosVertex[0].pos.x, PosVertex[0].pos.y, color) != 0) return -1;
}
return 0;
}



  • 最初のサンプルコード

DrawStar(Vec2(256, 64), Vec2(128, 144), Vec2(160, 320), Vec2(352, 320), Vec2(384, 144), Color(0, 0, 255), TRUE);

DrawStar(Vec2(256, 64), Vec2(128, 144), Vec2(160, 320), Vec2(352, 320), Vec2(384, 144), Color(255, 0, 0), FALSE);


解説

部分的に抜き出して解説していきます。

GetPositionBy4Point関数は2本の直線の交点の座標を割り出し、返す関数です。

こちらのサイトを参考にしました。

DrawStar関数のはじめの

    UINT r = color >> 16;

UINT g = color << 8;
UINT b = color << 16;
g = g >> 16;
b = b >> 16;
COLOR_U8 fillColor = GetColorU8(r, g, b, 225);

の部分ですが、描画色はほかの図形描画関数同様intで受け取っていますが、実際に使えるのはCOLOR_U8型です。なのでこのような計算をしています。

PosVertexの奇数番は直線同士の交点、偶数番は頂点部分です。

IndexNum[0] = 0;

IndexNum[1] = 1;
IndexNum[2] = 9;

IndexNum[3] = 2;
IndexNum[4] = 3;
IndexNum[5] = 1;

IndexNum[6] = 4;
IndexNum[7] = 5;
IndexNum[8] = 3;

IndexNum[9] = 6;
IndexNum[10] = 7;
IndexNum[11] = 5;

IndexNum[12] = 8;
IndexNum[13] = 9;
IndexNum[14] = 7;

IndexNum[15] = 3;
IndexNum[16] = 1;
IndexNum[17] = 9;

IndexNum[18] = 3;
IndexNum[19] = 5;
IndexNum[20] = 7;

IndexNum[21] = 7;
IndexNum[22] = 3;
IndexNum[23] = 9;

の部分は面張りをしています。詳しいことはよくわかりません。


最後に

始めて書いたこの記事ですがこんなテキトーでいいんでしょうかね(^^;

自分もこれ書いたのだいぶ前なので詳しいことはあまり覚えておらず・・・

アドベントカレンダーに飛び入り参戦させていただきました。

なんかあったらコメントしてくださいまし。

ソースコードは自由に使用してください。