傾斜した画像を表示させます。
まずどれだけ平行移動するか、回転させるかのプロパティを作成します。値が変更されたらチェックボックスに表示される文字列も同時に変更することにしました。
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 |
public partial class Form1 : Form { double x0 = 0; double X { get { return x0; } set { x0 = (double)Math.Round(value, 2, MidpointRounding.AwayFromZero); string str = String.Format("平行移動 X方向 {0}", x0); checkBoxTranslateX.Text = str; } } double y0 = 0; double Y { get { return y0; } set { y0 = (double) Math.Round(value, 2, MidpointRounding.AwayFromZero); string str = String.Format("平行移動 Y方向 {0}", y0); checkBoxTranslateY.Text = str; } } double z0 = 0; double Z { get { return z0; } set { z0 = (double)Math.Round(value, 2, MidpointRounding.AwayFromZero); string str = String.Format("平行移動 Z方向 {0}", z0); checkBoxTranslateZ.Text = str; } } double rx0 = 0; double RotateX { get { return rx0; } set { if(value < 0) value += 360; rx0 = value % 360; string str = String.Format("回転X軸 {0}°", rx0); checkBoxRotateX.Text = str; } } double ry0 = 0; double RotateY { get { return ry0; } set { if(value< 0) value += 360; ry0 = value % 360; string str = String.Format("回転Y軸 {0}°", ry0); checkBoxRotateY.Text = str; } } double rz0 = 0; double RotateZ { get { return rz0; } set { if(value < 0) value += 360; rz0 = value % 360; string str = String.Format("回転Y軸 {0}°", rz0); checkBoxRotateZ.Text = str; } } } |
キー操作で先述のプロパティを変化させます。↑キーと→キーが押されたら増加、↓キーと←キーが押されたら減少ですが、X軸で回転するときは↑キーが押されたら向こう側に倒れるように回転させたいのと、Z軸方向に移動する場合は↑キーが押されたら遠ざかるようにしたいので、その部分だけ符号を逆にしています。
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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
public partial class Form1 : Form { [System.Security.Permissions.UIPermission( System.Security.Permissions.SecurityAction.Demand, Window = System.Security.Permissions.UIPermissionWindow.AllWindows)] protected override bool ProcessDialogKey(Keys keyData) { //キーの本来の処理を //させたくないときは、trueを返す if((keyData & Keys.KeyCode) == Keys.Left) { OnLeft(); return true; } else if((keyData & Keys.KeyCode) == Keys.Right) { OnRight(); return true; } else if((keyData & Keys.KeyCode) == Keys.Up) { OnUp(); return true; } else if((keyData & Keys.KeyCode) == Keys.Down) { OnDoun(); return true; } return base.ProcessDialogKey(keyData); } void OnRight() { if(checkBoxTranslateX.Checked) X += 0.1; if(checkBoxTranslateY.Checked) Y += 0.1; if(checkBoxTranslateZ.Checked) Z += 0.1; if(checkBoxRotateX.Checked) RotateX += 1; if(checkBoxRotateY.Checked) RotateY += 1; if(checkBoxRotateZ.Checked) RotateZ += 1; glControl.Refresh(); } void OnLeft() { if(checkBoxTranslateX.Checked) X -= 0.1; if(checkBoxTranslateY.Checked) Y -= 0.1; if(checkBoxTranslateZ.Checked) Z -= 0.1; if(checkBoxRotateX.Checked) RotateX -= 1; if(checkBoxRotateY.Checked) RotateY -= 1; if(checkBoxRotateZ.Checked) RotateZ -= 1; glControl.Refresh(); } // Upが押されたときにX軸で回転させるときは向こう側に倒したい // Z軸方向に平行移動させるときは遠ざけたいので符号を逆にしている void OnUp() { if(checkBoxTranslateX.Checked) X += 0.1; if(checkBoxTranslateY.Checked) Y += 0.1; if(checkBoxTranslateZ.Checked) Z -= 0.1; if(checkBoxRotateX.Checked) RotateX -= 1; if(checkBoxRotateY.Checked) RotateY += 1; if(checkBoxRotateZ.Checked) RotateZ -= 1; glControl.Refresh(); } void OnDoun() { if(checkBoxTranslateX.Checked) X -= 0.1; if(checkBoxTranslateY.Checked) Y -= 0.1; if(checkBoxTranslateZ.Checked) Z += 0.1; if(checkBoxRotateX.Checked) RotateX += 1; if(checkBoxRotateY.Checked) RotateY -= 1; if(checkBoxRotateZ.Checked) RotateZ += 1; glControl.Refresh(); } } |
視界の設定は以下のとおりです。コントロールがロードされたときだけ視界の設定を行ないます(視界は変更しない)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { /// <summary> /// コントロールがロードされたら初期化をする /// </summary> private void glControlEx1_Load(object sender, EventArgs e) { GL.ClearColor(glControl.BackColor); SetProjection(); // デプスバッファの使用 GL.Enable(EnableCap.DepthTest); // 視界の設定 Vector3 eye = new Vector3(0, 0, 2); Matrix4 look = Matrix4.LookAt(eye, Vector3.Zero, Vector3.UnitY); GL.LoadMatrix(ref look); glControl.Refresh(); } } |
画像読み込みがクリックされたら画像ファイルを読み込みます。そして読み込まれた画像ファイルのBitmapを保存しておきます。CreateTextureメソッドがどのようなものかは
を参照してください。
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 |
public partial class Form1 : Form { Bitmap _bitmap = null; Bitmap Bitmap { get{ return _bitmap; } set { if(_bitmap != null) _bitmap.Dispose(); _bitmap = value; } } private void buttonLoadImage_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "画像ファイル(*.bmp)|*.bmp|画像ファイル(*.jpg)|*.jpg|画像ファイル(*.png)|*.png|すべてのファイル|*.*"; if(dialog.ShowDialog() == DialogResult.OK) { Bitmap bitmap = null; try { bitmap = new Bitmap(dialog.FileName); // CreateTextureメソッドに渡すBitmapはPixelFormat.Format24bppRgbでないといけないので変換する if(bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) { Bitmap bitmap1 = bitmap; bitmap = new Bitmap(bitmap1.Width, bitmap1.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(bitmap1, new Point(0, 0)); g.Dispose(); bitmap1.Dispose(); } CreateTexture(bitmap); Bitmap = bitmap; glControl.Refresh(); } catch { MessageBox.Show("例外が発生しました!"); } } dialog.Dispose(); } } |
glControl.Refresh()が実行されたときにBitmapプロパティがnullでない場合はこれを表示します。
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 |
public partial class Form1 : Form { private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); if(Bitmap == null) { glControl.SwapBuffers(); return; } int w = Bitmap.Width; int h = Bitmap.Height; double a = (double)h / w; GL.PushMatrix(); { GL.Translate(new Vector3d(X, Y, Z)); GL.Rotate(RotateX, new Vector3d(1, 0, 0)); GL.Rotate(RotateY, new Vector3d(0, 1, 0)); GL.Rotate(RotateZ, new Vector3d(0, 0, 1)); Vector3d LeftTop = new Vector3d(-1, 1 * a, 0.0); Vector3d LeftBottom = new Vector3d(-1, -1 * a, 0.0); Vector3d RightTop = new Vector3d( 1, 1 * a, 0.0); Vector3d RightBottom = new Vector3d( 1, -1 * a, 0.0); GL.Begin(BeginMode.Quads); { GL.TexCoord2(0, 0); GL.Vertex3(LeftTop); GL.TexCoord2(0, 1); GL.Vertex3(LeftBottom); GL.TexCoord2(1, 1); GL.Vertex3(RightBottom); GL.TexCoord2(1, 0); GL.Vertex3(RightTop); } GL.End(); } GL.PopMatrix(); glControl.SwapBuffers(); } } |
画像を保存するときは以下の処理をおこないます。自作メソッド ToBitmapはglControlに描画されているものを保存するためのものです。
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 |
public partial class Form1 : Form { private void buttonSaveImage_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); if(dialog.ShowDialog() == DialogResult.OK) { Bitmap bitmap = ToBitmap(); if(bitmap != null) { bitmap.Save(dialog.FileName); bitmap.Dispose(); } } dialog.Dispose(); } public Bitmap ToBitmap() { glControl.Refresh(); Bitmap bmp = null; try { bmp = new Bitmap(glControl.Width, glControl.Height); } catch { return null; } var bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); GL.ReadPixels(0, 0, glControl.Width, glControl.Height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0); bmp.UnlockBits(bmpData); bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); return bmp; } } |