2011-12-18 2 views
2

Я использовал учебник по 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); 
     } 
     } 
    } 
    } 
} 
+0

Я нашел ссылку на OpenGL arcball здесь: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball – ja72

ответ

0

Где вы создали свой ModelView матрицу умножить на Matrix4.CreateRotation с вращением вашего объекта, указанного.

-2

Чтобы применить преобразование одного объекта:

GL.PushMatrix(); 
GL.Translate(X, 0f, 0f); // My object is moving along the X axis 
GL.Rotate(AngleX, 0.0f, 1.0f, 0.0f); // Also it rotates alongs its 

... put here all the code necessary to draw your object 

GL.PopMatrix(); 
+0

Каковы AngleX и X ? –

+1

AngleX - это двойной. Это ориентация, которую я хочу в градусах по оси X. X является двойным, и это позиция объекта, которую я хочу на оси X. – Larry

Смежные вопросы