基于OpenGL的三维图形绘制实验

基于OpenGL的三维图形绘制实验
基于OpenGL的三维图形绘制实验

基于OpenGL的三维图形绘制实验

目录

实验题目:交互图形程序设计基础实验 (3)

1.实验目的 (3)

2.实验内容 (3)

2.1 实验内容 (3)

2.2 实验任务 (3)

3.实验过程 (4)

3.1 预处理 (4)

3.3 主要函数说明 (5)

3.4 过程描述 (6)

3.5 运行截图 (7)

4.实验结果 (7)

5.实验体会 (7)

实验题目:交互图形程序设计基础实验1.实验目的

1)理解并掌握三维基本图形数据结构表示方法。

2)掌握编写OpenGL图形程序的基本方法.

3)掌握OpenGL基本图形表示及绘制。

2.实验内容

2.1 实验内容

基于OpenGL的三维图形绘制实验目的是掌握图形信息的表示、数据的组织,在此基础上基于OpenGL绘制出三维图形。实验内容包括OpenGL编程环境搭建、OpenGL程序结构、基本数据类型、核心函数等的使用;基本图形的绘制(点、线段、折线、闭合折线、多边形、三角形、三角扇、三角条带、四边形、四边形条带等)及图形属性控制(线宽、颜色、线型、填充样式等);对指定的若干三维模型进行建模、绘制,在一个程序框架下实现,提交1次程序,1份实验报告。

2.2 实验任务

1、使用Visual C++建立一个单文档(SDI)程序,完成OpenGL绘制框架程序的设计。在此基础上参照提供的资料,定义绘制函数,基于自定义的若干点坐标与颜色,分别绘制绘制点、线段、不闭合折线、闭合折线、多边形、三角形、四边形、三角扇、三角条带、四边形条带。

2、使用1中建立的程序框架,完成如下任务:

(1)绘制正棱柱(底面多变形的边数及高度可以通过对话框输入)

(2)正棱锥(底面多变形的边数及高度可以通过对话框输入)

(3)正棱台(底面多变形的边数、台高、锥高可以通过对话框输入)

注意模型坐标系的选择和顶点坐标的计算,每个图形的绘制单独写成函数。加入菜单绘制三、四、五、六边的情况,其他边数情况从弹出对话框中输入参数,然后绘制。实际绘制要绘制成表面着色图,如下线框图仅供参考。

图 1

3.实验过程

3.1 建立Open程序框架

1. 设置好 OpenGL 编程环境:

使用 Microsoft 公司实现的 OpenGL 库

( 1)头文件:检查 VC 的\Include\GL 下是否有 OpenGL 开发库的头文件 gl.h、

glu.h、 glaux.h以及 glut.h

( 2)链接导入库文件:检查 VC 的\Lib 目录下是否opengl32.lib、 glu32.lib、glaux.lib 以及 glut32.lib

( 3)程序运行需要的动态链接库:系统目录下 opengl32.dll、 glu32.dll、

glut32.dll

2. 启动 Visual C++ 6.0,选择[New]菜单,在 New 对话框中建立图形程序的MFC工程,工程名为CG2016112455 兰红林 02

3. 测试OpenGL的环境。

4. OpenGL设置像素格式和逻辑色板

在CG2016112455 兰红林 02View.cpp中添加如下代码,并在CG2016112455 兰红林 02View.h中添加相应的函数声明:

//设置窗口的像素格式(自定义方法)

BOOL CCG201611245502View::SetupPixelFormat(void)

{

PIXELFORMATDESCRIPTOR pfd =

{

sizeof(PIXELFORMATDESCRIPTOR), // pfd 结构的大小

1, // 版本号

PFD_DRAW_TO_WINDOW | // 支持在窗口中绘图

PFD_SUPPORT_OPENGL | // 支持 OpenGL

PFD_DOUBLEBUFFER, // 双缓存模式

PFD_TYPE_RGBA, // RGBA 颜色模式

24, // 24 位颜色深度

0, 0, 0, 0, 0, 0, // 忽略颜色位

0, // 没有非透明度缓存

0, // 忽略移位位

0, // 无累加缓存

0, 0, 0, 0, // 忽略累加位

32, // 32 位深度缓存

0, // 无模板缓存

0, // 无辅助缓存

PFD_MAIN_PLANE, // 主层

0, // 保留

0, 0, 0 // 忽略层,可见性和损毁掩模

};

int iPixelFormat;

// 为设备描述表得到最匹配的像素格式

if((iPixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0) {

MessageBox("ChoosePixelFormat Failed", NULL, MB_OK);

return FALSE;

}

// 设置最匹配的像素格式为当前的像素格式(一个窗口的像素格式只能被设置一次)

if(SetPixelFormat(m_pDC->GetSafeHdc(), iPixelFormat, &pfd) == FALSE) {

MessageBox("SetPixelFormat Failed", NULL, MB_OK);

return FALSE;

}

if(pfd.dwFlags & PFD_NEED_PALETTE)

SetLogicalPalette();//设置逻辑调色板

return TRUE;

}

//设置逻辑调色板(自定义方法)

void CCG201611245502View::SetLogicalPalette(void)

{

struct

{

WORD Version;

WORD NumberOfEntries;

PALETTEENTRY aEntries[256];

} logicalPalette = { 0x300, 256 };

BYTE reds[] = {0, 36, 72, 109, 145, 182, 218, 255};

BYTE greens[] = {0, 36, 72, 109, 145, 182, 218, 255};

BYTE blues[] = {0, 85, 170, 255};

for (int colorNum=0; colorNum<256; ++colorNum)

{

logicalPalette.aEntries[colorNum].peRed =

reds[colorNum & 0x07];

logicalPalette.aEntries[colorNum].peGreen =

greens[(colorNum >> 0x03) & 0x07];

logicalPalette.aEntries[colorNum].peBlue =

blues[(colorNum >> 0x06) & 0x03];

logicalPalette.aEntries[colorNum].peFlags = 0;

}

//创建逻辑调色板

m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette);

}

3.2 程序分析

设备的在当前像素格式下的坐标范围为-1.0f –1.0f ,为了方便设置顶点,所有的图形都采用菜单来绘制,一次只显示一种图形,下一次绘制时清屏。

在CG2016112455 兰红林02View.cpp源文件中引用菜单,添加菜单命令。设置一个全局变量m_mode来确定当前绘制的内容,点击菜单时改变m_mode的值,并调用OnPaint 函数来刷新屏幕,再调用相应的绘制函数来绘图。

自定义绘制三维图形时,绘制正棱柱和正棱锥需要两个参数:高度和边数,绘制棱台时需要设置三个参数,棱台的高,棱锥的高和边数。这些数据需要通过对话框来获取,所以需要设计两个对话框。

3.3 过程描述

3.3.1 菜单和对话框设计

1)、添加两个对话框类CDialogDraw和CDialogDraw2;界面如下:

图2. CDialogDraw

图3. CDialogDraw2

2)、菜单栏设计如下:

图4. 二维画图

图5. 正棱柱

图6. 正棱锥

图7. 棱台

3)、添加菜单响应事件

BEGIN_MESSAGE_MAP(CCG201611245502View, CScrollView) //{{AFX_MSG_MAP(CCG201611245502View)

ON_WM_CREATE()

ON_WM_DESTROY()

ON_WM_SIZE()

ON_COMMAND(ID_POINT, OnDrawPoint)

ON_COMMAND(ID_LINE, OnDrawLine)

ON_COMMAND(ID_NONE_BROKENLINE, OnDrawUnBrokenLine) ON_COMMAND(ID_BROKENLINE, OnDrawBrokenLine)

ON_COMMAND(ID_POLYGON, OnDrawPoligon)

ON_COMMAND(ID_TRIANGLE, OnDrawTriangle)

ON_COMMAND(ID_QUADRANGLE, OnDrawQuadrangle)

ON_COMMAND(ID_TRIANGLE_FAN, OnDrawTriangleFan)

ON_COMMAND(ID_TRIANGLE_STRIPS, OnDrawTriangleStrips)

ON_COMMAND(ID_QUADRANGLE_STRIPS, OnDrawQuadrangleStrips)

ON_COMMAND(ID_PRISM_THREE, OnDrawPrismThree)

ON_COMMAND(ID_PRISM_FOUR, OnDrawPrismFour)

ON_COMMAND(ID_PRISM_FIVE, OnDrawPrismFive)

ON_COMMAND(ID_PRISM_SIX, OnDrawPrismSix)

ON_COMMAND(ID_PRISM_OTHER, OnDrawPrismOther)

ON_COMMAND(ID_PYRAMID_THREE, OnDrawPyramidThree)

ON_COMMAND(ID_PYRAMID_FOUR, OnDrawPyramidFour)

ON_COMMAND(ID_PYRAMID_FIVE, OnDrawPyramidFive)

ON_COMMAND(ID_PYRAMID_SIX, OnDrawPyramidSix)

ON_COMMAND(ID_PYRAMID_OTHER, OnDrawPyramidOther)

ON_COMMAND(ID_TRUSTUM_PYRAMID_THREE, OnDrawTrustumPyramidThree) ON_COMMAND(ID_TRUSTUM_PYRAMID_FOUR, OnDrawTrustumPyramidFour)

ON_COMMAND(ID_TRUSTUM_PYRAMID_FIVE, OnDrawTrustumPyramidFive)

ON_COMMAND(ID_TRUSTUM_PYRAMID_SIX, OnDrawTrustumPyramidSix)

ON_COMMAND(ID_TRUSTUM_PYRAMID_OTHER, OnDrawTrustumPyramidOther) //}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) END_MESSAGE_MAP()

//设置场景

BOOL CCG201611245502View::RenderScene(void)

{

//调用 OpenGL 绘图函数进行图形绘制

//根据需要自行修改,也可在派生类中重载此函数

//本例中以绘制一个三棱柱

if(m_mode==0)

Point();

else if(m_mode == 2)

Line();

else if(m_mode == 3)

UnBrokenLine();

else if(m_mode == 4)

BrokenLine();

else if(m_mode == 5)

Poligon();

else if(m_mode == 6)

Triangle();

else if(m_mode == 7)

Quadrangle();

else if(m_mode == 8)

TriangleFan();

else if(m_mode == 9)

TriangleStrips();

else if(m_mode == 10)

QuadrangleStrips();

else if(m_mode == 11)

Prism(3, 0.8);

else if(m_mode == 12)

Prism(4, 0.8);

else if(m_mode == 13)

Prism(5, 0.8);

else if(m_mode == 14)

Prism(6, 0.8);

else if(m_mode == 15)

{

CDialogDraw dlg;

if(dlg.DoModal()==IDOK)

{

Prism(dlg.side, dlg.height);

}

}

else if(m_mode == 16)

Pyramid(3,0.8);

else if(m_mode == 17)

Pyramid(4,0.8);

else if(m_mode == 18)

Pyramid(5,0.8);

else if(m_mode == 19)

Pyramid(6,0.8);

else if(m_mode == 20)

{

CDialogDraw dlg;

if(dlg.DoModal()==IDOK)

{

Pyramid(dlg.side, dlg.height);

}

}

else if(m_mode == 21)

TrustumPyramid(3, 0.8, 0.5);

else if(m_mode == 22)

TrustumPyramid(4, 0.8, 0.5);

else if(m_mode == 23)

TrustumPyramid(5, 0.8, 0.5);

else if(m_mode == 24)

TrustumPyramid(6, 0.8, 0.5);

else if(m_mode == 25)

{

CDialogDraw2 dlg;

if(dlg.DoModal()==IDOK)

{

TrustumPyramid(dlg.side, dlg.total_height, dlg.part_height);

}

}

//else cube();

return TRUE;

}

void CCG201611245502View::OnDrawQuadrangleStrips()

{

m_mode = 10;

OnPaint();

}

void CCG201611245502View::OnDrawTriangleStrips()

{

m_mode = 9;

OnPaint();

}

void CCG201611245502View::OnDrawTriangleFan()

{

m_mode = 8;

OnPaint();

}

void CCG201611245502View::OnDrawQuadrangle()

{

m_mode = 7;

OnPaint();

}

void CCG201611245502View::OnDrawTriangle()

{

m_mode = 6;

OnPaint();

}

void CCG201611245502View::OnDrawPoligon()

{

m_mode = 5;

OnPaint();

}

void CCG201611245502View::OnDrawBrokenLine() {

m_mode = 4;

OnPaint();

}

void CCG201611245502View::OnDrawUnBrokenLine() {

m_mode = 3;

OnPaint();

}

void CCG201611245502View::OnDrawLine()

{

m_mode = 2;

OnPaint();

}

void CCG201611245502View::OnDrawPrismThree() {

m_mode = 11;

OnPaint();

}

void CCG201611245502View::OnDrawPrismFour() {

m_mode = 12;

OnPaint();

}

void CCG201611245502View::OnDrawPrismFive() {

m_mode = 13;

OnPaint();

}

void CCG201611245502View::OnDrawPrismSix() {

m_mode = 14;

OnPaint();

void CCG201611245502View::OnDrawPrismOther()

{

m_mode = 15;

OnPaint();

}

void CCG201611245502View::OnDrawPyramidThree()

{

m_mode = 16;

OnPaint();

}

void CCG201611245502View::OnDrawPyramidFour()

{

m_mode = 17;

OnPaint();

}

void CCG201611245502View::OnDrawPyramidFive()

{

m_mode = 18;

OnPaint();

}

void CCG201611245502View::OnDrawPyramidSix()

{

m_mode = 19;

OnPaint();

}

void CCG201611245502View::OnDrawPyramidOther()

{

m_mode = 20;

OnPaint();

}

void CCG201611245502View::OnDrawTrustumPyramidThree() {

m_mode = 21;

OnPaint();

}

void CCG201611245502View::OnDrawTrustumPyramidFour() {

m_mode = 22;

OnPaint();

}

void CCG201611245502View::OnDrawTrustumPyramidFive()

m_mode = 23;

OnPaint();

}

void CCG201611245502View::OnDrawTrustumPyramidSix()

{

m_mode = 24;

OnPaint();

}

void CCG201611245502View::OnDrawTrustumPyramidOther()

{

m_mode = 25;

OnPaint();

}

3.3.2 主要函数说明

3.3.2.1 画点

void CCG201611245502View::Point()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

glColor3f(1.0, 0.0, 0.0);

glBegin(GL_POINTS);

glPointSize(5);

glVertex2f(0.0, 0.0);

glVertex2f(0.1, 0.1);

glVertex2f(0.1, 0.2);

glVertex2f(0.1, 0.3);

glVertex2f(0.1, 0.4);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.2 画线

void CCG201611245502View::Line()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glClearColor(0.0, 0.0, 0.0, 0.0);

//glClear(GL_COLOR_BUFFER_BIT);

glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

glBegin(GL_LINES);

glColor3f(1.0,0.0,0.0);

glVertex3f(0.25,0.25,0);

glVertex3f(0.75,0.25,0);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.3 画不闭合折线

void CCG201611245502View::UnBrokenLine()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

glColor3f(1.0, 0.0, 0.0);

glBegin( GL_LINE_STRIP);

glVertex2f( 0.0f, 0.0f);

glVertex2f( -0.3f, 0.1f);

glVertex2f( 0.1f, 0.8f);

glVertex2f( 0.4f, 0.6f);

glEnd();

glFinish();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.4 画闭合折线

void CCG201611245502View::BrokenLine()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

glColor3f(1.0, 0.0, 0.0);

glBegin( GL_LINE_LOOP);

glVertex2f( 0.0f, 0.0f);

glVertex2f( -0.3f, 0.1f);

glVertex2f( 0.1f, 0.8f);

glVertex2f( 0.4f, 0.6f);

glEnd();

glFinish();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.5 画多边形

void CCG201611245502View::Poligon()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

glBegin(GL_POLYGON);

glColor3f(1.0,0.0,0.0);

glVertex3f(0.25,0.25,0);

glVertex3f(0.5,0,0);

glVertex3f(0.75,0.25,0);

glVertex3f(0.75,0.75,0);

glVertex3f(0.25,0.75,0);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.6 画三角形

void CCG201611245502View::Triangle()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glutInitWindowPosition(300, 300);

glBegin(GL_TRIANGLES);

glColor3f(1.0,0.0,0.0);

glVertex2f(-0.5f, -0.5f);

glVertex2f(0.0f, -0.3f);

glVertex2f(0.5f, 0.8f);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.7 四边形

void CCG201611245502View::Quadrangle()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glutInitWindowPosition(300, 300);

glColor3f(0.0, 1.0, 1.0);

glBegin(GL_QUADS);

glVertex2f(-0.3, 0.1);

glVertex2f(-0.4, 0.1);

glVertex2f(-0.5, 0.3);

glVertex2f(-0.4, 0.5);

glVertex2f(-0.5, 0.1);

glVertex2f(-0.6, 0.1);

glVertex2f(-0.7, 0.3);

glVertex2f(-0.6, 0.5);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.8 画三角扇

void CCG201611245502View::TriangleFan()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glutInitWindowPosition(300, 300);

glBegin(GL_TRIANGLE_FAN);

glColor3f(1.0, 0.0, 1.0);

glVertex2f(0.0f, -0.25f);

glColor3f(0.0, 1.0, 1.0);

glVertex2f(0.5f, -0.25f);

glColor3f(0.0, 0.0, 1.0);

glVertex2f(0.4f, 0.0f);

glColor3f(0.0, 1.0, 0.0);

glVertex2f(0.2f, 0.15f);

glColor3f(1.0, 0.0, 0.0);

glVertex2f(0.0f, 0.2f);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.9 画三角条带

void CCG201611245502View::TriangleStrips()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glutInitWindowPosition(300, 300);

glBegin(GL_TRIANGLE_STRIP);

glColor3f(1.0, 0.0, 1.0);

glVertex2f(0.0f, -0.25f);

glColor3f(0.0, 1.0, 1.0);

glVertex2f(0.5f, -0.25f);

glColor3f(0.0, 0.0, 1.0);

glVertex2f(0.4f, 0.0f);

glColor3f(0.0, 1.0, 0.0);

glVertex2f(0.2f, 0.15f);

glColor3f(1.0, 0.0, 0.0);

glVertex2f(0.0f, 0.2f);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.10 画四边形条带

void CCG201611245502View::QuadrangleStrips()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//glutInitWindowPosition(300, 300);

glBegin(GL_QUAD_STRIP);

glColor3f(1.0, 1.0, 0.0);

glVertex2f(-0.3, 0.5);

glColor3f(0.0, 1.0, 0.0);

glVertex2f(-0.4, 0.4);

glColor3f(1.0, 0.0, 0.0);

glVertex2f(-0.5, 0.3);

glColor3f(1.0, 0.0, 1.0);

glVertex2f(-0.4, 0.2);

glColor3f(0.0, 1.0, 1.0);

glVertex2f(-0.5, 0.1);

glColor3f(0.0, 1.0, 0.0);

glVertex2f(-0.6, 0.0);

glColor3f(0.0, 0.0, 1.0);

glVertex2f(-0.7, 0.3);

glColor3f(1.0, 0.0, 0.0);

glVertex2f(-0.6, 0.5);

glEnd();

glPopMatrix();

glFlush();

SwapBuffers(m_pDC->GetSafeHdc());

}

3.3.2.11 画正棱柱

参数n为边数,height表示半高。

void CCG201611245502View::Prism(int n, float height)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存

glPushMatrix();

//int n = 3; //面

float length = 0.5f;

float rangle = 360.0/n;

int i,j;

GLfloat (*vtx)[3]= new GLfloat[2*n][3];

for(i=0; i

{

j = i*rangle;

if(i < n)

{

vtx[i][0] = length*cos(j/180.0 * PI); vtx[i][1] = length*sin(j/180.0 * PI); vtx[i][2] = height;

vtx[n+i][0] = length*cos(j/180.0 * PI); vtx[n+i][1] = length*sin(j/180.0 * PI); vtx[n+i][2] = (-1)*height;

}

}

GLfloat color[6][3] = //三棱柱顶点颜色

{

{0.0f,0.0f,1.0f},

{0.0f,1.0f,1.0f},

{1.0f,1.0f,1.0f},

{1.0f,0.0f,1.0f},

{1.0f,0.0f,0.0f},

{0.0f,1.0f,0.0f}

};

glRotatef(10.0f,1.0f,0.0f,0.0f); //沿x轴旋转30度(旋转的角度,旋转的对称轴(x,z,y))

glBegin(GL_POLYGON); //各个面的顶点连接顺序(从体外向体内看,顺时针或逆时针)要一致

//顶面,注意各点的连接顺序

//glNormal3fv(norm[0]);

j = 0;

for(i=0; i

{

glColor3fv(color[j]);

glVertex3fv(vtx[i]);

j++;

if(j == 6)

j = 0;

}

//底面

for(i=0; i

{

glColor3fv(color[j]);

glVertex3fv(vtx[n+i]);

j++;

if(j == 6)

j = 0;

}

glEnd();

//侧面

glBegin(GL_QUADS);

for(i=0; i

{

//glNormal3fv(norm[2]);

glColor3fv(color[j%6]);

glVertex3fv(vtx[i]);

glColor3fv(color[(j+1)%6]);

glVertex3fv(vtx[i+n]);

glColor3fv(color[(j+2)%6]);

glVertex3fv(vtx[((i+n+1)==2*n)?n:(i+n+1)]);

glColor3fv(color[(j+3)%6]);

glVertex3fv(vtx[((i+1)==n)?0:(i+1)]);

j = j+4;

}

glEnd();

glPopMatrix();

相关主题
相关文档
最新文档