Global Class 用在GLUT 不好?如果是的话如何避免这种情况?

发布于 2024-10-21 17:29:19 字数 2936 浏览 1 评论 0原文

我利用 GLUT 函数使用 Open GL 编写了这个简单的程序。为了操纵立方体,我使用 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 文件只包含我的包含并初始化 OGL 类的 2 个函数。这是 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 中初始化它,但我永远无法让它在没有错误的情况下进行编译。使用 glut 时全局类是否被认为是不好的?如果是这样,有人可以提供一些可以与我的代码一起使用来解决此问题的技术示例吗?

请不要将此视为“为我做作业”线程或任何我只要求使用我的代码的示例,因为它将帮助我更好地理解这些技术的实现。

预先感谢您,请原谅糟糕的代码(如果是的话),我只是在学习,不想摆脱坏习惯。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

因为看清所以看轻 2024-10-28 17:29:19

我认为您正在尝试协调“全局变量总是邪恶的”以及必须在 GLUT 中使用非 OO 回调。

简短的回答-您必须使用某种全局是正确的。

因此,为了获得良好的程序设计,请回过头来考虑全局变量的问题。您的代码“按原样”很好,因为全局位于单个文件中。将其显式标记为文件范围会更好:

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

这意味着它在某种程度上是封装的,但可以通过回调访问。
您可以使用单例遵循大致相同的模式。
如果您确定只需要一个 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; 
}

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; 
}
雪若未夕 2024-10-28 17:29:19

基本的 GLUT API 没有任何方法将用户数据与过剩的 Windows 关联起来。

因此,通常所做的是维护一个静态作用域映射,将过剩窗口 ID 映射到每个窗口类实例的应用程序。

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

在每个静态回调函数中,您都会查找创建过剩窗口时添加到地图中的类实例:-

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

};

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();
  }

};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文