切り出したドーナツ型の描画
Siv3D Advent Calender 2024 21日目の記事です
まずこの形をなんと呼ぶべきか
この形だ。なんと呼べばいいのか、正式名称がないのだ。
ドーナツ型を切り出した図形と呼べるが、そう思っている人ばかりではあるまい。
ただの円を切り出したものであれば「扇形」という立派な名前があるのだが、これは数学の定義上の扇形ではない。
「でも扇ってこういう形してるしドーナツ型の切り出しも扇形呼んでもよくない?」とは思う。
Siv3Dでの切り出したドーナツ型の描画
Siv3D切り出したドーナツ型を描画するのはCircle.drawPieメソッドでは実現できない。空隙を指定することはできないからだ。
しかし実際のところは分厚い弧を描く形を取ることで、そう苦労せず描画できる。
これにはCircle.drawArcメソッドを使う。
図形の塗りを描くのならそれで済むのだが、境界線を描きたい場合、rawPieやdrawArcの返り値はCircleなので、これにdrawFrameを使うと基準となる円の外周を描くだけになってしまう。
境界線を描きたい場合は以下に2通りになりそうだ。
- (A) Circle.arcAsPolygonメソッドで一旦Polygon型に変換し、drawFrameする。
- (B) 4本の線をそれぞれ直線と弧で描画する。
普通は(A)のやり方を取るだろう。線を図形にするのがポイントだ。
double angle1 = 0_deg;
double angle2 = 90_deg;
double line_thickness = 10;
circle.arcAsPolygon(angle1, angle2, 150, 0)..drawFrame(line_thickness, Palette::Orange);
(B)は地道に描画するのでそれぞれの線の色を変えることができる。
OffsetCircularで角度と距離を指定すれば特定位置からそれだけ離れた座標を取得できるので、意外とそこまで面倒ではない。
ちなみに弧の描画で内側と外側を同じ太さにしないときれいにならない。
double angle1 = 0_deg;
double angle2 = 90_deg;
double line_thickness = 10;
circle.drawArc(angle1, angle2, line_thickness / 2, line_thickness / 2, Palette::Green);
circle2.drawArc(angle1, angle2, line_thickness / 2, line_thickness / 2, Palette::Orange);
Line(OffsetCircular(circle.center, circle.r, angle1), OffsetCircular(circle.center, circle2.r, angle1)).draw(line_thickness,Palette::Orange);
Line(OffsetCircular(circle.center, circle.r, angle2), OffsetCircular(circle.center, circle2.r, angle2)).draw(line_thickness, Palette::Orange);
この図形の用途
かぼちゃの煮つけにも使えないことはないが、ゲーム等での用途はほぼパイメニュー(円状のメニュー)に絞られると思われる。
パイメニューについては公式でコードを出しているのでそちらも役に立つだろう。
手作りで実装する場合はきれいに見せるのにコツがある。
例えば4分割のメニューを作るとして、「87度+隙間3度で作ろう」とやると以下のようなものが出来上がって、メニューUIとしてはちょっと違うなという感じになる。
そのため一旦隙間のないように切り出しドーナツを敷き詰めてから、それぞれを少し散開させるようにするときれいに見えるだろう。
描線に影をつけたい場合、一旦レンダーテクスチャに完成形を作っておいて、そのテクスチャをdrawする方法が無難だと思うが、
場合によっては予め画像ファイルを作ったほうが楽かもしれない。