Я использовал учебник по http://viewport3d.com/trackball.htm для программирования трекбола. У меня вычисляется ось и угол, но поскольку я только начинаю работать с OpenTK и OpenGL, я не знаю, как применить поворот к объекту. Любая помощь, пожалуйста?OpenTK - Как повернуть объект по заданному углу
код состоит из нескольких файлов, вот два наиболее важных.
Trackball.cs
using System;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace _038trackball
{
public partial class Form1
{
#region Camera attributes
/// <summary>
/// Current camera position.
/// </summary>
private Vector3 eye = new Vector3(0.0f, 0.0f, 10.0f);
/// <summary>
/// Current point to look at.
/// </summary>
private Vector3 pointAt = Vector3.Zero;
/// <summary>
/// Current "up" vector.
/// </summary>
private Vector3 up = Vector3.UnitY;
/// <summary>
/// Vertical field-of-view angle in radians.
/// </summary>
private float fov = 1.0f;
/// <summary>
/// Camera's far point.
/// </summary>
private float far = 200.0f;
#endregion
protected Vector3d v1 = new Vector3d(0, 0, 0);
protected Vector3d v2 = new Vector3d(0, 0, 0);
protected float theta = 0;
/// <summary>
/// Sets up a projective viewport
/// </summary>
private void SetupViewport()
{
int width = glControl1.Width;
int height = glControl1.Height;
// 1. set ViewPort transform:
GL.Viewport(0, 0, width, height);
// 2. set projection matrix
GL.MatrixMode(MatrixMode.Projection);
Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView(fov, (float)width/(float)height, 0.1f, far);
GL.LoadMatrix(ref proj);
}
/// <summary>
/// Setup of a camera called for every frame prior to any rendering.
/// </summary>
private void SetCamera()
{
// !!!{{ TODO: add camera setup here
SetupViewport();
GL.MatrixMode(MatrixMode.Modelview);
Matrix4 modelview = Matrix4.CreateTranslation(-center) *
Matrix4.Scale(1.0f/diameter) *
Matrix4.CreateTranslation(0.0f, 0.0f, -1.5f);
GL.LoadMatrix(ref modelview);
// !!!}}
}
private void ResetCamera()
{
// !!!{{ TODO: add camera reset code here
// !!!}}
}
/// <summary>
/// Rendering of one frame.
/// </summary>
private void Render()
{
if (!loaded) return;
frameCounter++;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.ShadeModel(ShadingModel.Flat);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
GL.Enable(EnableCap.CullFace);
SetCamera();
RenderScene();
glControl1.SwapBuffers();
}
public void glControl1_MouseDown (object sender, MouseEventArgs e)
{
Cursor.Current = Cursors.Hand;
double x = MousePosition.X * 1.0/(glControl1.Width * 1.0/2);
double y = MousePosition.Y * 1.0/(glControl1.Height * 1.0/2);
x = x - 1;
y = 1 - y;
double z2 = 1 - x * x - y * y;
double z = z2 > 0 ? Math.Sqrt(z2) : 0;
v1 = new Vector3d(x, y, z);
v1.Normalize();
//labelFile.Text = String.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}", x, y, z, MousePosition.X, MousePosition.Y, glControl1.Width, glControl1.Height);
}
private void glControl1_MouseUp (object sender, MouseEventArgs e)
{
Cursor.Current = Cursors.Default;
double x = MousePosition.X * 1.0/(glControl1.Width * 1.0/2);
double y = MousePosition.Y * 1.0/(glControl1.Height * 1.0/2);
x = x - 1;
y = 1 - y;
double z2 = 1 - x * x - y * y;
double z = z2 > 0 ? Math.Sqrt(z2) : 0;
v2 = new Vector3d(x, y, z);
v2.Normalize();
Vector3d axis = Vector3d.Cross(v1, v2);
float theta = (float) Vector3d.CalculateAngle(v1, v2);
// Here sholud be smoething
//labelFile.Text = String.Format("{0}, {1}", axis, theta);
}
private void glControl1_MouseMove (object sender, MouseEventArgs e)
{
// !!!{{ TODO: add the event handler here
// !!!}}
}
private void glControl1_MouseWheel (object sender, MouseEventArgs e)
{
// !!!{{ TODO: add the event handler here
// HINT: for most mouses, e.delta/120 is the number of wheel clicks, +/- indicated the direction
// !!!}}
}
private void glControl1_KeyDown (object sender, KeyEventArgs e)
{
// !!!{{ TODO: add the event handler here
// !!!}}
}
private void glControl1_KeyUp (object sender, KeyEventArgs e)
{
// !!!{{ TODO: add the event handler here
// !!!}}
}
private void buttonReset_Click (object sender, EventArgs e)
{
// !!!{{ TODO: add the event handler here
ResetCamera();
// !!!}}
}
}
}
и Form1.cs
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Scene3D;
namespace _038trackball
{
public partial class Form1 : Form
{
/// <summary>
/// Scene read from file.
/// </summary>
protected SceneBrep scene = new SceneBrep();
/// <summary>
/// Scene center point.
/// </summary>
protected Vector3 center = Vector3.Zero;
/// <summary>
/// Scene diameter.
/// </summary>
protected float diameter = 3.5f;
/// <summary>
/// GLControl guard flag.
/// </summary>
bool loaded = false;
/// <summary>
/// Are we allowed to use VBO?
/// </summary>
bool useVBO = true;
#region OpenGL globals
private uint[] VBOid = new uint[ 2 ]; // vertex array (colors, normals, coords), index array
private int stride = 0; // stride for vertex array
#endregion
#region FPS counter
long lastFpsTime = 0L;
int frameCounter = 0;
long triangleCounter = 0L;
#endregion
public Form1()
{
InitializeComponent();
}
private void glControl1_Load (object sender, EventArgs e)
{
loaded = true;
// OpenGL init code:
GL.ClearColor(Color.DarkBlue);
GL.Enable(EnableCap.DepthTest);
GL.ShadeModel(ShadingModel.Flat);
// VBO init:
GL.GenBuffers(2, VBOid);
if (GL.GetError() != ErrorCode.NoError)
useVBO = false;
SetupViewport();
Application.Idle += new EventHandler(Application_Idle);
comboTrackballType.SelectedIndex = 0;
}
private void glControl1_Resize (object sender, EventArgs e)
{
if (!loaded) return;
SetupViewport();
glControl1.Invalidate();
}
private void glControl1_Paint (object sender, PaintEventArgs e)
{
Render();
}
private void buttonOpen_Click (object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Open Scene File";
ofd.Filter = "Wavefront OBJ Files|*.obj" +
"|All scene types|*.obj";
ofd.FilterIndex = 1;
ofd.FileName = "";
if (ofd.ShowDialog() != DialogResult.OK)
return;
WavefrontObj objReader = new WavefrontObj();
objReader.MirrorConversion = false;
StreamReader reader = new StreamReader(new FileStream(ofd.FileName, FileMode.Open));
int faces = objReader.ReadBrep(reader, scene);
reader.Close();
scene.BuildCornerTable();
diameter = scene.GetDiameter(out center);
scene.GenerateColors(12);
ResetCamera();
//labelFile.Text = String.Format("{0}: {1} faces, {2}, {3}, {4}, {5}", ofd.SafeFileName, faces, theta, v1.X, x, y);
PrepareDataBuffers();
glControl1.Invalidate();
}
/// <summary>
/// Prepare VBO content and upload it to the GPU.
/// </summary>
private void PrepareDataBuffers()
{
if (useVBO &&
scene != null &&
scene.Triangles > 0)
{
GL.EnableClientState(ArrayCap.VertexArray);
if (scene.Normals > 0)
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.ColorArray);
// Vertex array: color [normal] coord
GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[ 0 ]);
int vertexBufferSize = scene.VertexBufferSize(true, false, true, true);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)vertexBufferSize, IntPtr.Zero, BufferUsageHint.StaticDraw);
IntPtr videoMemoryPtr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.WriteOnly);
unsafe
{
stride = scene.FillVertexBuffer((float*)videoMemoryPtr.ToPointer(), true, false, true, true);
}
GL.UnmapBuffer(BufferTarget.ArrayBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// Index buffer
GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[ 1 ]);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(scene.Triangles * 3 * sizeof(uint)), IntPtr.Zero, BufferUsageHint.StaticDraw);
videoMemoryPtr = GL.MapBuffer(BufferTarget.ElementArrayBuffer, BufferAccess.WriteOnly);
unsafe
{
scene.FillIndexBuffer((uint*)videoMemoryPtr.ToPointer());
}
GL.UnmapBuffer(BufferTarget.ElementArrayBuffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}
else
{
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.ColorArray);
if (useVBO)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[ 0 ]);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)0, IntPtr.Zero, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[ 1 ]);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)0, IntPtr.Zero, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}
}
}
}
}
Я нашел ссылку на OpenGL arcball здесь: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball – ja72