Is there to have a scene panning (kind of like we get in gmaps) with simple mouse event ? Currently I two mouse events :
Mousewheel to zoom by changing cRadius
in glTranslatef
LMB dragging for rotation by changing xrot
and yrot
in glRotatef
.
Below is the function:
float xpos = 0, ypos = 0, zpos = 0, xrot = 0, yrot = 0, zrot = 0, cRadius = 30.0f, lastx, lasty, lastz;
void mouseMovement(int x, int y)
{
int diffx = x - lastx;
int diffy = y - lasty;
lastx = x;
lasty = y;
xrot += (float)diffy;
yrot += (float)diffx;
}
and mouse button initialization function below
void mouseFunc(int button, int state, int x, int y)
{
lastx = x;
lasty = y;
}
Can the pan function be enabled using the same logic that is being used for rotation, like replacing xrot
and yrot
with a different variable in glTranslatef
(if not where should be the translation applied) ? Below is my display function along with reshape function. Am using glPerspective
rather that glLookat
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -cRadius);
glRotatef(xrot, 1.0, 0.0, 0.0);
glRotatef(yrot, 0.0, 1.0, 0.0);
glBegin(GL_LINES);
------------
------
glTranslated(-xpos, 0.0f, zpos);
glutSwapBuffers();
glEnd();
}
The mouse functions has been called in main loop
int OpenGL(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Window");
glutDisplayFunc(display);
glutIdleFunc(display);
glutMouseFunc(mouseFunc);
glutMotionFunc(mouseMovement);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
//Reshape
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 0.1, 500.0);
glMatrixMode(GL_MODELVIEW);
}
At perspective projection panning depends on the depth of the object. (See Qmatrix4x4 translate does not take any effect.
Luckily you know the dept of the geometry. It is defined in view space by cRadius
.
The relation between the projected area in view space and the Z coordinate of the view space is linear. It depends on the field of view angle and the aspect ratio.
(See also Field of view + Aspect Ratio + View Matrix from Projection Matrix (HMD OST Calibration))
A projected size in normalized device space can be transformed to a size in view space by:
aspect = w / h
tanFov = tan(fov_y * 2.0) * 2.0;
size_x = ndx_size_x * z_eye * tanFov * aspect;
size_y = ndx_size_y * z_eye * tanFov;
Apply that to your code:
#define _USE_MATH_DEFINES
#include <math.h>
float cRadius = 10.0f;
float fov_y = 60.0f;
float nearp = 0.1f;
float farp = 500.0f;
float width = 500.0f;
float height = 500.0f;
void mouseMovement(int x, int y)
{
int diffx = x - lastx;
int diffy = y - lasty;
lastx = x;
lasty = y;
float ndc_x = diffx * 2.0f / width;
float ndc_y = diffy * 2.0f / height;
float aspect = width / height;
float fov_rad = fov_y * M_PI / 180.0;
float tanFov = tan(fov_rad / 2.0);
xtrans += ndc_x * cRadius * tanFov * aspect;
ytrans -= ndc_y * cRadius * tanFov;
}
void mouseFunc( int button, int state, int x, int y )
{
lastx = x;
lasty = y;
}
void reshape(int w, int h)
{
width = (float)w;
height = (float)h;
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov_y, width / height, nearp, farp);
glMatrixMode(GL_MODELVIEW);
}
void display(void)
{
// [...]
glLoadIdentity();
glTranslatef(xtrans, ytrans, -cRadius);
glRotatef(xrot, 1.0, 0.0, 0.0);
glRotatef(yrot, 0.0, 1.0, 0.0);
// [...]
glEnd();
glutSwapBuffers();
}