1

Is there to have a scene panning (kind of like we get in gmaps) with simple mouse event ? Currently I two mouse events :

  1. Mousewheel to zoom by changing cRadius in glTranslatef

  2. 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);
}
Community
  • 1
  • 1
Sid133
  • 354
  • 2
  • 17
  • At perspective projection panning depends on the depth of the object. Related: [Qmatrix4x4 translate does not take any effect](https://stackoverflow.com/questions/54491410/qmatrix4x4-translate-does-not-take-any-effect/54491988#54491988) – Rabbid76 Dec 30 '19 at 15:30
  • I went through the link but i couldn't figure out how I could implement that in my code. As you can see, my current mouse functions doesn't have any buttons or state defined(GLUT_UP or GLUT_DOWN). As of now both my LMB and RMB is doing the same thing. Can gltranslatef be made varying according to mouse? Am using the same for 'zoom' with glutMouseWheelFunc , by changing cRadius in gltranslatef (under display) – Sid133 Dec 31 '19 at 10:55

1 Answers1

2

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();
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    That works Perfectly!. I have also added an if else statement to check left or right button click in both mouseFunc and mouseMovement. Now I have all my mouse button configured. LMB for rotating,RMB for panning and Mousewheel for zoom. Thanks again!! – Sid133 Dec 31 '19 at 14:17