Para utilizar opengl com wxWidgets nós dispomos da classe wxGLCanvas. Esta classe possui os métodos SetColor(const wxString& cor) que seta a cor da janela de vizualização usando um nome de cor pré-definido, sendo portanto, uma alternativa para a função OpenGL 'glColor3f', SetCurrent(), que seta o estado representado pelo contexto de renderização OpenGL e SwapBuffers(), que é o método reponsável pela troca dos buffers atual e de fundo e vice-versa, permitindo dessa forma, que os comando OpenGL prévios (de fundo) sejam mostrados na janela de vizualização.
Exemplo
No nosso exemplo fazer escrever uma aplicação que mostra um cubo em 3 dimensões tendo cada face uma cor. Através do movimento da 'rodinha' do mouse nosso cubo poderá ser girado em torno dos eixos x e z em ambos os sentidos, mostrando suas diferentes faces.
//main.h
#ifndef _glpane
#define _glpane
#include "wx/wx.h"
#include "wx/glcanvas.h"
class PainelGL : public wxGLCanvas
{
public:
float rot;
PainelGL(wxFrame* pai);
void resized(wxSizeEvent& evt);
void Desenha(wxPaintEvent& evt);
void preparaViewport3D(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y);
//evento responsável pela rotação
void mouseWheelMoved(wxMouseEvent& evt);
DECLARE_EVENT_TABLE()
};
class MinhaApp : public wxApp
{
virtual bool OnInit();
wxFrame *janela;
PainelGL *glPainel;
};
#endif
//main.cpp
#include "wx/sizer.h"
#include "wx/glcanvas.h"
#include "main.h"
#ifdef __WXMAC__
#include "OpenGL/glu.h"
#include "OpenGL/gl.h"
#else
#include <GL/glu.h>
#include <GL/gl.h>
#endif
IMPLEMENT_APP(MinhaApp)
bool MinhaApp::OnInit()
{
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
janela = new wxFrame(NULL, -1, _("OpenGL com wxWidgets"), wxDefaultPosition, wxSize(400,400));
glPainel = new PainelGL(janela);
sizer->Add(glPainel, 1, wxEXPAND);
janela->SetSizer(sizer);
janela->SetAutoLayout(true);
janela->Show();
return true;
}
BEGIN_EVENT_TABLE(PainelGL, wxGLCanvas)
EVT_MOUSEWHEEL(PainelGL::mouseWheelMoved)
EVT_PAINT(PainelGL::Desenha)
END_EVENT_TABLE()
void PainelGL::mouseWheelMoved(wxMouseEvent& evt)
{
//o metodo GetWheelRotation nos indica o sentido da rotação da 'rodinha' do mouse, positivo/negativo - pra frente/pra tras
if(evt.GetWheelRotation() > 0)
rot += 0.5f;
else
rot -= 0.5f;
//atualizamos o desenho mostrando a rotação
Refresh();
}
PainelGL::PainelGL(wxFrame *pai) :
wxGLCanvas(pai, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{
//inicializamos o valor de rotação
rot = 0.5f;
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}
void PainelGL::resized(wxSizeEvent& evt)
{
//atualizamos o desenho no caso de redimensionamento da janela
Refresh();
}
void PainelGL::preparaViewport3D(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //fundo preto
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST); //habilita teste de profundidade
//testa se o valor de profundidade é menor ou igual o valor armazenado
//passando no caso de ser verdadeiro
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_COLOR_MATERIAL);
//define dimensões da viewport
glViewport(topleft_x, topleft_y, bottomrigth_x, bottomrigth_y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float ratio = (float) (bottomrigth_x ) / (float) (bottomrigth_y );
gluPerspective(45 /*angulo de visao*/, ratio, 0.2 /*corte pra perto*/, 200 /*corte pra longe*/);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void PainelGL::Desenha(wxPaintEvent& evt)
{
if(!IsShown())
return;
wxGLCanvas::SetCurrent();
wxPaintDC(this);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
preparaViewport3D(0,0,GetSize().x, GetSize().y);
glLoadIdentity();
glColor4f(0,0,1,1);
glTranslatef(0,0,-5);
//rotação nos eixos x e z
glRotatef(rot, 1.0f, 0.0f, 1.0f);
glBegin(GL_QUADS); //começamos a desenhar o cubo
glColor3f(0.0f,1.0f,0.0f); //verde
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 0.5f, 0.0f); //laranja
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(1.0f, 0.0f, 0.0f); //vermelho
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f); //amarelo
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); //azul
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(1.0f, 0.0f, 1.0f); //violeta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();
glFlush();
SwapBuffers();
}
Para compilar:
g++ main.cpp -o exemplo_gl `wx-config --libs --cxxflags --gl-libs` -lGLU
Referências:
http://wiki.wxwidgets.org/WxGLCanvas
http://docs.wxwidgets.org/trunk/classwx_g_l_canvas.html#a9f9ab3909606484e717904064d4e7b4f
http://nehe.gamedev.net/tutorial/3d_shapes/10035/