Turntable camera

Hello

I would like to implement a functionality similar to turntable camera in Blender. I need to move (strafe) 3D object and rotate it. After move it I would like to rotate scene always around of center of the screen. Actually after move object in any direction of the screen it rotates around its local coordinate system, not around center of the screen. It looks like the rotation center point is moving together with object. I’ve tried to use glTranslate function in several ways in the main render method, but I didn’t get expected results.
In the Mouse button down event I read the cursor position:


...
previousX = Mouse.X;
previousY = Mouse.Y;
previousZ = Mouse.Y;

prev_eyeX = (float)Mouse.X;
prev_eyeY = (float)Mouse.Y;
prev_eyeZ = (float)Mouse.Y;
...

In the mouse move event I modify the values of variables depending of the pressed mouse button


...		
if (Mouse[MouseButton.Middle])
{
    rot_x += (Mouse.Y - previousY);
    rot_y += (Mouse.X - previousX);
}

if (Mouse[MouseButton.Right])
{
    eyeZ += (Mouse.Y - prev_eyeZ) * 0.05f; // zoom in/out scene
}

if (Mouse[MouseButton.Left])
{
    centerX -= (Mouse.X - previousX) * 0.005f;	// centerX, centerY, centerZ determine the target point of camera view 
    centerY += (Mouse.Y - previousY) * 0.005f;
    centerZ -= (Mouse.Y - previousZ) * 0.005f;

    eyeX -= (Mouse.X - prev_eyeX) * 0.005f;  // eyeX, eyeY, eyeZ determine the position of camera 
    eyeY += (Mouse.Y - prev_eyeY) * 0.005f;

    translate_x -= (Mouse.X - previousX) * 0.005f; // translate_x, translate_y determines the object displacement
    translate_y += (Mouse.Y - previousY) * 0.005f;           
}

previousX = (float)Mouse.X;
previousY = (float)Mouse.Y;
previousZ = (float)Mouse.Y;
            
prev_eyeX = (float)Mouse.X;
prev_eyeY = (float)Mouse.Y;
prev_eyeZ = (float)Mouse.Y;
...

Main render method:


...
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

double aspect = Width / (float)Height;
GL.MatrixMode(MatrixMode.Projection);
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)aspect, 0.1f, 100.0f);
GL.LoadMatrix(ref perspective);
            
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

Matrix4 lookat = Matrix4.LookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref lookat);

GL.Rotate(rot_x, 1.0f, 0.0f, 0.0f);
GL.Rotate(rot_y, 0.0f, 1.0f, 0.0f);
GL.Rotate(rot_z, 0.0f, 0.0f, 1.0f);
			
GL.Translate(-translate_x, -translate_y, -translate_z);
            
RenderCube();
     
this.SwapBuffers();
...

Could you please suggest me how should I modify algorithm to get the expected results?

Thanks in advance for your any suggestions.


Regards,
Agarwean

Beware of copypaste :
previousZ = Mouse.Y; // Z !!
prev_eyeZ = (float)Mouse.Y; // Z !!

Read notes from “1:01:10” :
http://www.shamusyoung.com/twentysidedtale/?p=12574

I know exactly what kind of issue you mean, but in my case I move object using mouse on the application window and I’ve got access only to X and Y position of the mouse cursor. Therefore I’ve applied such solution (currently in test purposes).

In that case, put 0. Why let something that will be confusing later ?

For your original problem, try translate then rotate :

GL.Translate(-translate_x, -translate_y, -translate_z);

GL.Rotate(rot_x, 1.0f, 0.0f, 0.0f);
GL.Rotate(rot_y, 0.0f, 1.0f, 0.0f);
GL.Rotate(rot_z, 0.0f, 0.0f, 1.0f);

I tried to change X and Y values only and translate before rotate, it didn’t help.

Wouldn’t it be better to just rotate the camera,
On rotation simply increment/decrement theta and phi based on drag amount on x and y axis. Then calculate the new eye position and pass it to lookAt function to get the new modelview matrix


//0 < theta < PI
//0 < phi   < 2*PI
//radius is the distance of the camera 
//to the target
eyeX = radius * cos(phi) * sin(theta);
eyeY = radius * cos(theta);
eyeZ = radius * sin(phi) * sin(theta);	

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

double aspect = Width / (float)Height;
GL.MatrixMode(MatrixMode.Projection);
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)aspect, 0.1f, 100.0f);
GL.LoadMatrix(ref perspective);
            
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

Matrix4 lookat = Matrix4.LookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
GL.LoadMatrix(ref lookat);
             
RenderCube();
     
this.SwapBuffers();
}

Does it give me a circle-based camera rotation around the object?