2010-08-28 46 views
25

Tôi đã tạo một lớp C++ (myPixmap) để đóng gói công việc được thực hiện bởi bộ công cụ OpenGL GLUT. Hàm thành viên display() của lớp chứa hầu hết mã được yêu cầu để thiết lập GLUT.Sử dụng OpenGL glutDisplayFunc trong lớp


void myPixmap::display() 
{ 
    // open an OpenGL window if it hasn't already been opened 
    if (!openedWindow) 
    { 
     // command-line arguments to appease glut 
     char *argv[] = {"myPixmap"}; 
     int argc = 1; 
     glutInit(&argc, argv); 
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
     glutInitWindowSize(640, 480); 
     glutInitWindowPosition(30, 30); 
     glutCreateWindow("Experiment"); 
     glutDisplayFunc(draw); 
     glClearColor(0.9f, 0.9f, 0.9f, 0.0); 
     glClear(GL_COLOR_BUFFER_BIT); 
     glutMainLoop(); 

     openedWindow = true; 
    } 
} 

Chức năng hiển thị thông qua với glutDisplayFunc() là một hàm thành viên của lớp:


void myPixmap::draw(void) 
{ 
    glDrawPixels(m,n,GL_RGB,GL_UNSIGNED_BYTE, pixel); 
} 

Tuy nhiên, gcc 4.2.1 trên Mac OS X 10.6.4 từ chối để biên dịch mã này, tuyên bố rằng:

argument of type 'void (myPixmap::)()' does not match 'void (*)()'

có cách nào để sử dụng bộ công cụ thị trường bất động bên trong một hàm thành viên của một lớp học, hay tôi phải gọi tất cả functio GLUT ns trong hàm main của chương trình?

Trả lời

30

Vấn đề là một con trỏ tới hàm thành viên bị ràng buộc thể hiện phải bao gồm con trỏ this. OpenGL là một API C và không biết gì về các con trỏ this. Bạn sẽ phải sử dụng một hàm thành viên tĩnh (không yêu cầu một cá thể, và do đó không có this) và đặt một số thành viên dữ liệu tĩnh (để truy cập cá thể) để sử dụng glutDisplayFunc.

class myPixmap 
{ 
private: 
    static myPixmap* currentInstance; 

    static void drawCallback() 
    { 
    currentInstance->draw(); 
    } 

    void setupDrawCallback() 
    { 
    currentInstance = this; 
    ::glutDisplayFunc(myPixmap::drawCallback); 
    } 
}; 

Bạn cũng có thể gặp sự cố liên kết C liên kết với C++, trong trường hợp này bạn sẽ phải chơi xung quanh với extern "C". Nếu có, bạn có thể phải sử dụng chức năng toàn cầu, thay vì chức năng thành viên tĩnh làm gọi lại của bạn và có rằng gọi myPixmap::draw. Một cái gì đó như:

class myPixmap 
{ 
public: 
    void draw(); 

private: 
    void setupDrawCallback(); 
}; 

myPixmap* g_CurrentInstance; 

extern "C" 
void drawCallback() 
{ 
    g_CurrentInstance->draw(); 
} 

void myPixmap::setupDrawCallback(); 
{ 
    ::g_CurrentInstance = this; 
    ::glutDisplayFunc(::drawCallback); 
} 

Với tất cả điều này, hãy cố gắng thực hiện càng ít thay đổi càng tốt, vì đây thực sự là một kludge để xử lý w/OpenGL là API C.

Nếu bạn muốn nhiều phiên bản (Tôi không nghĩ rằng hầu hết mọi người sử dụng GLUT tạo nhiều phiên bản, nhưng có thể bạn), bạn sẽ phải tìm ra giải pháp bằng cách sử dụng sơ đồ :: để truy xuất thể hiện:

static std::map<int, myPixmap> instanceMap; 

trong trường hợp bạn muốn lấy int để giải quyết dụ, tôi không chắc chắn :)

FYI, bạn nên xác định chức năng mà không chứa tham số theo cách này:

void some_function() { } 

không

void some_function(void) { } 
+0

Cảm ơn Merlyn; đây là một giải pháp tuyệt vời. Tôi thấy rằng trong trường hợp của tôi, tôi đã có vấn đề với C liên kết vs C + + liên kết, vì vậy tôi đã phải sử dụng một chức năng toàn cầu như được hiển thị trong khối thứ hai của mã ví dụ. Cuối cùng tôi đã có thể biên dịch chương trình. Tôi không yêu cầu nhiều phiên bản, vì vậy đây không phải là vấn đề đối với tôi. –

2

Merlyn việc giải pháp didnt đối với tôi, vì vậy tôi đã thay đổi chút bằng cách đưa currentInstance ngoài và nó hoạt động:

Class myPixmap; 
static myPixmap* currentInstance; 
Class myPixmap { 
... 
} 
+0

Tất cả các tùy chọn khác không hoạt động đối với tôi, nhưng điều này chạy hoàn hảo. –

1

Tôi gặp khó khăn khi hiểu câu trả lời chính xác từ Merlyn, vì vậy đây là phiên bản đơn giản :

Trong myPixmap.h, thay đổi chức năng hiển thị thành static chức năng thành viên. Nên làm việc.

class myPixmap 
{ 
    //... 
    static void display(); 
    //... 
}; 
Các vấn đề liên quan