#include "CELLWinApp.hpp"#include <gl/GLU.h>#include <assert.h>#include <math.h>#pragma comment(lib,"opengl32.lib")#pragma comment(lib,"glu32.lib")/*** 该例子展示如何点,线,面等数据,* 主要用到的OpenGL函数及定义如下 GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN GL_QUADS GL_QUAD_STRIP GL_POLYGON
绘制函数:改函数是OpenGL系统定义的函数,一些基本的绘制可以使用,效率较高
缺点是如果顶点数据不可随意组合: 参数有以下:相信有经验的大牛们,一看就知道是啥了,但对新手,我还是做个简单的介绍T = texture coord :纹理坐标,四维
C = 颜色 N = 法线 V = 定点V = vertex
2 = 元素的个数 F = 数据的格式: float GL_V2F //! 数据是两个float, GL_V3F //! 数据是三个个floatC = COLOR
4ub= 4个(r,g,b,a unsigned byte) V = vertex 2f = 2 * float GL_C4UB_V2F GL_C4UB_V3F GL_C3F_V3F GL_N3F_V3F GL_C4F_N3F_V3F GL_T2F_V3F GL_T4F_V4F GL_T2F_C4UB_V3F GL_T2F_C3F_V3F GL_T2F_N3F_V3F GL_T2F_C4F_N3F_V3F GL_T4F_C4F_N3F_V4F glInterleavedArrays( ); glDrawArrays( ); gluPerspective,以及如何自己生成一个矩阵,替代gluPerspective函数 同时加入键盘事件的处理,通过按'S'键切换绘制图元的类型 为了在应用层中回去键盘事件,需要对之前的基类做再次改造 将event函数声明成为虚函数,这样应用层可以进行重写。 如果你对Windows事件消息不熟悉,那你要看书了**//*** 顶点结构声明*/struct Vertex{ unsigned char r, g, b, a; float x, y, z;};Vertex g_points[] =
{ { 255, 0, 0, 255, 0.0f, 0.0f, 0.0f }, { 0, 255, 0, 255, 0.5f, 0.0f, 0.0f }, { 0, 0, 255, 255, -0.5f, 0.0f, 0.0f }, { 255, 255, 0, 255, 0.0f,-0.5f, 0.0f }, { 255, 0, 255, 255, 0.0f, 0.5f, 0.0f }};Vertex g_lines[] =
{ { 255, 0, 0, 255, -1.0f, 0.0f, 0.0f }, // Line #1 { 255, 0, 0, 255, 0.0f, 1.0f, 0.0f },{ 0, 255, 0, 255, 0.5f, 1.0f, 0.0f }, // Line #2
{ 0, 255, 0, 255, 0.5f,-1.0f, 0.0f },{ 0, 0, 255, 255, 1.0f, -0.5f, 0.0f }, // Line #3
{ 0, 0, 255, 255, -1.0f, -0.5f, 0.0f }}; Vertex g_lineStrip_and_lineLoop[] = { { 255, 0, 0, 255, 0.5f, 0.5f, 0.0f }, { 0, 255, 0, 255, 1.0f, 0.0f, 0.0f }, { 0, 0, 255, 255, 0.0f,-1.0f, 0.0f }, { 255, 255, 0, 255, -1.0f, 0.0f, 0.0f }, { 255, 0, 0, 255, 0.0f, 0.0f, 0.0f }, { 255, 0, 255, 255, 0.0f, 1.0f, 0.0f }};Vertex g_triangles[] =
{ { 255, 0, 0, 255, -1.0f, 0.0f, 0.0f }, // Triangle #1 { 0, 0, 255, 255, 1.0f, 0.0f, 0.0f }, { 0, 255, 0, 255, 0.0f, 1.0f, 0.0f }, { 255, 255, 0, 255, -0.5f,-1.0f, 0.0f }, // Triangle #2 { 255, 0, 0, 255, 0.5f,-1.0f, 0.0f }, { 0, 255, 255, 255, 0.0f,-0.5f, 0.0f }};Vertex g_triangleStrip[] =
{ { 255, 0, 0, 255, -2.0f, 0.0f, 0.0f }, { 0, 0, 255, 255, -1.0f, 0.0f, 0.0f }, { 0, 255, 0, 255, -1.0f, 1.0f, 0.0f }, { 255, 0, 255, 255, 0.0f, 0.0f, 0.0f }, { 255, 255, 0, 255, 0.0f, 1.0f, 0.0f }, { 255, 0, 0, 255, 1.0f, 0.0f, 0.0f }, { 0, 255, 255, 255, 1.0f, 1.0f, 0.0f }, { 0, 255, 0, 255, 2.0f, 1.0f, 0.0f }};Vertex g_triangleFan[] =
{ { 255, 0, 0, 255, 0.0f,-1.0f, 0.0f }, { 0, 255, 255, 255, 1.0f, 0.0f, 0.0f }, { 255, 0, 255, 255, 0.5f, 0.5f, 0.0f }, { 255, 255, 0, 255, 0.0f, 1.0f, 0.0f }, { 0, 0, 255, 255, -0.5f, 0.5f, 0.0f }, { 0, 255, 0, 255, -1.0f, 0.0f, 0.0f }};Vertex g_quads[] =
{ { 255, 0, 0, 255, -0.5f,-0.5f, 0.0f }, // Quad #1 { 0, 255, 0, 255, 0.5f,-0.5f, 0.0f }, { 0, 0, 255, 255, 0.5f, 0.5f, 0.0f }, { 255, 255, 0, 255, -0.5f, 0.5f, 0.0f },{ 255, 0, 255, 255, -1.5f, -1.0f, 0.0f }, // Quad #2
{ 0, 255, 255, 255, -1.0f, -1.0f, 0.0f }, { 255, 0, 0, 255, -1.0f, 1.5f, 0.0f }, { 0, 255, 0, 255, -1.5f, 1.5f, 0.0f },{ 0, 0, 255, 255, 1.0f, -0.2f, 0.0f }, // Quad #3
{ 255, 255, 0, 255, 2.0f, -0.2f, 0.0f }, { 0, 255, 255, 255, 2.0f, 0.2f, 0.0f }, { 255, 0, 255, 255, 1.0f, 0.2f, 0.0f }};Vertex g_quadStrip[] =
{ { 255, 0, 0, 255, -0.5f,-1.5f, 0.0f }, { 0, 255, 0, 255, 0.5f,-1.5f, 0.0f }, { 0, 0, 255, 255, -0.2f,-0.5f, 0.0f }, { 255, 255, 0, 255, 0.2f,-0.5f, 0.0f }, { 255, 0, 255, 255, -0.5f, 0.5f, 0.0f }, { 0, 255, 255, 255, 0.5f, 0.5f, 0.0f }, { 255, 0, 0, 255, -0.4f, 1.5f, 0.0f }, { 0, 255, 0, 255, 0.4f, 1.5f, 0.0f },};Vertex g_polygon[] =
{ { 255, 0, 0, 255, -0.3f,-1.5f, 0.0f }, { 0, 255, 0, 255, 0.3f,-1.5f, 0.0f }, { 0, 0, 255, 255, 0.5f, 0.5f, 0.0f }, { 255, 255, 0, 255, 0.0f, 1.5f, 0.0f }, { 255, 0, 255, 255, -0.5f, 0.5f, 0.0f }};class Tutorial2 :public CELL::Graphy::CELLWinApp
{ public: Tutorial2(HINSTANCE hInstance) :CELL::Graphy::CELLWinApp(hInstance) ,_primitiveType(GL_POINTS) { } virtual void render() { do { glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);/**
* 指明,要操作的矩阵是模型矩阵 */ glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0f, 0.0f, -5.0f );switch( _primitiveType )
{ case GL_POINTS: glInterleavedArrays( GL_C4UB_V3F, 0, g_points ); glDrawArrays( GL_POINTS, 0, 5 ); break;case GL_LINES:
glInterleavedArrays( GL_C4UB_V3F, 0, g_lines ); glDrawArrays( GL_LINES, 0, 6 ); break;case GL_LINE_STRIP:
glInterleavedArrays( GL_C4UB_V3F, 0, g_lineStrip_and_lineLoop ); glDrawArrays( GL_LINE_STRIP, 0, 6 ); break;case GL_LINE_LOOP:
glInterleavedArrays( GL_C4UB_V3F, 0, g_lineStrip_and_lineLoop ); glDrawArrays( GL_LINE_LOOP, 0, 6 ); break;case GL_TRIANGLES:
glInterleavedArrays( GL_C4UB_V3F, 0, g_triangles ); glDrawArrays( GL_TRIANGLES, 0, 6 ); break;case GL_TRIANGLE_STRIP:
glInterleavedArrays( GL_C4UB_V3F, 0, g_triangleStrip ); glDrawArrays( GL_TRIANGLE_STRIP, 0, 8 ); break;case GL_TRIANGLE_FAN:
glInterleavedArrays( GL_C4UB_V3F, 0, g_triangleFan ); glDrawArrays( GL_TRIANGLE_FAN, 0, 6 ); break;case GL_QUADS:
glInterleavedArrays( GL_C4UB_V3F, 0, g_quads ); glDrawArrays( GL_QUADS, 0, 12 ); break;case GL_QUAD_STRIP:
glInterleavedArrays( GL_C4UB_V3F, 0, g_quadStrip ); glDrawArrays( GL_QUAD_STRIP, 0, 8 ); break;case GL_POLYGON:
glInterleavedArrays( GL_C4UB_V3F, 0, g_polygon ); glDrawArrays( GL_POLYGON, 0, 5 ); break;default:
break; }SwapBuffers( _hDC );
} while (false); }/**
* 生成投影矩阵 * 后面为了重用性,我们会写一个专门的matrix类,完成矩阵的一系列擦做 * 这个是很有必须要的,当你对Opengl了解的不断深入,你会发现,很多都是和数学有关的 */ void perspective(float fovy,float aspect,float zNear,float zFar,float matrix[4][4]) { assert(aspect != float(0)); assert(zFar != zNear); #define PI 3.14159265358979323ffloat rad = fovy * (PI / 180);
float halfFovy = tan(rad / float(2));
matrix[0][0] = float(1) / (aspect * halfFovy); matrix[1][1] = float(1) / (halfFovy); matrix[2][2] = -(zFar + zNear) / (zFar - zNear); matrix[2][3] = -float(1); matrix[3][2] = -(float(2) * zFar * zNear) / (zFar - zNear); #undef PI } virtual void onInit() { /** * 调用父类的函数。 */ CELL::Graphy::CELLWinApp::onInit(); /** * 设置Opengl的投影方式,改例子里面,我们使用正交投影 * OpenGL的投影方式有两种(我知道的):正交,和透视,有兴趣的可以google下 * 这里采用的窗口坐标系,与Windows窗口坐标一直,左上角为 0,0,右下角为 _winWidth,_winHeight * 这种投影下绘制出来的物体没有三维感 */ //glOrtho(0,_winWidth,_winHeight,0,1,-1); //! 修改投影方式-透视投影, //! 指定我们要进行操作的矩阵,OpenGL是一个状态机,所以要操作那一个状态的时候,需要进行切换 //! 下面的这句话就是切换到投影矩阵上 //! gluPerspective细节实现,参照下面的网址:http://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xmlglMatrixMode( GL_PROJECTION );
#if 0 glLoadIdentity(); gluPerspective( 45.0, (GLdouble)_winWidth / (GLdouble)_winHeight, 0.1, 100.0); float mat[4][4]; glGetFloatv(GL_PROJECTION_MATRIX,(float*)mat);#else
//! 这里我们也可以自己按照Opengl的投影方式生成一个投影矩阵, //! 然后将投影矩阵给OpenGL GLfloat matrix[4][4] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; perspective(45.0f, (GLfloat)_winWidth / (GLfloat)_winHeight, 0.1f, 100.0f,matrix); glLoadMatrixf((float*)matrix);#endif glClearColor(0,0,0,1); }virtual int events(unsigned msg, unsigned wParam, unsigned lParam)
{ switch(msg) { case WM_KEYDOWN: { if (wParam == 'S' ||wParam == 'S') { _primitiveType += 1; if (_primitiveType >=GL_POLYGON ) { _primitiveType = 0; } } } break; } return __super::events(msg,wParam,lParam); }protected: unsigned _primitiveType;};int CALLBACK _tWinMain(
HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ){Tutorial2 winApp(hInstance);
winApp.start(640,480); return 0;}