ほげほげ草 -3ページ目

OpenGL with C# (15) : 曲面の描画 [1] - 円

お久しぶりです。


いろいろありまして,前回からかなり間があいてしまいました。


さて,予定通り"OpenGL 球" で検索されてくる方のために,今回から曲面に関して書いていこうと思います。


そんなわけで,今回はまず円を書いてみましょう。


なんで,最初から球を書かないのかですと?


私は割と焦らす派だからですw


あと,基本原理を分かっていた方が応用が利くのでいいですよ。


そんなわけで進めましょう。


とりあえずいつものごとく型枠だけ作ります。


01 using System;
02 using System.Windows.Forms;
03 using System.Drawing;
04 
05 using OpenTK;
06 using OpenTK.Graphics.OpenGL;
07 
08 namespace BlogOpenGL
09 {
10   public partial class Form1 : Form
11   {
12     public Form1()
13     {
14       InitializeComponent();
15     }
16 
17     private void glControl_Load(object sender, EventArgs e)
18     {
19       // 背景色の設定
20       GL.ClearColor(glControl.BackColor);
21 
22       // Projection の設定
23       SetProjection();
24 
25       // 視界の設定
26       Matrix4 look = Matrix4.LookAt(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY);
27 
28       GL.LoadMatrix(ref look);
29     }
30 
31     private void glControl_Paint(object sender, PaintEventArgs e)
32     {
33       GL.Clear(ClearBufferMask.ColorBufferBit);
34 
35       DrawCircle();
36 
37       glControl.SwapBuffers();
38     }
39 
40     private void glControl_Resize(object sender, EventArgs e)
41     {
42       // Projection の設定
43       SetProjection();
44 
45       // 再描画
46       glControl.Refresh();
47     }
48 
49     void SetProjection()
50     {
51       // ビューポートの設定
52       GL.Viewport(0, 0, glControl.Width, glControl.Height);
53 
54       // 視体積の設定
55       GL.MatrixMode(MatrixMode.Projection);
56       float h = 2.0f, w = h * glControl.AspectRatio;
57       Matrix4 proj = Matrix4.CreateOrthographic(w, h, 0.1f, 3.0f);
58       GL.LoadMatrix(ref proj);
59 
60       // MatrixMode を元に戻す
61       GL.MatrixMode(MatrixMode.Modelview);
62     }
63 
64     void DrawCircle()
65     {
66     }
67   }
68 }

DrawCircle に円を描画する処理を追加します。


ここから数学の時間です。


(x, y) = (r cosθ, r sinθ) (0 ≤ θ < 2π) が xy 平面で原点中心,半径 r の円上の点を表すということを覚えていますでしょうか。


こんな感じの図でしたね。


ほげほげ草

θx 軸から測った角度になります。


曲面を描画するときはだいたいこの三角関数を使うので,OpenGL を使う際は好き嫌いせずに使ってみましょう。


さて,円を描画する話に戻ります。


いろいろ描画方法はあると思いますが,ここでは扇形を合わせて描画することを考えましょう。


扇形とは言いましたが,OpenGL では扇形が描画できないので,三角形を合わせて書くことになります。


つまるところ正 n 角形を描画するわけです。


ほげほげ草

n がおおきくなれば円に近付くというのはよく知られていますね。


通常,三角形を書くときは TriangleStrip を使うのがよいのですが,円の場合は適したものがあります。


ここ に示した TriangleFan というやつです。


まさに先ほどの図の三角形バージョンそのままですね。


さて三角形何個で書くというのを変更できた方がいいので,n 個としておきましょう。


1つ当たりの三角形の角度は 360° / n (= 2π / n) ですね。


そんなわけでやってみましょう。


10   public partial class Form1 : Form
11   {
31     private void glControl_Paint(object sender, PaintEventArgs e)
32     {
33       GL.Clear(ClearBufferMask.ColorBufferBit);
34 
35       DrawCircle(6);
36 
37       glControl.SwapBuffers();
38     }
39 
64     void DrawCircle(int n)
65     {
66       double delta = 2.0 * Math.PI / (double)n;
67 
68       GL.Begin(BeginMode.TriangleFan);
69       {
70         GL.Vertex3(Vector3.Zero);
71         for (int i = 0; i <= n; i++)
72         {
73           double x = Math.Cos(delta * i);
74           double y = Math.Sin(delta * i);
75           GL.Vertex3(x, y, 0.0);
76         }
77       }
78       GL.End();
79     }
80   }

n に 6 を渡すとちゃんと正六角形が表示できました。


71 行目で i <= n としていることに注意してください。


こうしないと最後の三角形が描画されませんね。


n の値を大きくして,円が描画できることを確認してください。


さて,今回はここまでですが,ここから新システムです。


レベルアップのための課題です。


気が向いたらやってみてください。


【課題】下に示すような半円を描画しましょう。



ほげほげ草