OpenTKで立方体を描く初歩を復習するための記録

何かと初歩的なこともすぐ忘れてしまうので、OpenTKで立方体を描いたときのコードを記録しておく。
イメージは以下のようなものが描画される。

f:id:willwealth:20200831131416j:plain
OpenTKで立方体

コンパイルのために以下の応答ファイル my.rsp を用意しておく。

#
# コンパイルのための応答ファイル
#   csc `@my.rsp   <target file.cs>
#     ※ powershellでは @ は "`" でエスケープしなければならない。
/reference:OpenTK.dll
/reference:OpenTK.GLControl.dll

ソースコードは以下の通り。

//
//  cc `@my.rsp test1.cs 
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace FormsOpenTKTest1
{
    public class Form1 : Form
    {
        /// <summary>
        /// 必要なデザイナー変数です。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        /// <param name="disposing">マネージ リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows フォーム デザイナーで生成されたコード

        /// <summary>
        /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディターで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.glControl = new OpenTK.GLControl();
            this.SuspendLayout();
            // 
            // glControl
            // 
            //this.glControl.BackColor = System.Drawing.Color.Black;
            this.glControl.BackColor = System.Drawing.Color.Yellow;

            //this.glControl.Location = new System.Drawing.Point(0, 0);
            this.glControl.Location = new System.Drawing.Point(10, 10);

            this.glControl.Margin = new System.Windows.Forms.Padding(7, 6, 7, 6);
            this.glControl.Name = "glControl";
            //this.glControl.Size = new System.Drawing.Size(1696, 603);
            this.glControl.Size = new System.Drawing.Size(1200, 1000);

            this.glControl.TabIndex = 0;
            this.glControl.VSync = false;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 24F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            //this.ClientSize = new System.Drawing.Size(1741, 647);
            this.ClientSize = new System.Drawing.Size(1300, 1300);

            this.Controls.Add(this.glControl);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion
        private OpenTK.GLControl glControl;

        public Form1()
        {
            InitializeComponent();
            //イベントの追加 
            glControl.Load += glControl_Load;
            glControl.Paint += glControl_Paint;
            //glControl.Resize += glControl_Resize;
        }

        private void glControl_Load(object sender, EventArgs e)
        {
            // 背景色の設定
            GL.ClearColor(glControl.BackColor);

            // ビューポートの設定
            GL.Viewport(0, 0, glControl.Width, glControl.Height);

            // 視体積の設定
            GL.MatrixMode(MatrixMode.Projection);
            //GL.MatrixMode(MatrixMode.Modelview);

            Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, glControl.AspectRatio, 0.2f, 5);
            GL.LoadMatrix(ref proj);

            // 視界の設定
            GL.MatrixMode(MatrixMode.Modelview);
            //Matrix4 look = Matrix4.LookAt(Vector3.One, new Vector3(0, 0, 0.75f), Vector3.UnitZ);
            Matrix4 look = Matrix4.LookAt(new Vector3(1, 1, 1.75f), new Vector3(0, 0, 0.75f), Vector3.UnitZ);

            GL.LoadMatrix(ref look);

            // デプスバッファの使用
            GL.Enable(EnableCap.DepthTest);

            // 光源の使用
            GL.Enable(EnableCap.Lighting);

            float[] position = new float[] { 1.0f, 2.0f, 3.0f, 0.0f };
            GL.Light(LightName.Light0, LightParameter.Position, position);
            GL.Enable(EnableCap.Light0);
        }

        private void glControl_Resize(object sender, EventArgs e)
        {
            // ビューポートの設定
            GL.Viewport(0, 0, glControl.Width, glControl.Height);
        }

        private void glControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //GL.Clear(ClearBufferMask.ColorBufferBit);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, Color4.Blue);

            //tube(1, 0.1f, 0.1f);
            cube( 0.3, -0.3, 0.6);

            glControl.SwapBuffers();
//    this.pictureBox1.Image = image;
//    image.Save(saveFileDialog1.FileName,ImageFormat.Jpeg);
//
//            this.glControl.

        }

        void cube(double x, double y, double z)
        {
            //double w = 1.0, h = 1.0, d = 1.0;
            double w = 0.2, h = 0.2, d = 0.2;

            GL.PushMatrix();

            GL.Begin(PrimitiveType.TriangleStrip); // right
	    {
                GL.Normal3( Vector3.UnitX);
                GL.Vertex3( x+w, y+h, z-d);
                GL.Vertex3( x+w, y+h, z+d);
                GL.Vertex3( x+w, y-h, z-d);
                GL.Vertex3( x+w, y-h, z+d);
	    }
            GL.End();
            GL.Begin(PrimitiveType.TriangleStrip); // left
	    {
                GL.Normal3(-Vector3.UnitX);
                GL.Vertex3( x-w, y-h, z-d);
                GL.Vertex3( x-w, y-h, z+d);
                GL.Vertex3( x-w, y+h, z-d);
                GL.Vertex3( x-w, y+h, z+d);
	    }
            GL.End();
            GL.Begin(PrimitiveType.TriangleStrip); // up
	    {
                GL.Normal3( Vector3.UnitY);
                GL.Vertex3( x+w, y+h, z-d);
                GL.Vertex3( x-w, y+h, z-d);
                GL.Vertex3( x+w, y+h, z+d);
                GL.Vertex3( x-w, y+h, z+d);
	    }
            GL.End();
            GL.Begin(PrimitiveType.TriangleStrip); // down
	    {
                GL.Normal3(-Vector3.UnitY);
                GL.Vertex3( x-w, y-h, z+d);
                GL.Vertex3( x-w, y-h, z-d);
                GL.Vertex3( x+w, y-h, z+d);
                GL.Vertex3( x+w, y-h, z-d);
	    }
            GL.End();
            GL.Begin(PrimitiveType.TriangleStrip); // front
	    {
                GL.Normal3( Vector3.UnitZ);
                GL.Vertex3( x+w, y+h, z+d);
                GL.Vertex3( x-w, y+h, z+d);
                GL.Vertex3( x+w, y-h, z+d);
                GL.Vertex3( x-w, y-h, z+d);
	    }
            GL.End();
            GL.Begin(PrimitiveType.TriangleStrip); // back
	    {
                GL.Normal3(-Vector3.UnitZ);
                GL.Vertex3( x+w, y-h, z-d);
                GL.Vertex3( x-w, y-h, z-d);
                GL.Vertex3( x+w, y+h, z-d);
                GL.Vertex3( x-w, y+h, z-d);
	    }
            GL.End();

            GL.PopMatrix();
        }

        void tube(float length, float radius1, float radius2)
        {
            float rx, ry, theta;

            GL.PushMatrix();
            GL.Begin(PrimitiveType.TriangleStrip);
            //GL.Normal3(Vector3.One);
            //for (int deg = 0; deg <= 360; deg = deg + 3)
            for (int deg = 0; deg <= 360; deg = deg + 36)
            {
                theta = (float)Math.PI * deg / 180;
                //rx = (float)Math.Cos((float)Math.PI * deg / 180);
                //ry = (float)Math.Sin((float)Math.PI * deg / 180);
                rx = (float)Math.Cos(theta);
                ry = (float)Math.Sin(theta);
                GL.Normal3(rx, ry, 0.0f);

                GL.Vertex3(rx * radius2, ry * radius2, length / 2 + 0.5);
                GL.Vertex3(rx * radius1, ry * radius1, -length / 2 + 0.5);

            }
            GL.End();
            GL.PopMatrix();

        }
    }

    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

以上