GLUT的简洁OO封装
毕业设计用到了OpenGL,由于不会用MFC和Win32API做窗口程序;自然选用了GLUT。GLUT很好用,就是每次写一堆Init,注册callback,觉得有点恶心,于是对他做了简单的OO封装。记录在此,如有同学有兴趣可以下载。
GLUT应用程序
#include <GL/glut.h>
#include <stdio.h> void display()
{
// OpenGL commands
} // 一般按键(所有可打印字符,ESC也在内)
void keyboardHander(unsigned char ch, int x, int y)
{
printf("key %d(%c) x: %d, y: %d\n", ch, ch, x, y);
fflush(stdout);
} // 特殊按键
void specialKeyHandler(int key, int x, int y)
{
printf("special key"); switch(key) {
case GLUT_KEY_UP:
printf("%d(%s) ", key, "GLUT_KEY_UP");
break;
case GLUT_KEY_DOWN:
printf("%d(%s) ", key, "GLUT_KEY_DOWN");
break;
case GLUT_KEY_LEFT:
printf("%d(%s) ", key, "GLUT_KEY_LEFT");
break;
case GLUT_KEY_RIGHT:
printf("%d(%s) ", key, "GLUT_KEY_RIGHT");
break;
default:
printf("%d(%s) ", key, "Other Special keys");
}
printf("x: %d, y: %d\n", x, y);
fflush(stdout);
} // 鼠标按键
void mouseHandler(int button, int state, int x, int y)
{
printf("mouse pos: (%3d, %3d) button: %s(%d), state: %s(%d)\n", x, y,
GLUT_LEFT_BUTTON == button ? "GLUT_LEFT_BUTTON"
: GLUT_RIGHT_BUTTON == button ? "GLUT_RIGHT_BUTTON"
: GLUT_MIDDLE_BUTTON == button ? "GLUT_MIDDLE_BUTTON"
: "UNKOW"
, button,
GLUT_UP == state ? "GLUT_UP"
: GLUT_DOWN == state ? "GLUT_DOWN"
: "UNKNOW"
, state
);
fflush(stdout);
} // 鼠标拖动
void motionHandler(int x, int y)
{
printf("motion to %d, %d\n", x, y);
fflush(stdout);
} // 鼠标移动
void passiveMotionHandler(int x, int y)
{
printf("passive motion to %d, %d\n", x, y);
fflush(stdout);
} void testTimer(int i)
{
printf("Alarm %d\n", i);
fflush(stdout);
if( i < 5 )
glutTimerFunc(1000, testTimer, i+1);
} int main(int argc, char *argv[])
{
glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("Getting started with OpenGL 4.3"); glutDisplayFunc(display); glutKeyboardFunc(keyboardHander); // 键盘按键(一般)
glutSpecialFunc(specialKeyHandler); // 特殊按键 glutMouseFunc(mouseHandler); // 鼠标按键
glutMotionFunc(motionHandler); // 鼠标拖动
glutPassiveMotionFunc(passiveMotionHandler); // 鼠标移动 glutTimerFunc(1000, testTimer, 1); // 定时器 glutMainLoop(); // start main loop.
return 0;
}
用起来还算简单,就是每次都写一堆Init和callback注册...
int main(int argc, char **argv)
{
GlutApp::initGlut(argc, argv);
GlutApp* app = new DemoApp(); app->setTitle("a demo app");
app->setWindowsSize(800, 600); app->run();
delete app;
return 0;
}
Member function 如何作为Callback?
GlutApp
#ifndef GLUT_APP_H
#define GLUT_APP_H class GlutApp
{
public:
typedef void (*MenuFuncPtr)(void); struct MenuEntry
{
int id;
const char* str;
MenuFuncPtr fun;
}; // 当前 App 实例指针,指向子类实例
static GlutApp* s_pCurrentApp; // 右键菜单 项数最大值
static const int MAX_MENU = 32; // ctor
GlutApp(); // getter and setters:
static void initGlut(int argc, char** argv) { s_argc = argc; s_argv = argv; } void setDisplayMode(unsigned int mode) { m_displayMode = mode; } void setWindowsSize(int w, int h) { m_winWidth = w; m_winHeight = h; } int getWindowWidth() { return m_winWidth; } int getWindowHeight() { return m_winHeight; } void setWindowsPos(int x, int y) { m_winPosX = x; m_winPosY = y; } void setTitle(char *title) { m_title = title; } void run(); void addRightMenu(const char *str, MenuFuncPtr fun); // 初始化
virtual void onInit(){} //////////////////////////////////////////////////////////////////////////
// GLUT delegate callbacks: // 空闲函数
virtual void onIdle(){} // 图形显示(OpenGL绘图指令)
virtual void onDisplay() = 0; // 子类必须重写;不能实例化该类 // 窗口大小改变
virtual void onResize(int w, int h){} //////////////////////////////////////////////////////////////////////////
// 键盘事件响应 方法: // 一般按键(可打印字符,ESC)
virtual void onKey(unsigned char key, int x, int y){} // 一般按键 按下
virtual void onKeyDown(unsigned char key, int x, int y) {} // 特殊按键(除一般按键外按键)
virtual void onSpecialKey(int key, int x, int y){} // 特殊按键按下
virtual void onSpecialKeyDown(int key, int x, int y){} //////////////////////////////////////////////////////////////////////////
// 鼠标事件响应 方法: // 鼠标按键
//! @param button: The button parameter is one of GLUT LEFT BUTTON, GLUT MIDDLE BUTTON, or GLUT RIGHT BUTTON.
//! @param state: The state parameter is either GLUT UP or GLUT DOWN indicating
// whether the callback was due to a release or press respectively.
virtual void onMousePress(int button, int state, int x, int y){} // 鼠标移动
virtual void onMouseMove(int x, int y){} // 鼠标拖动
virtual void onMousePressMove(int x,int y){} //////////////////////////////////////////////////////////////////////////
// 定时器相关 方法:
virtual void onTimer() {} void setTimer(int delay, int period = 0); protected:
void registerMenus(); // actual GLUT callback functions:
static void KeyboardCallback(unsigned char key, int x, int y); static void KeyboardUpCallback(unsigned char key, int x, int y); static void SpecialKeyboardCallback(int key, int x, int y); static void SpecialKeyboardUpCallback(int key, int x, int y); static void ReshapeCallback(int w, int h); static void IdleCallback(); static void MouseFuncCallback(int button, int state, int x, int y); static void MotionFuncCallback(int x,int y); static void MousePassiveCallback(int x, int y); static void DisplayCallback(); static void MenuCallback(int menuId); static void TimerCallback(int period);
private:
unsigned int m_displayMode; // for glutInit
static int s_argc;
static char** s_argv; char *m_title; // for glutSetWindowSize
int m_winWidth;
int m_winHeight; // for windows position
int m_winPosX;
int m_winPosY; // for menus:
int m_menuCount;
MenuEntry m_menuEntry[MAX_MENU]; // for timer:
int m_delay;
int m_period;
}; #endif // GLUT_APP_H
GlutApp.cpp
#include <gl/glut.h>
#include <assert.h>
#include <stdio.h> #include "GlutApp.h" int GlutApp::s_argc = 0; char** GlutApp::s_argv = 0; GlutApp* GlutApp::s_pCurrentApp = 0; int g_iLastWindow = 0; void GlutApp::run()
{
GlutApp* lastApp = GlutApp::s_pCurrentApp;
GlutApp::s_pCurrentApp = this; GlutApp* app = GlutApp::s_pCurrentApp;
assert(app); int screenW = glutGet(GLUT_SCREEN_WIDTH);
int screenH = glutGet(GLUT_SCREEN_HEIGHT); if (!app->m_winWidth)
{
app->m_winWidth = screenW / 2;
app->m_winHeight = screenH / 2;
} if (!app->m_winPosX)
{
app->m_winPosX = (screenW - app->m_winWidth) / 2;
app->m_winPosY = (screenH - app->m_winHeight) / 2;
} if (!lastApp) // first time calling Glut::run().
{
// glutInit that should only be called exactly once in a GLUT program.
glutInit(&this->s_argc, this->s_argv); glutInitDisplayMode(this->m_displayMode);
glutInitWindowPosition(app->m_winPosX, app->m_winPosY);
glutInitWindowSize(app->m_winWidth, app->m_winHeight); glutCreateWindow(app->m_title);
g_iLastWindow = glutGetWindow();
// printf("create window: %d\n", g_iLastWindow);
}
else
{
glutDestroyWindow(g_iLastWindow); glutInitDisplayMode(this->m_displayMode);
glutInitWindowPosition(app->m_winPosX, app->m_winPosY);
glutInitWindowSize(app->m_winWidth, app->m_winHeight); glutCreateWindow(app->m_title);
g_iLastWindow = glutGetWindow();
// printf("create window: %d\n", g_iLastWindow);
} app->onInit(); // register keyboard callbacks
glutKeyboardFunc(GlutApp::KeyboardCallback);
glutKeyboardUpFunc(GlutApp::KeyboardUpCallback);
glutSpecialFunc(GlutApp::SpecialKeyboardCallback);
glutSpecialUpFunc(GlutApp::SpecialKeyboardUpCallback); // register mouse callbacks
glutMouseFunc(GlutApp::MouseFuncCallback);
glutMotionFunc(GlutApp::MotionFuncCallback);
glutPassiveMotionFunc(GlutApp::MousePassiveCallback); // register menus:
registerMenus(); // regitser windows resize callback
glutReshapeFunc(GlutApp::ReshapeCallback); // register render callback
glutDisplayFunc(GlutApp::DisplayCallback); // register timer callbacks:
if (app->m_delay)
{
glutTimerFunc(app->m_delay, GlutApp::TimerCallback, app->m_period);
} // register idle callback
glutIdleFunc(GlutApp::IdleCallback); GlutApp::IdleCallback(); glutMainLoop();
} GlutApp::GlutApp()
{
m_displayMode = GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL;
m_menuCount = 0;
m_delay = 0;
m_period = 0; m_winPosX = 0;
m_winPosY = 0;
m_winWidth = 0;
m_winHeight = 0;
} void GlutApp::KeyboardCallback( unsigned char key, int x, int y )
{
GlutApp::s_pCurrentApp->onKey(key,x,y);
} void GlutApp::KeyboardUpCallback( unsigned char key, int x, int y )
{
GlutApp::s_pCurrentApp->onKeyDown(key,x,y);
} void GlutApp::SpecialKeyboardCallback( int key, int x, int y )
{
GlutApp::s_pCurrentApp->onSpecialKey(key,x,y);
} void GlutApp::SpecialKeyboardUpCallback( int key, int x, int y )
{
GlutApp::s_pCurrentApp->onSpecialKeyDown(key,x,y);
} void GlutApp::ReshapeCallback( int w, int h )
{
GlutApp::s_pCurrentApp->setWindowsSize(w, h);
GlutApp::s_pCurrentApp->onResize(w,h);
} void GlutApp::IdleCallback()
{
GlutApp::s_pCurrentApp->onIdle();
} void GlutApp::MouseFuncCallback( int button, int state, int x, int y )
{
GlutApp::s_pCurrentApp->onMousePress(button,state,x,y);
} void GlutApp::MotionFuncCallback( int x,int y )
{
GlutApp::s_pCurrentApp->onMousePressMove(x,y);
} void GlutApp::MousePassiveCallback( int x, int y )
{
GlutApp::s_pCurrentApp->onMouseMove(x, y);
} void GlutApp::DisplayCallback( void )
{
GlutApp::s_pCurrentApp->onDisplay();
} void GlutApp::addRightMenu( const char *str, MenuFuncPtr fun )
{
m_menuEntry[m_menuCount].id = m_menuCount;
m_menuEntry[m_menuCount].str = str;
m_menuEntry[m_menuCount].fun = fun;
m_menuCount++;
} void GlutApp::registerMenus()
{
if (m_menuCount > 0)
{
glutCreateMenu(GlutApp::MenuCallback);
for (int i=0; i<m_menuCount; ++i)
{
glutAddMenuEntry(m_menuEntry[i].str, m_menuEntry[i].id);
}
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
} void GlutApp::MenuCallback( int menuId )
{
for (int i=0; i<GlutApp::s_pCurrentApp->m_menuCount; ++i)
{
if (menuId == GlutApp::s_pCurrentApp->m_menuEntry[i].id)
{
GlutApp::s_pCurrentApp->m_menuEntry[i].fun();
}
}
} void GlutApp::setTimer( int delay, int period )
{
this->m_delay = delay;
this->m_period = period;
} void GlutApp::TimerCallback( int period )
{
// printf("Timer Alarm!\n");
GlutApp::s_pCurrentApp->onTimer();
if (period)
{
glutTimerFunc(period, GlutApp::TimerCallback, period);
}
}
一个Demo
#include <windows.h> // 这里使用的是 Windows SDK 实现的OpenGL,必须写在<gl/gl.h>之前
#include <gl/gl.h>
#include <gl/glut.h>
#include <stdio.h> #include "GlutApp.h" class TestApp : public GlutApp
{
virtual void onSpecialKeyDown( int key, int x, int y )
{
printf("onKeyDown: %d(%c), <%d, %d>\n", key, key, x, y);
} virtual void onSpecialKey( int key, int x, int y )
{
printf("onSpecialKey: %d(%c), <%d, %d>\n", key, key, x, y);
} virtual void onKeyDown( unsigned char key, int x, int y )
{
printf("onKeyDown: %d(%c), <%d, %d>\n", key, key, x, y);
} virtual void onKey( unsigned char key, int x, int y )
{
printf("onKey: %d(%c), <%d, %d>\n", key, key, x, y);
} virtual void onMouseMove( int x, int y )
{
printf("onMouseMove: %d, %d\n", x, y);
} virtual void onMousePress( int button, int state, int x, int y )
{
printf("onMousePress: %d, %d, %d, %d\n", button, state, x, y);
} virtual void onMousePressMove( int x,int y )
{
printf("onMousePressMove: %d, %d\n", x, y);
} virtual void onInit()
{
printf("OnInit\n"); glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
} virtual void onDisplay()
{
glClear(GL_COLOR_BUFFER_BIT); // glPolygonMode(GL_FRONT, GL_LINE); glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(0, 1);
glEnd(); glFlush();
glutSwapBuffers();
} virtual void onResize( int w, int h )
{
printf("resize window: %d, %d\n", w, h);
} virtual void onIdle()
{ }
}; void menu1() { printf("menu1 selected!\n"); } void menu2() { printf("menu2 selected!\n"); } void fullScreen() { glutFullScreen(); } void exitApp() { exit(0); } int main(int argc, char **argv)
{
TestApp test; test.initGlut(argc, argv);
test.setTitle("AppTest");
test.setWindowsSize(640, 480);
test.setDisplayMode(GLUT_RGBA | GLUT_SINGLE); test.addRightMenu("menu1", menu1);
test.addRightMenu("menu2", menu2);
test.addRightMenu("full screen", fullScreen);
test.addRightMenu("exit", exitApp); test.run(); return 0;
}
GLUT的简洁OO封装的更多相关文章
- OO(Object Oriented)思想和PO(Procedure-Oriented)思想
对象将需求用类一个个隔开,就象用储物箱把东西一个个封装起来一样,需求变了,分几种情况,最严重的是大变,那么每个储物箱都要打开改,这种方法就不见得有好处:但是这种情况发生概率比较小,大部分需求变化都是局 ...
- ACE - 代码层次及Socket封装
原文出自http://www.cnblogs.com/binchen-china,禁止转载. ACE源码约10万行,是c++中非常大的一个网络编程代码库,包含了网络编程的边边角角.在实际使用时,并不是 ...
- 专访图书作者祁宇:C++11让程序更简洁、更现代、更强大
日前CSDN采访了祁宇,请他解读C++11的新标准.C++的现状以及未来的发展前景. CSDN:怎么会想到编写<深入应用C++11:代码优化与工程级应用>这本书的?有没有什么故事可以分享下 ...
- 高性能封装检测浏览器支持css3属性函数
css3出来已经很久了,现在来谈判断浏览器是否支持某个css3的属性虽说有点过时了,但是还是可以谈谈的,然后,此篇主要谈的不是判断是否支持,而是怎么封装更好,为什么这么封装,欢迎吐槽. 入题,判断浏览 ...
- 从零开始山寨Caffe·壹:仰望星空与脚踏实地
请以“仰望星空与脚踏实地”作为题目,写一篇不少于800字的文章.除诗歌外,文体不限. ——2010·北京卷 仰望星空 规范性 Caffe诞生于12年末,如果偏要形容一下这个框架,可以用"须敬 ...
- C++ stringstream介绍,使用方法与例子
From: http://www.usidcbbs.com/read-htm-tid-1898.html C++引入了ostringstream.istringstream.stringstream这 ...
- stringstream
C++引入了ostringstream.istringstream.stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件. istringstream类用于执行C++ ...
- C++ 系列:iostream 的用途与局限
转载自http://www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html 本文主要考虑 x86 Linux 平台,不考虑跨平台的可移植性,也 ...
- [转]DDD领域驱动设计基本理论知识总结
领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...
随机推荐
- 使用Xcode7的Instruments检测解决iOS内存泄露
文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 作为一名iOS开发攻城狮, ...
- css3-无缝滚动
@keyframes 规则用于创建动画.在 @keyframes 中规定某项 CSS 样式,就能创建由当前样式逐渐改为新样式的动画效果. 动画的名称和运行所需时间是必须的 帧动画:将动画名称赋给选择器 ...
- C#-WebForm-文件上传-FileUpload控件
FileUpload - 选择文件,不能执行上传功能,通过点击按钮实现上传 默认选择类型为所有类型 //<上传>按钮 void Button1_Click(object sender, E ...
- 故障review的一些总结
故障review的一些总结 故障review的目的 归纳出现故障产生的原因 检查故障的产生是否具有普遍性,并尽可能的保证同类问题不在出现, 回顾故障的处理流程,并检查处理过程中所存在的问题.并确定此类 ...
- 博文Contents<1--到200—>
====================-------------- 前言:博客中的随笔文章.并非都是笔者的原创文章.有些是听别人说的.有些是书上摘录的.有些是百度的.有些是别人博客的文章.有些是自己 ...
- 二维码相关---java生成二维码名片,并且自动保存到手机通讯录中...
http://blog.csdn.net/lidew521/article/details/24441825
- 自制-随机生成不重复的数组 --算法,egret平台下的TS code
感觉这个算法经常会用到,前段时间写过一次,现在push出来.原理是有两个数组,一个数组存放随机数,然后从另一个数组提取相关的数,然后把另一个数组的大小-1,remove掉这个数,unity里也是这个原 ...
- [Android]优化相关
尽量减少布局的层次,最多10层,可以通过LinearLayout向RelativeLayout的转变来减少层的数量 使用ListView的时候,getView方法中的对象尽量重用
- OncrickListener的实现
在Java中实现的监控事件的方法 button.addActionListener(new ActionListener() { @Override public void actionPerform ...
- 拖动对象ondrag
说明: 在进行拖放操作时,dataTransfer 对象用来保存被拖动的数据.它可以保存一项或多项数据.一种或者多种数据类型.dataTransfer对象有两个主要的方法:getData()方法和se ...