Soll ich lieber mit OpenGL fortfahren?
-
Hallo zusammen!
Ich habe mit wxWidgets eine kleine Anwendung geschrieben, mit dem man ein Fahrstuhl in vier verschiedene Ebenen bewegen kann. Ich bin sehr stolz auf mein Programm, weil alles funktioniert und versucht wurde zu berücksichtigen – wie etwa beim Resize-Ereignis die Graphik anzupassen und das selbst erstellte rote LED-Display zum Leuchten zu bringen. Das Quelltext findet ihr unten.
Ich frage mich, wie man eigentlich OpenGL in wxWidgets einbinden kann und richtig verwendet. Ich möchte gerne OpenGL lernen, da mir das Flimmern mit den Paint-Ereignis stört. Ich bringe Erfahrungen mit dem 3D-Modeler Povray mit und kann mir daher 3D-Objekt beim Lesen eines Befehls richtig vorstellen.
Es währe toll, wenn mir einer anhand eines Beispiels zeigen könnte, wie man mit OpenGL ein 2D-Objekt in einem Panel von wxWidgets darstellen kann. 3D-Objekt, wie ein Würfel, währe auch nicht schlecht.
Sagt mir bitte, wie euch mein Programm gefällt!
Gruß,
Stefanbase.h
#ifndef BASE_H #define BASE_H class GUIsrbib : public wxApp { public: virtual bool OnInit(); }; class BasicFrame : public wxFrame { private: unsigned int direction; unsigned int input; unsigned int unit; unsigned int pos; unsigned int step; unsigned int storey; wxPanel *panel[4]; wxButton *button[4]; wxTimer *timer; public: enum { srID_ZERO, srID_FIRST, srID_SECOND, srID_THIRD } wxWindowID; BasicFrame(const wxChar *title, int xpos, int ypos, int width, int height, long style); ~BasicFrame(); void Level(wxDC *dc, unsigned int num, unsigned int arrow); void OnPaint(wxPaintEvent &event); void OnDisplay(wxPaintEvent &event); void OnDrive0(wxCommandEvent &event); void OnDrive1(wxCommandEvent &event); void OnDrive2(wxCommandEvent &event); void OnDrive3(wxCommandEvent &event); void OnSize(wxSizeEvent &event); void OnTimer(wxTimerEvent &event); }; #endif
base.cpp:
#include <wx/wx.h> #include "base.h" IMPLEMENT_APP(GUIsrbib) bool GUIsrbib::OnInit() { BasicFrame *frame = new BasicFrame(wxString("Fahrstuhl"), -1, -1, 800, 600, wxDEFAULT_FRAME_STYLE); frame->Show(TRUE); frame->Connect(BasicFrame::srID_ZERO, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BasicFrame::OnDrive0)); frame->Connect(BasicFrame::srID_FIRST, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BasicFrame::OnDrive1)); frame->Connect(BasicFrame::srID_SECOND, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BasicFrame::OnDrive2)); frame->Connect(BasicFrame::srID_THIRD, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BasicFrame::OnDrive3)); frame->Connect(wxEVT_SIZE, wxSizeEventHandler(BasicFrame::OnSize)); frame->Connect(wxEVT_TIMER, wxTimerEventHandler(BasicFrame::OnTimer)); SetTopWindow(frame); return TRUE; } BasicFrame::BasicFrame(const wxChar *title, int xpos, int ypos, int width, int height, long style) : wxFrame((wxFrame *)NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height), style), step(429) { input = 0; direction = 0; unit = 143; pos = 72; storey = 0; panel[0] = new wxPanel(this, wxID_ANY, wxPoint(0, 0), wxSize(800, 600)); panel[1] = new wxPanel(panel[0], wxID_ANY, wxPoint(0, 0), wxSize(800, 572)); panel[2] = new wxPanel(panel[0], wxID_ANY, wxPoint(680, 424), wxSize(110, 138)); panel[3] = new wxPanel(panel[2], wxID_ANY, wxPoint(5, 4), wxSize(100, 100)); button[0] = new wxButton(panel[2], srID_ZERO, wxString("E"), wxPoint(4, 110), wxSize(24, 24)); button[1] = new wxButton(panel[2], srID_FIRST, wxString("1"), wxPoint(30, 110), wxSize(24, 24)); button[2] = new wxButton(panel[2], srID_SECOND, wxString("2"), wxPoint(56, 110), wxSize(24, 24)); button[3] = new wxButton(panel[2], srID_THIRD, wxString("3"), wxPoint(82, 110), wxSize(24, 24)); timer = new wxTimer(this, wxID_ANY); panel[1]->SetBackgroundColour(wxColour(0, 0, 0)); panel[2]->SetBackgroundColour(wxColour(80, 80, 80)); panel[3]->SetBackgroundColour(wxColour(40, 40, 40)); panel[1]->Connect(wxEVT_PAINT, wxPaintEventHandler(BasicFrame::OnPaint), NULL, this); panel[3]->Connect(wxEVT_PAINT, wxPaintEventHandler(BasicFrame::OnDisplay), NULL, this); button[0]->Enable(FALSE); } BasicFrame::~BasicFrame() { } void BasicFrame::Level(wxDC *dc, unsigned int num, unsigned int arrow) { unsigned int start, end; wxPoint points1[3]; wxPoint points2[3]; points1[0] = wxPoint(79, 38); points1[1] = wxPoint(87, 26); points1[2] = wxPoint(95, 38); points2[0] = wxPoint(79, 62); points2[1] = wxPoint(87, 74); points2[2] = wxPoint(95, 62); dc->SetBrush(wxBrush(wxColour(255, 0, 0))); dc->SetPen(wxPen(wxColour(255, 0, 0), 1)); //Die Pfeile leuchten im Display switch(arrow) { case 1: dc->DrawPolygon(WXSIZEOF(points1), points1); dc->DrawRectangle(wxRect(84, 39, 7, 8)); break; case 2: dc->DrawPolygon(WXSIZEOF(points2), points2); dc->DrawRectangle(wxRect(84, 54, 7, 8)); break; default: break; } //Die Zahlen leuchten im Display switch(num) { case 0: //Das Zeichen für 'Erdgeschoss' for(unsigned int posy = 0; posy < 7; posy++) { start = 0; switch(posy) { case 0: end = 5; break; case 3: end = 4; break; case 6: end = 5; break; default: end = 1; } for(unsigned int posx = start; posx < end; posx++) { dc->DrawEllipse(wxRect(((14 * posx) + 2), ((14 * posy) + 2), 12, 12)); } } break; case 1: //Das Zeichen für '1. Stockwerk' for(unsigned int posy = 0; posy < 7; posy++) { switch(posy) { case 1: start = 1; end = 3; break; case 6: start = 0; end = 5; break; default: start = 2; end = 3; } for(unsigned int posx = start; posx < end; posx++) { dc->DrawEllipse(wxRect(((14 * posx) + 2), ((14 * posy) + 2), 12, 12)); } dc->DrawEllipse(wxRect(2, 30, 12, 12)); } break; case 2: //Das Zeichen für '2. Stockwerk' for(unsigned int posy = 0; posy < 7; posy++) { switch(posy) { case 0: start = 1; end = 4; break; case 1: start = 4; end = 5; break; case 2: start = 4; end = 5; break; case 3: start = 3; end = 4; break; case 4: start = 2; end = 3; break; case 5: start = 1; end = 2; break; default: start = 0; end = 5; } for(unsigned int posx = start; posx < end; posx++) { dc->DrawEllipse(wxRect(((14 * posx) + 2), ((14 * posy) + 2), 12, 12)); } dc->DrawEllipse(wxRect(2, 16, 12, 12)); } break; case 3: //Das Zeichen für '3. Stockwerk' for(unsigned int posy = 0; posy < 7; posy++) { switch(posy) { case 0: start = 1; end = 4; break; case 3: start = 2; end = 4; break; case 6: start = 1; end = 4; break; default: start = 4; end = 5; } for(unsigned int posx = start; posx < end; posx++) { dc->DrawEllipse(wxRect(((14 * posx) + 2), ((14 * posy) + 2), 12, 12)); } dc->DrawEllipse(wxRect(2, 16, 12, 12)); dc->DrawEllipse(wxRect(2, 72, 12, 12)); } break; } } void BasicFrame::OnPaint(wxPaintEvent &event) { wxSize area = this->GetSize(); wxPaintDC *paint = new wxPaintDC(panel[1]); paint->SetBackground(wxBrush(wxColour(0, 0, 0))); paint->SetBrush(wxBrush(wxColour(128, 0, 0))); paint->SetFont(wxFont(12, wxROMAN, wxNORMAL, wxNORMAL, FALSE, "DejaVu Sans")); paint->SetTextForeground(wxColour(255, 0, 0)); paint->SetPen(wxPen(wxColour(255, 0, 0), 1)); paint->DrawRectangle(wxRect(40, step, (unit - 20), (unit - 20))); paint->DrawLine(wxPoint((pos + 30), 0), wxPoint((pos + 30), (unit + step - 20))); paint->DrawText(wxString("3. Stockwerk"), (area.x / 2), (pos - 10)); paint->DrawText(wxString("2. Stockwerk"), (area.x / 2), ((pos * 3) - 10)); paint->DrawText(wxString("1. Stockwerk"), (area.x / 2), ((pos * 5) - 10)); paint->DrawText(wxString("Erdgeschoss"), (area.x / 2), ((pos * 7) - 10)); paint->SetBrush(wxBrush(wxColour(85, 85, 85))); paint->SetPen(wxPen(wxColour(255, 255, 255), 1)); paint->DrawLine(wxPoint(39, 0), wxPoint(39, area.y)); paint->DrawLine(wxPoint((unit + 20), 0), wxPoint((unit + 20), area.y)); paint->DrawRectangle(wxRect(0, (unit - 20), area.x, 20)); paint->DrawRectangle(wxRect(0, ((unit * 2) - 20), area.x, 20)); paint->DrawRectangle(wxRect(0, ((unit * 3) - 20), area.x, 20)); paint->DrawRectangle(wxRect(0, ((unit * 4) - 20), area.x, 20)); delete paint; } void BasicFrame::OnDisplay(wxPaintEvent &event) { //Das Display ausgeben wxPaintDC *paint2 = new wxPaintDC(panel[3]); wxPoint points1[3]; wxPoint points2[3]; points1[0] = wxPoint(79, 38); points1[1] = wxPoint(87, 26); points1[2] = wxPoint(95, 38); points2[0] = wxPoint(79, 62); points2[1] = wxPoint(87, 74); points2[2] = wxPoint(95, 62); paint2->SetBackground(wxBrush(wxColour(0, 0, 0))); paint2->SetBrush(wxBrush(wxColour(100, 40, 40))); paint2->SetFont(wxFont(12, wxROMAN, wxNORMAL, wxNORMAL, FALSE, "DejaVu Sans")); paint2->SetTextForeground(wxColour(255, 0, 0)); paint2->SetPen(wxPen(wxColour(100, 40, 40), 1)); for(unsigned int posy = 0; posy < 7; posy++) { for(unsigned int posx = 0; posx < 5; posx++) { paint2->DrawEllipse(wxRect(((14 * posx) + 2), ((14 * posy) + 2), 12, 12)); } } paint2->DrawPolygon(WXSIZEOF(points1), points1); paint2->DrawPolygon(WXSIZEOF(points2), points2); paint2->DrawRectangle(wxRect(84, 39, 7, 8)); paint2->DrawRectangle(wxRect(84, 54, 7, 8)); Level(paint2, storey, direction); delete paint2; } void BasicFrame::OnDrive0(wxCommandEvent &event) { input = 0; button[0]->Enable(FALSE); button[1]->Enable(FALSE); button[2]->Enable(FALSE); button[3]->Enable(FALSE); timer->Start(100); } void BasicFrame::OnDrive1(wxCommandEvent &event) { input = 1; button[0]->Enable(FALSE); button[1]->Enable(FALSE); button[2]->Enable(FALSE); button[3]->Enable(FALSE); timer->Start(100); } void BasicFrame::OnDrive2(wxCommandEvent &event) { input = 2; button[0]->Enable(FALSE); button[1]->Enable(FALSE); button[2]->Enable(FALSE); button[3]->Enable(FALSE); timer->Start(100); } void BasicFrame::OnDrive3(wxCommandEvent &event) { input = 3; button[0]->Enable(FALSE); button[1]->Enable(FALSE); button[2]->Enable(FALSE); button[3]->Enable(FALSE); timer->Start(100); } void BasicFrame::OnSize(wxSizeEvent &event) { wxSize area = this->GetSize(); unit = (area.y - 28) / 4; pos = unit / 2; panel[0]->SetSize(wxSize(area.x, area.y)); panel[1]->SetSize(wxSize(area.x, (area.y - 28))); panel[2]->SetPosition(wxPoint((area.x - 120), (area.y - 176))); if(!timer->IsRunning()) { step = (3 - storey) * unit; } panel[1]->Refresh(); } void BasicFrame::OnTimer(wxTimerEvent &event) { if(step == 0) { storey = 3; panel[3]->Refresh(); } else { if(step == unit) { storey = 2; panel[3]->Refresh(); } else { if(step == (unit * 2)) { storey = 1; panel[3]->Refresh(); } else { if(step == (unit * 3)) { storey = 0; panel[3]->Refresh(); } } } } if(storey > input) { direction = 2; step++; } else { if(storey < input) { direction = 1; step--; } else { direction = 0; timer->Stop(); button[0]->Enable(TRUE); button[1]->Enable(TRUE); button[2]->Enable(TRUE); button[3]->Enable(TRUE); button[storey]->Enable(FALSE); } } panel[1]->Refresh(); }
-
Es gibt ein OpenGl Control für wxWidgets, du kannst also OpenGL in dein Programm einbinden.
Das Geflicker könntest du wohl allerdings schon mit einem wxBufferedPaintDC beseitigen.
-
Mein Rat: Programmier erstmal ein wenig ohne OpenGL, denn OpenGL ist an sich zwar nicht schwierig, aber wenn du 3D-Sachen zeichnen willst, kommst du schnell an einen Punkt, wo du mit sehr viel Mathe konfrontiert wirst.
Für OpenGL + wxWidgets beispiele, musst du nur ins Quelltext-Verzeichnis von wxWidgets gucken. Da findest du unter
samples/opengl
genug Beispiele.