using System;
using System.Windows;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using MathNet.Numerics.LinearAlgebra;
namespace NDof3DManipulatorFK
{
///
/// MainWindow.xaml の相互作用ロジック
///
public partial class MainWindow : Window
{
# region Camera__Field
bool isCameraRotating;
Vector2 current, previous;
Matrix4 rotate;
float zoom;
//float wheelPrevious;
# endregion
# region Light__Field
Vector4 lightPosition;
Color4 lightAmbient;
Color4 lightDiffuse;
Color4 lightSpecular;
Color4 materialAmbient;
Color4 materialDiffuse;
Color4 materialSpecular;
float materialShininess;
# endregion
//glControlの起動時に実行される。
private void glControl_Load(object sender, EventArgs e)
{
GL.ClearColor(Color4.Black);
GL.Enable(EnableCap.DepthTest);
# region Camera_Initialize
this.isCameraRotating = false;
this.current = Vector2.Zero;
this.previous = Vector2.Zero;
this.rotate = Matrix4.Identity;
this.zoom = 1.0f;
//this.wheelPrevious = 0.0f;
# endregion
# region Light_Initialize
lightPosition = new Vector4(200.0f, 150f, 500.0f, 0.0f);
lightAmbient = new Color4(0.2f, 0.2f, 0.2f, 1.0f);
lightDiffuse = new Color4(0.7f, 0.7f, 0.7f, 1.0f);
lightSpecular = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
materialAmbient = new Color4(0.24725f, 0.1995f, 0.0225f, 1.0f);
materialDiffuse = new Color4(0.75164f, 0.60648f, 0.22648f, 1.0f);
materialSpecular = new Color4(0.628281f, 0.555802f, 0.366065f, 1.0f);
materialShininess = 51.4f;
//裏面削除、反時計回りが表でカリング
GL.Enable(EnableCap.CullFace);
GL.CullFace(CullFaceMode.Back);
GL.FrontFace(FrontFaceDirection.Ccw);
//ライティングON Light0を有効化
//GL.Enable(EnableCap.Lighting);
//GL.Enable(EnableCap.Light0);
//法線の正規化
GL.Enable(EnableCap.Normalize);
# endregion
}
//glControlのサイズ変更時に実行される。
private void glControl_Resize(object sender, EventArgs e)
{
GL.Viewport(0, 0, glControl.Size.Width, glControl.Size.Height);
GL.MatrixMode(MatrixMode.Projection);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)glControl.Size.Width / (float)glControl.Size.Height, 1.0f, 64.0f);
GL.LoadMatrix(ref projection);
}
//glControlの描画時に実行される。
private void glControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
glControl_Update();
}
// glControlの再描画のハブ
private void glControl_Update()
{
glControl_draw();
}
public Vector Cross(Vector vector1, Vector vector2)
{
//外積
return Vector.Build.DenseOfArray(new double[]{
vector1[1] * vector2[2] - vector1[2]*vector2[1],
vector1[2] * vector2[0] - vector1[0]*vector2[2],
vector1[0] * vector2[1] - vector1[1]*vector2[0]});
}
//glControlの描画時に実行される。
private void glControl_draw()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
#region TransFormationMatrix
Matrix4 modelView = Matrix4.LookAt(Vector3.UnitZ * 10 / zoom, Vector3.Zero, Vector3.UnitY);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelView);
GL.MultMatrix(ref rotate);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4 / zoom, (float)this.Width / (float)this.Height, 1.0f, 64.0f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
#endregion
# region Lighting
GL.Light(LightName.Light0, LightParameter.Position, lightPosition);
GL.Light(LightName.Light0, LightParameter.Ambient, lightAmbient);
GL.Light(LightName.Light0, LightParameter.Diffuse, lightDiffuse);
GL.Light(LightName.Light0, LightParameter.Specular, lightSpecular);
GL.Material(MaterialFace.Front, MaterialParameter.Ambient, materialAmbient);
GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, materialDiffuse);
GL.Material(MaterialFace.Front, MaterialParameter.Specular, materialSpecular);
GL.Material(MaterialFace.Front, MaterialParameter.Shininess, materialShininess);
#endregion
#region AXES_PLOT
GL.Begin(BeginMode.LineLoop);
GL.LineWidth(3.0f);
GL.Color4(Color4.White);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 1, 0);
GL.Color4(Color4.White);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 0, 1);
GL.Color4(Color4.White);
GL.Vertex3(0, 0, 0);
GL.Vertex3(1, 0, 0);
GL.End();
#endregion
#region Robot_Arm
GL.Begin(BeginMode.Lines);
GL.LineWidth(13.0f);
GL.Color4(Color4.Red);
Color4[] colors = new Color4[]{
Color4.Red, Color4.Blue,Color4.Green,
Color4.Red, Color4.Blue,Color4.Green,
Color4.Red, Color4.Blue,Color4.Green
};
var Vn = Vector.Build.DenseOfArray(new double[3] { 1, 0, 0 });
var ex = Vector.Build.DenseOfArray(new double[3] { 1, 0, 0 });
var V1 = Vector.Build.DenseOfArray(new double[3] { 1, 1, 1 });
var V2 = Vector.Build.DenseOfArray(new double[3] { 1, 1, 1 });
var V12 = Vector.Build.DenseOfArray(new double[3] { 1, 1, 1 });
var Vp = Vector.Build.DenseOfArray(new double[3] { 1, 1, 1 });
for (int i = 1; i < this.Pi.GetLength(0); i++)
{
GL.Color4(colors[i]);
GL.Vertex3(this.Pi[i - 1, 0], this.Pi[i - 1, 1], this.Pi[i - 1, 2]);
GL.Vertex3(this.Pi[i, 0], this.Pi[i, 1], this.Pi[i, 2]);
}
for (int i = 1; i < this.Pi.GetLength(0); i++)
{
GL.Color4(colors[i]);
V1 = Vector.Build.DenseOfArray(new double[3] { this.Pi[i - 1, 0], this.Pi[i - 1, 1], this.Pi[i - 1, 2] });
V2 = Vector.Build.DenseOfArray(new double[3] { this.Pi[i, 0], this.Pi[i, 1], this.Pi[i, 2] });
// 単位ベクトル*0.2
V12 = 0.2 * (V2 - V1);
// 単位法線ベクトル
Vn = Cross(V12, ex);
Vn = Vn / Vn.L2Norm() * V12.L2Norm();
// ターゲット
Vp = V1 + V12 + Vn;
// 法線ベクトル
GL.Vertex3((V12 + V1).ToArray());
GL.Vertex3(Vp.ToArray());
// 斜めベクトル
GL.Vertex3((V1).ToArray());
GL.Vertex3(Vp.ToArray());
GL.Vertex3((V2).ToArray());
GL.Vertex3(Vp.ToArray());
}
GL.End();
#endregion
#region Robot_TargetPoint
GL.Begin(BeginMode.Lines);
GL.LineWidth(13.0f);
GL.Color4(Color4.Gray);
GL.Vertex3(this.Pi[0, 0], this.Pi[0, 1], this.Pi[0, 2]);
GL.Vertex3(this.Pg[0], this.Pg[1], this.Pg[2]);
GL.End();
# endregion
# region Draw_Grid
int J = 5;
GL.Begin(BeginMode.Lines);
GL.Color4(0.3, 0.3, 0.3, 0.3);
GL.LineWidth(0.1f);
for (int i = -J; i <= J; i++)
{
GL.Vertex3(-J, i, 0);
GL.Vertex3(J, i, 0);
GL.Vertex3(i, -J, 0);
GL.Vertex3(i, J, 0);
}
GL.End();
# endregion
glControl.SwapBuffers();
}
///
/// マウスイベント関連
///
///
///
private void glControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
this.isCameraRotating = true;
this.current = new Vector2(e.X, e.Y);
}
// 左マウスクリック
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
}
}
private void glControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
this.isCameraRotating = false;
this.previous = Vector2.Zero;
}
}
private void glControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (this.isCameraRotating)
{
this.previous = this.current;
this.current = new Vector2(e.X, e.Y);
Vector2 delta = current - previous; // 移動方向ベクトル
delta /= (float)Math.Sqrt(this.Width * this.Width + this.Height * this.Height); //対角線長さ
float length = delta.Length;
if (length > 0.0)
{
float rad = length * MathHelper.Pi;
float theta = (float)Math.Sin(rad) / length;
Quaternion after = new Quaternion(delta.Y * theta, delta.X * theta, 0.0f, (float)Math.Cos(rad));
rotate = rotate * Matrix4.Rotate(after);
}
glControl_Update();
}
} // glControl_MouseUP
private void glControl_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
{
float delta = (float)e.Delta;
zoom *= (float)Math.Pow(1.1, delta / 120.0);
if (zoom > 2.0f) zoom = 2.0f;
if (zoom < 0.5f) zoom = 0.5f;
glControl_Update();
}
}
}