立方体だけでなく円錐やパイプの描画をやってみます。
円錐を描画する自作メソッド DrawCone(double radius, double height)は底面の半径と円錐の高さを指定します。底面と側面をそれぞれBeginMode.TriangleFanをつかって描画します。原点が底面の中心で頂点の座標は(0,0,height)になります。側面の法線は外積を使って求めています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
public partial class Form1 : Form { private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // 視点を変更する SetSight(EyeX, EyeY, EyeZ); GL.PushMatrix(); { GL.Translate(X, Y, Z); GL.Rotate(RotateX, 1, 0, 0); GL.Rotate(RotateY, 0, 1, 0); GL.Rotate(RotateZ, 0, 0, 1); DrawCone(1, 2); } GL.PopMatrix(); Lighting(); glControl.SwapBuffers(); } private void DrawCone(double radius, double height) { GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.Yellow); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.Normalize); // 底面 int count = 16; GL.Begin(BeginMode.TriangleFan); { GL.Normal3(-Vector3.UnitZ); GL.Vertex3(0, 0, 0.01); for(int i = 0; i <= count; i++) { double rad = GetRad(360f / count * i); double sin = Sin(rad); double cos = Cos(rad); GL.Vertex3(radius * cos, radius * sin, 0); } } GL.End(); GL.Begin(BeginMode.TriangleFan); { GL.Vertex3(0, 0, height); for(int i = 0; i <= count; i++) { double rad = GetRad(360f / count * i); double sin = Sin(rad); double cos = Cos(rad); // 1度だけ足して外積をとる。これが法線 double rad2 = GetRad(360f / count * i + 1); double sin2 = Sin(rad2); double cos2 = Cos(rad2); Vector3 v1 = new Vector3((float)cos, (float)sin, -(float)height); Vector3 v2 = new Vector3((float)cos2, (float)sin2, -(float)height); GL.Normal3(Vector3.Normalize(Vector3.Cross(v1, v2))); GL.Vertex3(radius * cos, radius * sin, 0); } } GL.End(); } } |
あとパイプも描画してみましょう。自作メソッド DrawPipe(double radius, double length)は内径と長さを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public partial class Form1 : Form { private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // 視点を変更する SetSight(EyeX, EyeY, EyeZ); GL.PushMatrix(); { GL.Translate(X, Y, Z); GL.Rotate(RotateX, 1, 0, 0); GL.Rotate(RotateY, 0, 1, 0); GL.Rotate(RotateZ, 0, 0, 1); DrawPipe(0.5, 2); } GL.PopMatrix(); Lighting(); glControl.SwapBuffers(); } private void DrawPipe(double radius, double length) { GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.Yellow); int count = 64; for(int k = 0; k <= count; k++) { double rad1 = GetRad(360f / count * k); double sin1 = Sin(rad1); double cos1 = Cos(rad1); double rad2 = GetRad(360f / count * (k + 1)); double sin2 = Sin(rad2); double cos2 = Cos(rad2); GL.Begin(BeginMode.Quads); { GL.Normal3(new Vector3((float)cos1, (float)sin1, 0)); GL.Vertex3(radius * cos1, radius * sin1, length * 0.5); GL.Vertex3(radius * cos1, radius * sin1, -length * 0.5); GL.Normal3(new Vector3((float)cos2, (float)sin2, 0)); GL.Vertex3(radius * cos2, radius * sin2, -length * 0.5); GL.Vertex3(radius * cos2, radius * sin2, length * 0.5); } GL.End(); } } } |
ふたつのパイプを組み合わせてこんな図形も描画できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class Form1 : Form { private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // 視点を変更する SetSight(EyeX, EyeY, EyeZ); GL.PushMatrix(); { GL.Translate(X, Y, Z); GL.Rotate(RotateX, 1, 0, 0); GL.Rotate(RotateY, 0, 1, 0); GL.Rotate(RotateZ, 0, 0, 1); GL.Rotate(90, 0, 1, 0); DrawPipe(0.5, 2); GL.Rotate(90, 1, 0, 0); DrawPipe(0.5, 2); } GL.PopMatrix(); Lighting(); glControl.SwapBuffers(); } } |