最近整理硬碟突然翻到以前剛開始從MFC改用wxWidgets時寫的結合OpenGL的練習實驗,也想到還沒紀錄最基本的怎麼讓wxWidgets操作OpenGL,因為samples的方法我覺得不好,所以我覺得還是紀錄上來好了,基本上只要把wxPanel當作parent傳給wxGLCanvas就可以畫在wxPanel上,然後就可以用wxBoxSizer去layout了,用wxImage載入材質再將相關資訊bind上目標並用VA的方式畫出等等...。
render_data.h
#ifndef __RENDER_DATA__
#define __RENDER_DATA__
typedef struct
{
float vertex[3];
float texcoord[2];
}VertexTexture;
VertexTexture vertex[4] = {
{{-0.5f,-0.5f,0.0f},{0.0f,1.0f}},
{{0.5f,-0.5f,0.0f},{1.0f,1.0f}},
{{-0.5f,0.5f,0.0f},{0.0f,0.0f}},
{{0.5f,0.5f,0.0f},{1.0f,0.0f}}
};
#endif
wxGL.h
#ifndef __WX_GL__
#define __WX_GL__
#include <wx/wx.h>
#include <wx/glcanvas.h>
#include "render_data.h"
class wxGL;
class App:public wxApp
{
public:
bool OnInit();
};
class Frame:public wxFrame
{
public:
Frame(const wxString&);
~Frame();
void OnExit(wxCommandEvent&);
void CreateUI();
void Render(wxTimerEvent&);
private:
wxGL *gl;
wxTimer timer;
wxSlider *angle[3];
static const unsigned long fps = 60;
unsigned long begin,last;
DECLARE_EVENT_TABLE();
};
class wxGL:public wxGLCanvas
{
public:
wxGL(wxWindow*,wxWindowID,
const wxPoint&,
const wxSize&,
long,const wxString);
~wxGL();
void OnSize(wxSizeEvent&);
void InitGL();
void Render();
void SetAngleXYZ(int x,int y,int z){angleX = x;angleY = y,angleZ = z;};
private:
bool init;
float angleX,angleY,angleZ;
wxImage *image;
GLuint texture_id;
DECLARE_EVENT_TABLE();
};
enum{
RENDER_TIMER = 1000
};
DECLARE_APP(App)
IMPLEMENT_APP(App)
BEGIN_EVENT_TABLE(wxGL,wxGLCanvas)
EVT_SIZE(wxGL::OnSize)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(Frame,wxFrame)
EVT_MENU(wxID_EXIT,Frame::OnExit)
EVT_TIMER(RENDER_TIMER,Frame::Render)
END_EVENT_TABLE()
#endif
wxGL.cpp
#include "wxGL.h"
bool App::OnInit()
{
Frame *frame = new Frame(wxT("wxGL"));
frame->Show(true);
return true;
}
Frame::Frame(const wxString &title):wxFrame(NULL,wxID_ANY,title,wxDefaultPosition,wxSize(800,600)),timer(this,RENDER_TIMER)
{
CreateUI();
begin = 0;
last = 0;
timer.Start(10);
}
void Frame::CreateUI()
{
wxMenu *file = new wxMenu;
file->Append(wxID_EXIT,wxT("E&xit\tAlt-q"),wxT("Exit"));
wxMenuBar *bar = new wxMenuBar;
bar->Append(file,wxT("File"));
SetMenuBar(bar);
wxBoxSizer *top = new wxBoxSizer(wxVERTICAL);
this->SetSizer(top);
wxBoxSizer *screen_box = new wxBoxSizer(wxVERTICAL);
top->Add(screen_box,0,wxALIGN_CENTER_HORIZONTAL | wxALL,5);
wxPanel *panel = new wxPanel(this,wxID_ANY,wxDefaultPosition,wxSize(380,380));
screen_box->Add(panel,0,wxALIGN_CENTER_HORIZONTAL | wxALL,5);
for(int i = 0;i < 3;++i){
angle[i] = new wxSlider(this,wxID_ANY,0,0,360,wxDefaultPosition,wxSize(300,-1),wxSL_HORIZONTAL | wxSL_AUTOTICKS | wxSL_LABELS);
screen_box->Add(angle[i],0,wxALIGN_CENTER_HORIZONTAL | wxALL,5);
}
gl = new wxGL(panel,wxID_ANY,wxDefaultPosition,wxSize(380,380),0,wxT("wxGL"));
CreateStatusBar(2);
SetStatusText(wxDateTime::Now().Format());
}
void Frame::Render(wxTimerEvent &event){
begin = wxGetLocalTimeMillis().ToLong();
gl->SetAngleXYZ(angle[0]->GetValue(),angle[1]->GetValue(),angle[2]->GetValue());
if(begin - last > (1000 / fps)){
last = begin;
gl->Render();
}
}
Frame::~Frame()
{
timer.Stop();
}
void Frame::OnExit(wxCommandEvent &event)
{
Close();
}
wxGL::wxGL(wxWindow *paraent,wxWindowID id = wxID_ANY,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,const wxString name = wxT("wxGL")):
wxGLCanvas(paraent,(wxGLCanvas*)NULL,id,pos,size,style | wxFULL_REPAINT_ON_RESIZE,name)
{
wxInitAllImageHandlers();
image = new wxImage(wxT("lena_std.tif"));
texture_id = 0;
init = false;
}
void wxGL::InitGL()
{
SetCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,1.0f,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f,0.0f,2.0f,
0.0f,0.0f,0.0f,
0.0f,-1.0f,0.0f);
for(int i = 0;i < 4;++i){
vertex[i].texcoord[1] = 1.0f - vertex[i].texcoord[1];
}
glGenTextures(1,&texture_id);
glBindTexture(GL_TEXTURE_2D,texture_id);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,
(GLint)image->GetWidth(),(GLint)image->GetHeight(),0,
GL_RGB,GL_UNSIGNED_BYTE,image->GetData());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
}
wxGL::~wxGL()
{
}
void wxGL::OnSize(wxSizeEvent &event)
{
wxGLCanvas::OnSize(event);
int w,h;
GetClientSize(&w,&h);
if(GetContext()){
SetCurrent();
glViewport(0,0,(GLint)w,(GLint)h);
}
}
void wxGL::Render()
{
wxPaintDC dc(this);
if(!init){
InitGL();
init = true;
}
SetCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f,0.0f,2.0f,
0.0f,0.0f,0.0f,
0.0f,-1.0f,0.0f);
glRotatef(angleX,1.0f,0.0f,0.0f);
glRotatef(angleY,0.0f,1.0f,0.0f);
glRotatef(angleZ,0.0f,0.0f,1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(VertexTexture),&vertex[0].vertex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,sizeof(VertexTexture),&vertex[0].texcoord);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
SwapBuffers();
}
沒有留言:
張貼留言