GLUT, GLFW... programming style

Hi,

Coming from Python and pyglet, I am now starting coding in C
and playing around with GLUT and GLFW…

Because of the nature of GLUT callbacks, it seems that you have to use an awful lot of global variables so thatcallbacks can share infos about the scene.

I’m fine with it, but I remember my school days… and 2 rules: “No GOTOs”, “Minimal amount of globals”…

So I wonder, is there a more fancy of dealing with this (besides changing languages)?

Globals are “bad”, because of possibles variables collisions right? so the best I can think of, is enforcing a naming convention for globals (envFoo or whatever), so i minimize this risk?

I’d like to hear the thoughts of experts about this…
what is considered good programming style with C/GLUT (or whatever toolkit)? any link to a nicely designed openSource app, maybe?

thx :slight_smile:

Are you wanting to use C? Is C++ an option?

If you are using C, then there aren’t many good ways around the globals. They are not really that bad but yes if the code becomes very large then this can be troublesome.

Some suggestions for C:

  1. naming convention like you said helps
  2. use of structs
  3. Some variables you will find are used only in one callback, in that case you can use static varibles (see timer/angle below)
  4. Or use separate C files with variables having scope only in that one file and write interface functions callable to the outside world that access these “local” variables.

For C++, use classes to hold internal state information. For instance what I find to work well is something along the lines of


class CustomGraphicsPipeline
{
   //private state variables
   GLuint variable_x;
   public:
      CustomGraphicsPipeline() : variable_x(1) { }
      ~CustomGraphicsPipeline() {}

      bool Init()                    // All Setup For OpenGL Goes Here
      {
        GLint ret = true;  
        // do onetime initialization here
        // variable_x available to use
        return ret;                    // Initialization Went OK?
      }

      void Draw()
      {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        // Here's Where We Do All The Drawing
        // variable_x available to use
      }
      
      void CameraRotate(GLfloat angle)
      { 
        // Place your camera with gluLookAt / MODELVIEW
        // variable_x available to use
      }

      void reshape(GLfloat w, GLfloat h)
      { 
        glViewport(0,0,w,h);
        // set perspective view
        // variable_x available to use
      }
};

// One GLOBAL ///////////////////////////////////////////////////////
CustomGraphicsPipeline Scene;
/////////////////////////////////////////////////////////////////////

static void timer(int dt_msec) // put not-drawing / physics updates here
{
  glutTimerFunc(30,timer,30); // come back in 30msec

  static GLfloat Angle=0.0;
  Angle+= 360./8000.*dt_msec; // 360 degrees rotation in 8 seconds
  Scene.CameraRotate(Angle);

  glutPostRedisplay();
}

static void display(void)
{
  Scene.Draw();
  glutSwapBuffers();
}

static void reshape(int width, int height)// Resize And Initialize The GL Window
{
  Scene.reshape(width,height);
}

static void key(unsigned char k, int x, int y)
{
  switch (k) {
  case 27:  // Escape
    exit(0);
    break;
  default:
    return;
  }
}

int main( int argc, char *argv[] )
{
   glutInit( &argc, argv );
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
   glutCreateWindow ("hello world");

   assert( Scene.Init() ); // bail if scene initialization fails

   glutTimerFunc(0,timer,0);
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(key);

   glutMainLoop();

   return 0;
}

Note, I try to keep the gl calls all in the class but all the glut calls outside the class.

I want to use C for non technical reasons really…
I left python for C as an incentive for my fellow collegues (old school C guys) to give a hand and collaborate with me…

Coding in C++, even though it would feel more natural for me, would give them an easy way out: “c++?, oop?, no can do!”

Maybe I should give this a thought again…

Thanks for the suggestions in C…there is no magic trick I wasn’t aware of :smiley:

nice structs with a strong naming convention, might provide some safety…

No, a collision will be picked up by the linker so no problem there.

IMHO the main reason globals are bad because they can lead to highly connected code. If you solve every problem by “Oh I’ll just make this variable global so I can access it over here in this other piece of code” then you can quickly get an tightly coupled, hard to change system.

If you limit the use of globals between modules and as you say, make good use of structs, naming etc you can write perfectly good code without C++ or OO.

That said, I would urge you to consider the use of C++ as “a better C”. It has many useful additions e.g. stronger type checking, so you can still code in C, but compile with C++. You might also want to try using just some of the C++ features such as “pass by reference” or function overloading (by that I just mean having two or more functions with the same name, but with different parameter lists).

C++ can (and often is) be used as a procedural language, it doesn’t have to be OO.

IMHO the main reason globals are bad because they can lead to highly connected code. If you solve every problem by “Oh I’ll just make this variable global so I can access it over here in this other piece of code” then you can quickly get an tightly coupled, hard to change system.

They also introduce all sorts of thread safety issues. That said, precious few C programmers are capable of writing thread-safe code, so that’s par for the course. :stuck_out_tongue:

C++ is a multiparadigm language, but somehow I doubt that’s going to sway the “OOP? No can do!” crowd.