Ryan
Ryan

Reputation: 11

Global Class used in GLUT bad? if so how can this be avoided?

I drew up this simple program using Open GL utilizing the GLUT functions. In order to manipulate the cube i'm using glutKeyboardFunc() which manipulates the camera or the angle using variables at which point glutIdleFunc() is called to redraw the scene. The only way I have been able to get between my rend function and my keycheck function is creating a global class which houses my variables and both functions.

Here is the code that pertains directly to my question.

enter code here

#include "stdafx.h"
#include "OGL.h"


void boingdraw();
void boingkeys();

OGL  Tramp; //Global class
void boingdraw() // called by glutDisplayFunc and kicks to my draw function
{
    Tramp.rend();
}
void boingkeys(unsigned char key, int x, int y) //called by glutKeyboardFunc
                                                     //kicks to my key switch
{
    Tramp.Keycheck( key,x, y);
}




int main (int argc, char**argv)
{





    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(400,400);
    glutCreateWindow("Testing");
    render3d();
    glutDisplayFunc(boingdraw);
    glutKeyboardFunc(boingkeys);
    glutIdleFunc(boingdraw);
    glutReshapeFunc(resize);
    glutMainLoop();
}

OGL.h file just has my includes and initializes the 2 functions of OGL class. Heres the OGL.cpp file

enter code here 
#include "stdafx.h"
#include "OGL.h"


OGL::OGL()
{
    lx= 0.0;
    updown= 0.0;
    z= -5.0;
    v1=0.0;
    v2=1.0;
    v3=0.0;
}
void OGL::rend() 
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
                        // camera perspective variables used to move camera
                        //with keyfunc       
        gluLookAt(0.0,updown,z,
              lx,0.0,0.0,
              v1,v2,v3);





    glPushMatrix();
    glTranslatef(-0.0,-0.0,0.0);
              //angle if changed in keycheck func called by glutKeyboardFunc()
    glRotatef(angle,0.0,1.0,0.0); 


    glBegin(GL_QUADS);

               //draws stuff not important really



    glEnd();
    glPopMatrix();
    glutSwapBuffers();

}
void OGL::Keycheck(unsigned char key, int x, int y)
      //Key switchboard with various checks for wsadqe and esc keys

    {
switch (key) 
    {
    case 27: 
        {
            exit(0);break;
        }
    case 97:
        {
                lx=lx+0.25;

                        break;
        }
    case 100: 
        {
            {
                lx=lx-0.25;

                        break;
        }
        }
    case 101: 
        {

            angle += 2.0f;
            if(angle > 360) angle -= 360;

            break;

        }
    case 113: 
        {

            angle -= 2.0f;
            if(angle < 0) angle += 362;

            break;
        }
    case 115:
        {
            z=z-0.25;

                        break;
        }
    case 119:
        {
            z=z+0.25;


        }


    }
}

I have tried many implementations of trampolines and function pointers to try to get into my class and just initializing it in main but I can never get it to compile without errors. Is a global class considered bad when using glut? And if so could somebody please give some examples of techniques that can be used with my code to work around this issue?

Please dont take this as a "Do my homework for me" thread or whatever I only ask for examples using my code because it will help me better understand the implementation of the techniques.

thank you in advance and please excuse the poor code(if it is) im just learning and would like to not get off with bad habits.

Upvotes: 1

Views: 498

Answers (2)

Chris Becke
Chris Becke

Reputation: 36131

The basic GLUT API does not have any way of associating user data with glut Windows.

So, what is typically done is a static scoped map is maintained mapping glut window Ids to your applications per window class instance.

static std::map<int,MyGlutWindowClass*> windows;

Inside each of your static callback functions you lookup the class instance you add to the map when you create the glut window :-

struct MyGlutWindowClass {
  static void CallBack(){
    MyGlutWindowClass* self = windows[glutGetWindow()];
    self->OnCallback();
  }
  void OnCallback(){
    AccessMemberVariables();
  }

};

Upvotes: 1

Keith
Keith

Reputation: 6834

I think you are trying to get your head around reconciling "globals are always Evil" and having to use non-OO callbacks in GLUT.

Short answer - You are correct in having to use some kind of global.

So for good program design, come back to considering the issues with globals. Your code "as is" is good in that the global is in a single file. Marking it explicitly as file scope would be better:

static OGL  Tramp; // Or use a local namespace.

This means that it is somewhat encapsulated, but accessible from your callbacks. You can follow much the same pattern using a Singleton. If you are certain that you will only ever want a single instance of OGL, then this is fine. If you might want other instances, you can wrap it in a function call (maybe a static class method):

OGL&  getOGLInstance(unsigned id = 0)
{
    static OGL  Tramp; // Or use a local namespace.
    // Later, add in handling to find the instance given 'id'.
    return Tramp; 
}

Upvotes: 1

Related Questions