Глобальный класс используется в глюте плохо? если так, как этого можно избежать? - PullRequest
1 голос
/ 15 марта 2011

Я составил эту простую программу, используя Open GL с использованием функций GLUT. Чтобы манипулировать кубом, я использую glutKeyboardFunc (), который манипулирует камерой или углом, используя переменные, в которых вызывается glutIdleFunc () для перерисовки сцены. Единственный способ, которым я смог добраться между моей функцией rend и моей функцией keycheck, - это создать глобальный класс, в котором хранятся мои переменные и обе функции.

Вот код, который относится непосредственно к моему вопросу.

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 содержит мои включения и инициализирует 2 функции класса OGL. Вот файл OGL.cpp

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;


        }


    }
}

Я пробовал много реализаций батутов и указателей на функции, чтобы попытаться войти в мой класс и просто инициализировать его в main, но я никогда не смогу заставить его скомпилироваться без ошибок. Глобальный класс считается плохим при использовании перенасыщения? И если да, то может ли кто-нибудь привести примеры техник, которые можно использовать с моим кодом для решения этой проблемы?

Пожалуйста, не воспринимайте это как ветку "Сделай мою домашнюю работу для меня" или что-то, что я прошу только для примеров, используя мой код, потому что это поможет мне лучше понять реализацию методов.

заранее благодарю и прошу прощения за плохой код (если он есть), я только учусь и хотел бы не отказываться от вредных привычек.

Ответы [ 2 ]

1 голос
/ 15 марта 2011

В базовом API GLUT нет способа связать пользовательские данные с перенасыщенным Windows.

Таким образом, обычно выполняется статическая карта области видимости, отображающая идентификаторы перенасыщения окна в ваших приложениях для каждого экземпляра класса окна.

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

Внутри каждой из ваших статических функций обратного вызова вы просматриваете экземпляр класса, который вы добавляете на карту при создании окна перенасыщения: -

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

};
1 голос
/ 15 марта 2011

Я думаю, вы пытаетесь примириться с тем, что «глобальные всегда злые», и вам нужно использовать обратные вызовы не-OO в GLUT.

Краткий ответ - вы правы, когда используете какой-тоglobal.

Итак, для хорошего дизайна программы вернемся к рассмотрению проблем с глобальными переменными.Ваш код "как есть" хорош тем, что глобальный файл находится в одном файле.Лучше пометить его явно как область видимости файла:

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

Это означает, что он несколько инкапсулирован, но доступен из ваших обратных вызовов.Вы можете следовать по той же схеме, используя Singleton.Если вы уверены, что вам понадобится только один экземпляр OGL, тогда это нормально.Если вам могут понадобиться другие экземпляры, вы можете заключить их в вызов функции (возможно, в метод статического класса):

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; 
}
...