SVat's picture

Object rotation

Hello! Sorry for my english. I use Google Translate.
I learn c# and opentk.

My code:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
 
namespace OpenWinForm
{
    public partial class Form1 : Form
    {
        private float camPosX = 8.0f;
        private float camPosY = 8.0f;
        private float camPosZ = 8.0f;
 
        private bool checkMouse = false;
 
        private float cubePosX = 0.0f;
        private float cubePosY = 0.0f;
        private float cubePosZ = 0.0f;
 
        private float cubeScaleX = 1.0f;
        private float cubeScaleY = 1.0f;
        private float cubeScaleZ = 1.0f;
 
        private float cubeRotateX = 0.0f;
        private float cubeRotateY = 0.0f;
        private float cubeRotateZ = 0.0f;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            glControl1.KeyDown += new KeyEventHandler(glControl1_KeyDown);
            glControl1.MouseWheel += new MouseEventHandler(glControl1_MouseWheel);
 
            Application.Idle += Application_Idle;
 
            GL.ClearColor(0.1f, 0.1f, 0.1f, 1.0f);
            GL.Enable(EnableCap.DepthTest);
 
            glControl1_Resize(this, EventArgs.Empty);
        }
 
        void glControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (!checkMouse) return;
 
            if (e.Delta > 0)
            {
                camPosX -= 0.4f;
                camPosY -= 0.4f;
                camPosZ -= 0.4f;
            }
            else
            {
                camPosX += 0.4f;
                camPosY += 0.4f;
                camPosZ += 0.4f;
            }
        }
 
        protected override void OnClosing(CancelEventArgs e)
        {
            Application.Idle -= Application_Idle;
 
            base.OnClosing(e);
        }
 
        void Application_Idle(object sender, EventArgs e)
        {
            while (glControl1.IsIdle)
            {
                Render();
            }
        }
 
        private void glControl1_Paint(object sender, PaintEventArgs e)
        {
            Render();
        }
 
        private void Render()
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            Matrix4 lookat = Matrix4.LookAt(camPosX, camPosY, camPosZ, 0, 0, 0, 0, 1, 0);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref lookat);
 
            GL.PushMatrix();
            DrawAxies();
            GL.PopMatrix();
 
            GL.PushMatrix();
            DrawGrid();
            GL.PopMatrix();
 
            GL.PushMatrix();
            GL.Rotate(cubeRotateX, 1.0f, 0.0f, 0.0f);
            GL.Rotate(cubeRotateY, 0.0f, 1.0f, 0.0f);
            GL.Rotate(cubeRotateZ, 0.0f, 0.0f, 1.0f);
            GL.Translate(cubePosX, cubePosY, cubePosZ);
            GL.Scale(cubeScaleX, cubeScaleY, cubeScaleZ);
            DrawCube();
            GL.PopMatrix();
 
            glControl1.SwapBuffers();
        }
 
        private void glControl1_Resize(object sender, EventArgs e)
        {
            if (glControl1.ClientSize.Height == 0)
                glControl1.ClientSize = new System.Drawing.Size(glControl1.ClientSize.Width, 1);
 
            GL.Viewport(0, 0, glControl1.ClientSize.Width, glControl1.ClientSize.Height);
 
            float aspect_ratio = Width / (float)Height;
            Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 64);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref perpective);
        }
 
        private void glControl1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Escape:
                    this.Close();
                    break;
            }
        }
 
        private void DrawGrid()
        {
            GL.Begin(BeginMode.Lines);
                GL.Color3(0.2f, 0.2f, 0.2f);
                float i;
                for (i = -5; i <= 5; i++)
                {
                    GL.Vertex3(-5, 0, i);
                    GL.Vertex3(5, 0, i);
                    GL.Vertex3(i, 0, -5);
                    GL.Vertex3(i, 0, 5);
                }
            GL.End();
        }
 
        private void DrawAxies()
        {
            GL.Begin(BeginMode.Lines);
                GL.Color3(Color.Red);
                GL.Vertex3(-5, 0, 0);
                GL.Vertex3(5, 0, 0);
                GL.Color3(Color.Green);
                GL.Vertex3(0, -5, 0);
                GL.Vertex3(0, 5, 0);
                GL.Color3(Color.Blue);
                GL.Vertex3(0, 0, -5);
                GL.Vertex3(0, 0, 5);
            GL.End();
        }
 
        private void DrawCube()
        {
            GL.Begin(BeginMode.Quads);
 
            GL.Color3(Color.Silver);
            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, -1.0f);
 
            GL.Color3(Color.Honeydew);
            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);
 
            GL.Color3(Color.Moccasin);
            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);
 
            GL.Color3(Color.IndianRed);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);
 
            GL.Color3(Color.PaleVioletRed);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);
 
            GL.Color3(Color.ForestGreen);
            GL.Vertex3(1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);
 
            GL.End();
        }
 
        private void positionX_ValueChanged(object sender, EventArgs e)
        {
            cubePosX = (float)positionX.Value;
        }
 
        private void positionY_ValueChanged(object sender, EventArgs e)
        {
            cubePosY = (float)positionY.Value;
        }
 
        private void positionZ_ValueChanged(object sender, EventArgs e)
        {
            cubePosZ = (float)positionZ.Value;
        }
 
        private void glControl1_MouseEnter(object sender, EventArgs e)
        {
            checkMouse = true;
            glControl1.Focus();
        }
 
        private void glControl1_MouseLeave(object sender, EventArgs e)
        {
            checkMouse = false;
        }
 
        private void scaleX_ValueChanged(object sender, EventArgs e)
        {
            cubeScaleX = (float)scaleX.Value;
        }
 
        private void scaleY_ValueChanged(object sender, EventArgs e)
        {
            cubeScaleY = (float)scaleY.Value;
        }
 
        private void scaleZ_ValueChanged(object sender, EventArgs e)
        {
            cubeScaleZ = (float)scaleZ.Value;
        }
 
        private void rotationX_ValueChanged(object sender, EventArgs e)
        {
            cubeRotateX = (float)rotationX.Value;
        }
 
        private void rotationY_ValueChanged(object sender, EventArgs e)
        {
            cubeRotateY = (float)rotationY.Value;
        }
 
        private void rotationZ_ValueChanged(object sender, EventArgs e)
        {
            cubeRotateZ = (float)rotationZ.Value;
        }
    }
}

In the initial position (x=0, y=0, z=0) of the cube rotates correctly, around its axis (image 1).
If you change the position of the cube, it starts to rotate around the initial position (image 2).
What it is necessary to make, what after position change, the cube rotated round its axis?

Inline Images
rotation1
rotation2

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Matrix multiplication, in general, is not commutative.

This:

            GL.Rotate(cubeRotateX, 1.0f, 0.0f, 0.0f);
            GL.Rotate(cubeRotateY, 0.0f, 1.0f, 0.0f);
            GL.Rotate(cubeRotateZ, 0.0f, 0.0f, 1.0f);
            GL.Translate(cubePosX, cubePosY, cubePosZ);

will give different results than:

            GL.Translate(cubePosX, cubePosY, cubePosZ);
            GL.Rotate(cubeRotateX, 1.0f, 0.0f, 0.0f);
            GL.Rotate(cubeRotateY, 0.0f, 1.0f, 0.0f);
            GL.Rotate(cubeRotateZ, 0.0f, 0.0f, 1.0f);

There are many good tutorials on the topic, for example: http://www.glprogramming.com/red/chapter03.html#name2

SVat's picture

Fiddler thanks. Now everything is good. I thought that at first it is better to turn, and then to move.
Excuse if I sometimes ask silly questions.