これまで立方体の移動と描画をやってきましたが、今回は別の図形=球の描画をやってみることにします。三角形を並べて球を描きます。X軸、Y軸、Z軸で45°ずつ切ったときにできる球面の点を結んで三角形をつくります。
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 74 75 76 77 78 79 80 81 82 83 84 85 |
public partial class Form1 : Form { // Math.Cos()とかSin()と書くのが面倒なので・・・ float Cos(double d) { return (float)Math.Cos(d); } float Sin(double d) { return (float)Math.Sin(d); } private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // 視点を変更する SetSight(EyeX, EyeY, EyeZ); // 球を描画 DrawBall(1, X, Y, Z, RotateX, RotateY, RotateZ); Lighting(); glControl.SwapBuffers(); } /// <summary> /// 球を描画する /// </summary> /// <param name="radius">半径</param> /// <param name="x">X座標</param> /// <param name="y">Y座標</param> /// <param name="z">Z座標</param> /// <param name="rotateX">X座標を中心とした回転角度</param> /// <param name="rotateY">Y座標を中心とした回転角度</param> /// <param name="rotateZ">Z座標を中心とした回転角度</param> private void DrawBall(double radius, double x, double y, double z, double rotateX, double rotateY, double rotateZ) { 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); DrawBall((float)radius); } GL.PopMatrix(); } void DrawBall(float radius) { int count = 2; double a = Math.PI / count / 2; double b = Math.PI / count / 2; GL.Begin(BeginMode.TriangleStrip); { for(int k = -count + 1; k <= count; k++) { if(k == -1) GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.Blue); if(k == 0) GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.LightGreen); if(k == 1) GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.Red); if(k == 2) GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.LightPink); for(int i = 0; i <= count * 4; i++) { Vector3 vec1 = new Vector3(radius * Cos(b * k) * Cos(a * i), radius * Cos(b * k) * Sin(a * i), radius * Sin(b * k)); GL.Normal3(vec1); GL.Vertex3(vec1); Vector3 vec2 = new Vector3(radius * Cos(b * (k - 1)) * Cos(a * i), radius * Cos(b * (k - 1)) * Sin(a * i), radius * Sin(b * (k - 1))); GL.Normal3(vec2); GL.Vertex3(vec2); } } } GL.End(); } } |
わかりやすくするために各列で色を変えています。
X軸で90度回転させた状態です。
全部同じ色にするとこんな感じです。ややゴツゴツ感があります。
もう少し大きな数値に変えてみます。8に変更するとこうなります。これなら球に見えます。
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 { void DrawBall(float radius) { // int count = 2; int count = 8; double a = Math.PI / count / 2; double b = Math.PI / count / 2; GL.Begin(BeginMode.TriangleStrip); { for(int k = -count + 1; k <= count; k++) { GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.Yellow); for(int i = 0; i <= count * 4; i++) { Vector3 vec1 = new Vector3(radius * Cos(b * k) * Cos(a * i), radius * Cos(b * k) * Sin(a * i), radius * Sin(b * k)); GL.Normal3(vec1); GL.Vertex3(vec1); Vector3 vec2 = new Vector3(radius * Cos(b * (k - 1)) * Cos(a * i), radius * Cos(b * (k - 1)) * Sin(a * i), radius * Sin(b * (k - 1))); GL.Normal3(vec2); GL.Vertex3(vec2); } } } GL.End(); } } |
for(int i = 0; i <= count * 4; i++)としていますが、なぜ4倍するのでしょうか?
試しにfor(int i = 0; i <= count ; i++)に変更しましたが、球の1/4しか描画されませんでした。
Cos(a * i),Sin(a * i)のa * iが2πを超えると、頂点が重複するような気がするのですが、、、
理由を教えていただけたらありがたいです。
countの意味ですが、これは球の上半分を何分割するかという意味です。最初の例では2になっているので90度(π/2ラジアン)を2分割しています。
下半分も描画しないといけないので外側のループではfor(int k = -count + 1; k <= count; k++)としています。
次に分割された部分に三角形を配置していくのですが、この場合は360度(2πラジアン)を分割して考えないといけません。そのため4倍する必要があるのです。
ご回答ありがとうございます。
すいません、まだあまり理解できませんでした。
vec1,vec2で描画する三角形の頂点を決めているのですよね?
例えば、k=0,i=0の時のvec1の座標と、k=0,i=8の時のvec1の座標はk=0,i=16のvec1の座標は同じ座標になってしまい、同じ三角形ができませんか?
もしかすると、とても簡単な質問をしているのかもしれませんが、、、
よろしければ、ご回答よろしくお願いいたしします。
BeginMode.TriangleStripで描画しているので、最初の座標と最後から2番目の座標、2番目と最後の座標が同じになるようにしておかないと複数の三角形がひとつに繋がりません。
それでこのようなコードになっています。