OpenGL中的几种变换

合集下载

OpenGL应用编程接口文档

OpenGL应用编程接口文档

OpenGL1 OpenGL 特点1.建模:OpenGL图形库除了提供基本的点、线、多边形的绘制函数外,还提供了复杂的三维物体(球、锥、多面体、茶壶等)以及复杂曲线和曲面绘制函数。

2.变换:OpenGL图形库的变换包括基本变换和投影变换。

基本变换有平移、旋转、变比镜像四种变换,投影变换有平行投影(又称正射投影)和透视投影两种变换。

其变换方法有利于减少算法的运行时间,提高三维图形的显示速度。

3.颜色模式设置:OpenGL颜色模式有两种,即RGBA模式和颜色索引(Color Inde x)。

4.光照和材质设置:OpenGL光有辐射光(Emitted Light)、环境光(Ambient Ligh t)、漫反射光(Diffuse Light)和镜面光(Specular Light)。

材质是用光反射率来表示。

场景(Scene)中物体最终反映到人眼的颜色是光的红绿蓝分量与材质红绿蓝分量的反射率相乘后形成的颜色。

5.纹理映射(Texture Mapping)。

利用OpenGL纹理映射功能可以十分逼真地表达物体表面细节。

6.位图显示和图象增强图象功能除了基本的拷贝和像素读写外,还提供融合(Blendi ng)、反走样(Antialiasing)和雾(fog)的特殊图象效果处理。

以上三条可使被仿真物更具真实感,增强图形显示的效果。

7.双缓存动画(Double Buffering)双缓存即前台缓存和后台缓存,简言之,后台缓存计算场景、生成画面,前台缓存显示后台缓存已画好的画面。

此外,利用OpenGL还能实现深度暗示(Depth Cue)、运动模糊(Motion Blur)等特殊效果。

从而实现了消隐算法。

2 OpenGL 工作机制∙如何在OpenGL中表示3D物体∙OpenGL 的渲染流水线∙OpenGL中函数的命名规则2.1 OpenGL中3D物体的表示在3D空间中,场景是物体或模型的集合。

在3D图形渲染中,所有的物体都是由三角形构成的。

opengl 图形的变换与裁剪

opengl 图形的变换与裁剪
cos θ R −1 = R(−θ ) = − sin θ 0 sin θ cos θ 0 0 0 1 0 0 1
12
0 1/ sx 1 1 S −1 = S ( , ) = 0 1/ s y sx s y 0 0
复合二维变换
复合二维平移
3
关于齐次坐标
用一个n+1维向量表示一个n维向量
二维点(x,y),用(X,Y,ω)表示: (2,3)的齐次坐标表示可 以是(4,6,2)、(3,4.5,1.5) ω可以任意选取
齐次坐标与普通坐标之间是一一对应关系
x=X/ω y=Y/ω
ω
P
齐次坐标表示点的优势
防止浮点数溢出 矩阵变换的统一表示
X ω=1 平面 Y
局部坐标系可以简化物体的定义 物体={标准体素,变换}
造型变换:
物体从局部坐标系到世界坐标系的变换 三维线性和非线性变换
28
三维模型变换:平移
三维平移T:三维点P(x,y,z)移动(tx,ty,tz)后, 得到点P'(x',y',z')
x′ 1 ′ y = 0 z′ 0 1 0 0 1 0 0 0 t x x 0 t y y 1 t z z 0 1 1
y
P
P'
x
z
32
三维模型变换
绕z轴逆时针旋转θ角的旋转变换Rz (注: θ可以是(x,y,z)的函数)
x′ cosθ ′ y = sin θ z′ 0 1 0 − sin θ cosθ 0 0 0 0 x 0 0 y 1 0 z 0 1 1

gltranslatef函数

gltranslatef函数

gltranslatef函数
glTranslatef函数是一种OpenGL图形系统提供的基本函数,它的作用是改变图形的位置。

它接受三个参数,分别是X轴、Y轴和Z 轴的转换值。

它可以实现3D图形的平移操作,也可以用于2D图形的平移操作。

glTranslatef函数的一般语法如下:
glTranslatef (x, y, z);
其中,参数x,y,z是位移的量,表示在X,Y,Z轴上平移的距离。

glTranslatef函数可以用来实现对图形对象统一的平移操作,这样可以减少程序的开发和调试工作量,更加便捷。

同时,也可以用来在3D世界中实现物体的移动。

例如,要将一个物体平移到另一个位置,可以使用glTranslatef函数来实现,传递参数x,y,z表示物体在X,Y,Z轴上的位移。

在OpenGL中,图形的变换操作(包括缩放、旋转、平移等)都是以矩阵形式进行操作的。

在调用glTranslatef函数时,系统会使用一个4x4的矩阵来改变图形的位置,矩阵的第4列的四个元素就是glTranslatef传入的参数x,y,z。

glTranslatef函数是OpenGL中非常重要的一个函数,它可以实现最基本的平移操作:x,y,z轴上的位移。

同时,它也可以用于实现3D世界中物体移动的操作,因此,glTranslatef函数在OpenGL
图形系统中十分重要,也是非常常用的函数。

- 1 -。

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)在我的MFC单文档项目中enableview.h和enableview.cpp负责上面的窗口建立,myopenglview.h和myopenglView.cpp主要是功能的实现1.三维网格建立:void GLGrid(float pt1x, float pt1y, float pt1z, float pt2x, float pt2y, float pt2z, int num){const float _xLen = (pt2x - pt1x) / num;const float _yLen = (pt2y - pt1y) / num;const float _zLen = (pt2z - pt1z) / num; glLineWidth(2.f);glLineStipple(1, 0x0303);//线条样式glBegin(GL_LINES);glEnable(GL_LINE_SMOOTH);int xi = 0;int yi = 0;int zi = 0;//绘制平行于X的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;glVertex3f(pt1x, y, z);glVertex3f(pt2x, y, z);}}//绘制平行于Y的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, pt1y, z);glVertex3f(x, pt2y, z);}}//绘制平行于Z的直线for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, y, pt1z);glVertex3f(x, y, pt2z);}}glEnd();}void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH);}我们在ordination()函数中增加绘制x,y,z坐标的代码void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();//x//glTranslatef(-2, -2, -2);glColor3f(1.0f, 0.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(3.5, 0.0f, 0.0f);glEnd();glPushMatrix();glTranslatef(3.5, 0.0f, 0.0f);glRotatef(90.0f, 0.0f, 1.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//yglColor3f(0.0f, 1.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 3.5, 0.0f);glEnd();glPushMatrix();glTranslatef(0.0, 3.5, 0.0f);glRotatef(90.0f, -1.0f, 0.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//zglColor3f(0.0f, 0.0f, 1.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 0.0f, 3.5);glEnd();glPushMatrix();glTranslatef(0.0, 0.0f, 3.5);glRotatef(90.0f, 0.0f, 0.0f, 1.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH); }、2.基本三维图形创建点模型/线模型/面模型glColor3f(1.0f, 1.0f, 1.0f);if (model == 1){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidCube(4);}if (model == 2){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if(type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidSphere(3.0);}if (model == 3){glPushMatrix();glRotatef(90, -1.0, 0.0, 0.0);if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidCone(3, 3, 100, 100);glPopMatrix();}if (model == 4){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidTeapot(2.5);}3.鼠标相应旋转缩放BOOL enableview::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){// TODO: 在此添加消息处理程序代码和/或调用默认值double a = zDelta / 120;if ((scale + a * 0.1) < 10)scale += a * 0.1;this->InvalidateRect(NULL, FALSE);return CView::OnMouseWheel(nFlags, zDelta, pt);}void enableview::OnMouseMove(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值if (nFlags & MK_LBUTTON == TRUE) {//MessageBox("mouse move function triggered!", "attentino", MB_OK);du += point.x - oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了h += 0.03f*(point.y - oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了if (h>15.0f) h = 15.0f; //视点y坐标作一些限制,不会使视点太奇怪else if (h<-5.0f) h = -5.0f;oldmx = point.x, oldmy = point.y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备/*CString debug;debug.Format(_T("h,du= %0.3f %3d\n"), h, du);OutputDebugString(debug);*///OnPaint();this->OnDraw(this->GetDC()); //重绘界面}else if (nFlags & MK_RBUTTON == TRUE){oldmx += point.x - oldmx;oldmy += point.y - oldmy;glTranslatef(oldmx, oldmy, -0.1f);this->OnDraw(this->GetDC());oldmx = point.x, oldmy = point.y;}else {oldmx = point.x, oldmy = point.y;//OutputDebugString(_T("mouse up\n"));}//CView::OnMouseMove(nFlags, point);}4.键盘相应旋转缩放BOOL CmyopenglView::PreTranslateMessage(MSG* pMsg){if (pMsg->message == WM_KEYDOWN) // If a keydown message{if (pMsg->wParam == _T('W')){this->rotate_x += 6.0;if (this->rotate_x > 360)this->rotate_x = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('X')){this->rotate_x += 6.0;if (this->rotate_x < -360)this->rotate_x = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('A')){this->rotate_y -= 6.0;if (this->rotate_y < -360)this->rotate_y = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('D')){this->rotate_y += 6.0;if (this->rotate_y > 360)this->rotate_y = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Z')){this->rotate_z -= 6.0;if (this->rotate_z < -360)this->rotate_z = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('E')){this->rotate_z += 6.0;if (this->rotate_z > 360)this->rotate_z = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Q')){if ((scale + 2) < 10)scale += 2;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('R')){scale -= 2;this->InvalidateRect(NULL, FALSE);}}return CView::PreTranslateMessage(pMsg);}5.灯光设置:单方位灯光/多方位光/多种类型光效果// 设置材质颜色GLfloat mat_ambient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; // 蓝色的材质环境光GLfloat mat_diffuse[] = { 0.6f, 0.6f, 0.9f, 1.0f }; // 蓝色的材质漫反射光GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // 全白色的材质镜面反射光GLfloat mat_emission[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // 淡白色的材质辐射光GLfloat no_mat[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 无光(黑色光),用于关闭某种属性光时应用GLfloat no_shininess[] = { 0.0f }; // 无镜面反射GLfloat low_shininess[] = { 5.0f }; // 低镜面反射指数GLfloat high_shininess[] = { 70.0f }; // 高镜面反射指数void CmyopenglView::InitalLigt(){GLfloat light_position1[4] = { -52, -16, -50, 0 };GLfloat light_position2[4] = { -26, -48, -50, 0 };GLfloat light_position3[4] = { 16, -52, -50, 0 };GLfloat direction1[3] = { 52, 16, 50 };GLfloat direction2[3] = { 26, 48, 50 };GLfloat direction3[3] = { -16, 52, 50 };GLfloat light_position4[4] = { 52, 16, 50, 0 };GLfloat light_position5[4] = { 26, 48, 50, 0 };GLfloat light_position6[4] = { -16, 52, 50, 0 };GLfloat direction4[3] = { -52, -16, -50 };GLfloat direction5[3] = { -26, -48, -50 };GLfloat direction6[3] = { 16, -52, -50 };GLfloat color1[4], color2[4], color3[4], color4[4], color5[4], color6[4];glClearColor(1, 1, 1, 0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);if (color_type == 0) { //彩色灯光color1[0] = 1; color1[1] = 0; color1[2] = 0; color1[3] = 1;color2[0] = 0.5; color2[1] = 1; color2[2] = 0; color2[3] = 1;color3[0] = 0; color3[1] = 0; color3[2] = 1; color3[3] = 1;color4[0] = 1; color4[1] = 0; color4[2] = 0; color4[3] = 1;color5[0] = 0.5; color5[1] = 1; color5[2] = 0; color5[3] = 1;color6[0] = 0; color6[1] = 0; color6[2] = 1; color6[3] = 1;GLfloat ambient[4] = { 0.3f, 0.3f, 0.3f, 1.0f };GLfloat material_color[4] = { 1, 1, 1, 0.5f };GLfloat material_specular[4] = { 0.5f, 0.5f, 0.5f, 0.5f };GLfloat material_ambient[4] = { 0.0, 0.0, 0.0, 0.0 };glLightfv(GL_LIGHT3, GL_POSITION, light_position4);glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, direction4);glLightfv(GL_LIGHT3, GL_DIFFUSE, color4);glLightfv(GL_LIGHT3, GL_SPECULAR, color4);glLightfv(GL_LIGHT4, GL_POSITION, light_position5);glLightfv(GL_LIGHT4, GL_SPOT_DIRECTION, direction5);glLightfv(GL_LIGHT4, GL_DIFFUSE, color5);glLightfv(GL_LIGHT4, GL_SPECULAR, color5);glLightfv(GL_LIGHT5, GL_POSITION, light_position6);glLightfv(GL_LIGHT5, GL_SPOT_DIRECTION, direction6);glLightfv(GL_LIGHT5, GL_DIFFUSE, color6);glLightfv(GL_LIGHT5, GL_SPECULAR, color6);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_color);glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128);glDisable(GL_LIGHT0);glDisable(GL_LIGHTING);glEnable(GL_LIGHTING);glEnable(GL_LIGHT3);glEnable(GL_LIGHT4);glEnable(GL_LIGHT5);glDisable(GL_COLOR_MATERIAL);return;}if (color_type == 1){//白色灯光glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);GLfloat m_LightPostion[4] = { 0.0f, 10.0f, 10.0f, 1.0f };GLfloat ambientLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };GLfloat diffuseLight[] = { 0.5, 0.5f, 0.5f, 1.0f };GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);}else {glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);glDisable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);//glDisable(GL_LIGHTING);GLfloat no_ambientLight[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 用于关掉默认的全局环境光// 设置光源的颜色GLfloat ambientLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色环境光GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色漫射光GLfloat specularLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色镜面反射光GLfloat m_LightPostion[] = { 0.0f, 0.0f, 1.0f, 0.0f }; // 光源起始位置// 1.仅漫射光if (color_type == 12) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); // 关闭材质的环境反射光颜色glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); // 设置mat_diffuse的材质漫反射光glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); //关闭材质的镜面反射光颜色glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); // 设置材质的镜面反射指数为0glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); // 关闭材质的辐射光glEnable(GL_LIGHT0);}// 2.仅镜面光if (color_type == 13) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 3.漫射光与低镜面光if (color_type == 16) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 4.辐射光与低镜面光if (color_type == 18) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);glEnable(GL_LIGHT0);}}}6.纹理载入映射BOOL CmyopenglView::LoadImageResources() {FILE *File = NULL;AUX_RGBImageRec* textrue_Resource[6];if (model == 5 && type == 51)resource_path[0] = "shuijing.bmp";if(model == 5 && type == 52 )resource_path[0] = "earth.bmp";if (model == 5 && type == 53)resource_path[0] = "painting1.bmp";if (model == 5 && type == 54)resource_path[0] = "5.bmp";/*resource_path[1] = "image/2.bmp";resource_path[2] = "image/3.bmp";resource_path[3] = "image/4.bmp";resource_path[4] = "image/5.bmp";resource_path[5] = "image/6.bmp";*///装载图像文件资源for (int i = 0; i < 6; i++)//如果只需要一张贴图其实resource_path数组只需要一个元素就可以了{File = fopen(resource_path[0], "r");if (!File){//MessageBox(NULL, "加载图像资源文件失败!", "Fail", MB_OK);return FALSE;}fclose(File);CString str = CString(resource_path[0]);USES_CONVERSION;LPCWSTR wszClassName = A2CW(W2A(str));textrue_Resource[i] = auxDIBImageLoad(wszClassName);File = NULL;}//生成纹理glGenTextures(6, texture);for (int i = 0; i < 6; i++){glBindTexture(GL_TEXTURE_2D, texture[i]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//Use the mipmap textureglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, \textrue_Resource[i]->sizeX, textrue_Resource[i]->sizeY, \GL_RGB, GL_UNSIGNED_BYTE, textrue_Resource[i]->data);//删除堆上的临时图像delete textrue_Resource[i]->data;delete textrue_Resource[i];}return TRUE;}void CmyopenglView::Draw_textrue() {GLUquadricObj* qobj;glClearColor(0.0, 0.0, 0.0, 0.0);glShadeModel(GL_FLAT);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);InitalLigt(); ///初始化光照信息glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);glPushMatrix();glTranslatef(0.0f, 0.0f, scale); //滚轮缩放gluLookAt(r*cos(c*du), h, r*sin(c*du), 0, 0, 0, 0, 1, 0); //从视点看远点,y轴方向(0,1,0)是上方向,鼠标拖动glRotatef(this->rotate_x, 1.0, 0.0, 0.0);glRotatef(this->rotate_y, 0.0, 1.0, 0.0);glRotatef(this->rotate_z, 0.0, 0.0, 1.0);if (iao)ordination();glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);qobj = gluNewQuadric();//画球体glBindTexture(GL_TEXTURE_2D, texture[0]);glEnable(GL_TEXTURE_2D);gluQuadricTexture(qobj, GL_TRUE);//纹理函数if (type == 51){glBegin(GL_QUADS);// Front FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);// Back FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, -3.0f);// Top FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);// Bottom FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, -3.0f, 3.0f);// Right faceglTexCoord2f(0.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);// Left FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glEnd();}if( type == 52 )gluSphere(qobj, 4, 60, 60);//二次曲面qobjif( type == 53 )gluCylinder(qobj, 3.5, 3.5, 6, 26, 23);if( type == 54 )gluCylinder(qobj, 3.5, 0.0, 6, 26, 23);glPopMatrix();glDisable(GL_TEXTURE_2D);}6.读取obj模型我只是简单的读取vt,vn,f等基本参数void CmyopenglView::ReadObj(char* Filename) {VN.clear();V.clear();VT.clear();F.clear();FQ.clear();ifstream in(Filename);string aline; //逐行读入string erase;while (getline(in, aline)){if (aline[0] == 'v'){if (aline[1] == 'n') //vn{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;VN.push_back(v);}else if (aline[1] == 't')//vt{istringstream sin(aline);Texture v;sin >> erase >> v.s >> v.t;VT.push_back(v);}else //v{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;V.push_back(v);}}else if (aline[0] == 'f'){istringstream sin(aline);sin >> erase;vector<string> strvector;string temp;while (sin >> temp) {strvector.push_back(temp);}if (strvector.size() == 3) {//三角面片Face fff;for (int count = 0; count < 3; count++) {string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}F.push_back(fff);}else if (strvector.size() == 4){FaceQ fff;for (int count = 0; count < strvector.size(); count++) { string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}FQ.push_back(fff);}}}}绘制obj模型:void CmyopenglView::OnReadobj(){model = 6;wchar_t filters[] =L"3D模型文件(*.obj)\|*.obj|所有文件(*.*)|*.*||";CFileDialog fileDlg(TRUE, NULL, NULL,OFN_HIDEREADONL Y, filters);if (fileDlg.DoModal() == IDOK){CString strBuf = fileDlg.GetPathName();USES_CONVERSION;char *Filename = T2A(strBuf.GetBuffer(0));ReadObj(Filename);}stringstream ss;ss <<"OK!";string str;ss >> str;CString s;s = str.c_str();MessageBox(s);float min_x, min_y, min_z, max_x, max_y, max_z;min_x = min_y = min_z = 10000000;max_x = max_y = max_z = -1000000;for (int i = 0; i < V.size(); i++){min_x = min(min_x, V[i].x);min_y = min(min_y, V[i].y);min_z = min(min_z, V[i].z);max_x = max(max_x, V[i].x);max_y = max(max_y, V[i].y);max_z = max(max_z, V[i].z);}worldx = (min_x + max_x) / 2;worldy = (min_y + max_y) / 2;worldz = (min_z + max_z) / 2;type = 1;Invalidate();CDC* ppDC = GetWindowDC();OnDrawGL(ppDC);// TODO: 在此添加命令处理程序代码}void CmyopenglView::Draw_obj(){if (type == 1) {if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}else if (type == 3) {glBegin(GL_POINTS);for (int i = 0; i < V.size(); i++)glV ertex3f(V[i].x, V[i].y, V[i].z);glEnd();}else{if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glNormal3f(VN[F[i].vn[j] - 1].x, VN[F[i].vn[j] - 1].y, VN[F[i].vn[j] - 1].z);glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glNormal3f(VN[FQ[i].vn[j] - 1].x, VN[FQ[i].vn[j] - 1].y, VN[FQ[i].vn[j] - 1].z);glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else{for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}}。

OpenGL图形编程3二维观察与三维变换(陈永强)

OpenGL图形编程3二维观察与三维变换(陈永强)
行投影(正射投影),另一种是透视投影。
在投影变换之前必须指定当前处理的是投影
变换矩阵: glMatrixMode(GL_PROJECTION); glLoadIdentity();
34
3.2.5投影变换
平行投影
视景体是一个矩形的平行管道,也就是一个长方
体,其特点是无论物体距离相机多远,投影
后的物体大小尺寸不变。
OpenGL图形编程
武汉纺织大学数学与计算机学院 授课教师:陈永强 教授
1
3. OpenGL二维观察与三维变换
3.1二维观察 3.2三维变换
2
3. 1OpenGL二维观察
实现二维观察的步骤:
3.1.1指定矩阵堆栈 3.1.2指定裁剪窗口 3.1.3指定视区
3
3.1.1指定矩阵堆栈
这段程序中,先声明了一个数组来保存 4×4 矩阵的值,注意这里
矩阵按列优先顺序保存,这意味着先从上往下遍历每一列;
然后使用glLoadMatrix函数将定义的矩阵设置为当前操作的矩阵 。
18
3.2.2模型视图矩阵
如果需要执行变换,即把定义的矩阵乘到模型视图矩阵
中。 可以使用函数 glMultmatrix,其函数原型如下: void glMultMatrix{fd}(const TYPE *m); 参数 m 为一个以列优先顺序保存16个连续值的数组。
换和模型变换是相同的,把这两者分开完全是为了程 序员的方便,向后移动对象和向前移动参考系之间并 没有本质差别。术语“模型视图”表示你可以把这类 变换视为模型变换或视图变换,但实际上并无区别, 因此称它为模型视图变换。
12
3.2.1变换种类
投影变换:对视见空间进行修剪和改变大小;

第四章OpenGL图形变换(一)

第四章OpenGL图形变换(一)

第四章 OpenGL 图形变换OpenGL 图形变换是OpenGL 技术体系的核心内容之一,它的最主要功能是让虚拟世界里的物体动起来,是虚拟世界的动力驱动系统,也可以称之三维图形系统的引擎!OpenGL 图形变换的主要内容包括几何变换、投影变换、裁剪变换、视口变换等,本章尽量以通俗易懂的方式来讲解各技术要点。

4. 1 图形变换浅说OpenGL 图形变换和照相是非常相似的,它们之间的关系大致描述如下。

1、视点变换(View Transformation ) 视点变换相当于把相机放到一定的位置上,镜头对准场景。

如图4-1所示。

图4-1 视点变换与相机定位在OpenGL中,默认情况下,视点变换相当于把相机放到世界坐标系的原点(0,0,0),镜头指向Z轴的负方向,相当于从世界坐标系的原点向屏幕内部的虚拟场景观察。

2、模型变换(Model Transformation)模型变换相当于场景中人物或对象位置的变化、角度的改变和大小的改变。

图4-2 虚拟照相场景中的人物YXZ观察方向X照相时场景中的人物或对象需要作调整,以便他们位于场景中合适的位置上。

有此时候人物不在视野范围内时,还要走动一下,进入镜头场景内,方向不对时,还要转动一下,眼睛转向镜头。

比如图4-2所示,照相时,警察不在镜头场景内,他需要向后向移动。

中间的企鹅背对镜头,他需要转过向来面向镜头。

企鹅向左边的气球中吹气,气球变大。

调整后的场景如图4-3所示。

图4-3 虚拟照相场景中的调整后人物或对象上述调整过程中的人员移动 和企鹅的转身动作 和气球充气变大 都属于模型变换。

3、投影变换(Projection Transformation ) 投影变换相当于调整相机镜头焦距,放大或缩小景物(如图4-4所示)。

图4-4 投影变换与相机焦距调整OpenGL 中投影变换的本质功能是定义一个视景体,使视景体外的多余部分被裁剪掉,再把景物变换到一个规则投影体(高、宽、深均为2个单位的立方体)。

OpenGL空间(坐标系)变换

OpenGL空间(坐标系)变换

OpenGL空间(坐标系)变换⽹友的《3D图形学的学习策略》⼀⽂使我深受启发,在图形学以及openGL学习⽅⾯给了我很有价值的指导性意见,在此对前辈们的不吝赐教表⽰感激,谢谢你们的⽆私分享。

如⽂章所说,API是⼯具,不是本质,OpenGL/Direct3D的本质是图形学,⽽不是OpenGL/Direct3D的本⾝,API的本⾝只是⼀些Interface⽽已。

最重要的,最根本的是,你要明⽩这些API背后的图形学的原理---因为那才是根本中的根本。

其实很多事情,包括学习也涉及到⽣活,只有抓住了本质,才能体会到其中的真谛。

带着这种希望探究本质的学习⽅法,结合图形学原理,通过阅读书⽬和⽹友们的⽂章,我对OpenGL⼏何空间变换进⾏了总结性的学习。

OpenGL处理管线的⽬的是将对象的三维描述转换为可以显⽰的⼆维图像。

为了完成这个从三维到⼆维的转换,OpenGL 使⽤了多个空间(坐标系),每个空间完成特定的任务,从⼀个空间到另⼀个空间需要进⾏空间转换。

理解OpenGL所使⽤的各种空间以及它们间的变换是⾮常重要的。

如上图所⽰,openGL中使⽤的空间依次是:对象空间、世界空间、视点空间、裁剪空间、归⼀化设备空间、窗⼝空间、屏幕空间。

结合⾃⼰的理解,就每个空间完成的基本任务和空间的变换关系,总结如下。

对象空间。

对象空间中完成的最⼤任务是对象建模,三维对象的属性,包括顶点位置和表⾯法线等是在这个空间内指定的。

这个空间的坐标原点⼀般在对象上,有时候也在其他地⽅,主要是为了建模⽅便。

每⼀个对象都有⼀个⾃⼰的对象空间。

就openGL⽽⾔,我⽬前还没有接触到建⽴很复杂模型的应⽤,建模⼀般在其他地⽅如3DMAX中完成,然后读⼊openGL进⾏处理。

世界空间。

对象空间之后是世界空间,我理解为世界坐标系是固定不变的。

世界空间主要是对三维场景进⾏描述,就是把已经建⽴的各种对象摆放在三维空间中,空间的转换是通过模型变换完成的。

可以通过平移、旋转、⽐例缩放等把对象摆放在需要的位置,就好像买好家具以后设计房间布局⼀样。

OpenGL功能简介

OpenGL功能简介

OpenGL渲染流水线(4/20 )
熟练掌握渲染流水线是学习好OpenGL和 图形学的关键,渲染流水线也是学习 OpenGL和图形学的纲领 以后的每一章节基本上是对流水线某一部 分的展开阐述 总而言之,对于OpenGL本身,这套流水 线机制是最重要的,应该时时复习和回顾
OpenGL渲染流水线(5/20)
glGetBooleanv() glGetDoublev() glGetFloatv() glGetIntegerv() glGetPointerv() glIsEnabled()
OpenGL渲染流水线(1/20)
大多数OpenGL应用程序都采用一个相似 的操作顺序,这一系列处理阶段被称作 OpenGL的渲染流水线(Pipeline)
GL_TRIANGLES GL_QUADS GL_QUAD_STRIP GL_TRIANGLE_STRIP GL_TRIANGLE_FAN
OpenGL基本功能(4/11)
物体建模与图元(Primitive)绘制
物体建模的意思就是将物体用图元(Primitive) 表示,由于三点决定一个平面,所以物体常 用三角面片来表示,三角面片越多,物体越 复杂 OpenGL提供了各种图元的绘制函数,以及一 些复杂三维物体(球、锥、多面体、茶壶)、 曲线曲面(贝塞尔、NURBS)的绘制函数
显示列表 Display list
光栅化 RasterizationBiblioteka 帧缓存 Framebuffer
像素操作 Pixel operations 像素数据 Pixel data 纹理装配 Texture assembly
OpenGL渲染流水线(3/20 )
OpenGL的渲染流水线的构架基于计算机 图形学的基本原理 对于一个实际的OpenGL程序,并不一定 会应用渲染流水线中的每一步操作

OpenGL库函数大全

OpenGL库函数大全

1.OpenGL核心库核心库包含有115个函数,函数名的前缀为gl。

这部分函数用于常规的、核心的图形处理。

此函数由gl.dll来负责解释执行。

由于许多函数可以接收不同数以下几类。

据类型的参数,因此派生出来的函数原形多达300多个。

核心库中的函数主要可以分为以下几类函数:(1)绘制基本几何图元的函数。

如绘制图元的函数glBegain()、glEnd()、glNormal*()、glV ertex*()。

(2)矩阵操作、几何变换和投影变换的函数。

如矩阵入栈函数glPushMatrix()、矩阵出栈函数glPopMatrix()、装载矩阵函数glLoadMatrix()、矩阵相乘函数glMultMatrix(),当前矩阵函数glMatrixMode()和矩阵标准化函数glLoadIdentity(),几何变换函数glTranslate*()、glRotate*()和glScale*(),投影变换函数glOrtho()、glFrustum()和视口变换函数glViewport()等等。

(3)颜色、光照和材质的函数。

如设置颜色模式函数glColor*()、glIndex*(),设置光照效果的函数glLight*() 、glLightModel*()和设置材质效果函数glMaterial()等等。

(4)显示列表函数、主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glCallList()和glDeleteLists()。

(5)纹理映射函数,主要有一维纹理函数glTexImage1D()、二维纹理函数glTexImage2D()、设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()等。

(6)特殊效果函数。

融合函数glBlendFunc()、反走样函数glHint()和雾化效果glFog*()。

OpenGL图形变换

OpenGL图形变换

OpenGL图形变换OpenGL图形软件包是为三维应用设计的,其中包含了大量的有关三维变换的操作,二维变换则可以看作是三维变换的特例。

OpenGL中常用的变换包括模型视图变换、投影变换和视见区变换。

一、矩阵堆栈在计算机图形学中,所有的变换都是通过矩阵乘法来实现的,即将三维形体顶点构成的齐次坐标矩阵乘以三维变换矩阵就得到了变换后的形体顶点的齐次坐标矩阵,这样只要求出形体的三维变换矩阵,就可以得到变换后的形体。

在OpenGL中,对象的坐标变换也是通过矩阵来实现的。

OpenGL中包含了两个重要的矩阵:模型视图矩阵和投影矩阵,其中模型视图矩阵用于物体的模型视图变换,投影矩阵用于投影变换。

一般来说,在进行矩阵操作之前,需要指定当前操作的矩阵对象,这可以使用函数:glMatrixMode(GLenum mode);定义。

其中当mode取GL_MODELVIEW时,表示对模型视图矩阵进行操作;当mode取GL_PROJECTION时表示对投影矩阵进行操作,并且一旦设置了当前操作矩阵,它就将保持为当前的矩阵对象,直到再次调用函数glMatrixMode修改它为止。

默认情况下,系统处理的当前矩阵是模型视图矩阵。

OpenGL为模型视图矩阵和投影矩阵各维护着一个“矩阵堆栈”,其中堆栈的栈顶矩阵就是当前的模型视图矩阵或投影矩阵。

在调用变换函数的时候,系统自动计算变换函数对应的变换矩阵与当前操作的矩阵堆栈栈顶矩阵的乘积,并置为栈顶矩阵,绘制图形时使用栈顶矩阵作为图形的变换矩阵。

矩阵堆栈主要用来保存和恢复矩阵的状态。

OpenGL中利用函数:void glPushMatrix(void);void glPopMatrix(void);实现矩阵堆栈的操作。

其中函数glPushMatrix将当前矩阵堆栈的栈顶矩阵复制一个,并将其压入当前矩阵堆栈,以保存当前变换矩阵。

函数glPopMatrix用于将当前矩阵堆栈的栈顶矩阵弹出,这样,堆栈中的下一个矩阵变为栈顶矩阵(当前变换矩阵),用来恢复当前变换矩阵原先的状态。

OpeGL之坐标变换

OpeGL之坐标变换

OpenGL通过相机模拟、可以实现计算机图形学中最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换等,同时,OpenGL还实现了矩阵堆栈等。

理解掌握了有关坐标变换的内容,就算真正走进了精彩地三维世界。

一、OpenGL中的三维物体的显示(一)坐标系统在现实世界中,所有的物体都具有三维特征,但计算机本身只能处理数字,显示二维的图形,将三维物体及二维数据联系在一起的唯一纽带就是坐标。

为了使被显示的三维物体数字化,要在被显示的物体所在的空间中定义一个坐标系。

这个坐标系的长度单位和坐标轴的方向要适合对被显示物体的描述,这个坐标系称为世界坐标系。

世界坐标系是始终固定不变的。

OpenGL还定义了局部坐标系的概念,所谓局部坐标系,也就是坐标系以物体的中心为坐标原点,物体的旋转或平移等操作都是围绕局部坐标系进行的,这时,当物体模型进行旋转或平移等操作时,局部坐标系也执行相应的旋转或平移操作。

需要注意的是,如果对物体模型进行缩放操作,则局部坐标系也要进行相应的缩放,如果缩放比例在案各坐标轴上不同,那么再经过旋转操作后,局部坐标轴之间可能不再相互垂直。

无论是在世界坐标系中进行转换还是在局部坐标系中进行转换,程序代码是相同的,只是不同的坐标系考虑的转换方式不同罢了。

计算机对数字化的显示物体作了加工处理后,要在图形显示器上显示,这就要在图形显示器屏幕上定义一个二维直角坐标系,这个坐标系称为屏幕坐标系。

这个坐标系坐标轴的方向通常取成平行于屏幕的边缘,坐标原点取在左下角,长度单位常取成一个象素。

(二)三维物体的相机模拟为了说明在三维物体到二维图象之间,需要经过什么样的变换,我们引入了相机(Camera)模拟的方式,假定用相机来拍摄这个世界,那么在相机的取景器中,就存在人眼和现实世界之间的一个变换过程。

图一、相机模拟OpenGL中的各种坐标变换从三维物体到二维图象,就如同用相机拍照一样,通常都要经历以下几个步骤:1、将相机置于三角架上,让它对准三维景物,它相当于OpenGL中调整视点的位置,即视点变换(Viewing Transformation)。

OpenGL坐标 逆变换和模拟变换

OpenGL坐标 逆变换和模拟变换

逆变换和模拟变换几何处理管线擅长使用视图和投影矩阵以及用于裁剪的视口把顶点的世界(物体)坐标变换为窗口(屏幕)坐标。

但是,在有些情况下,需要反转这个过程。

一种常见的情形就是应用程序的用户利用鼠标选择了三维空间中的一个位置。

鼠标只返回一个二维值,也就是鼠标光标的屏幕位置。

因此,应用程序必须反转变换过程,确定这个屏幕位置源于三维空间的什么地方。

OpenGL工具函数库中gluUnProject()和gluUnProject4()函数用于执行这种逆变换操作。

只要提供一个经过变换的顶点的三维窗口坐标以及所有对它产生影响的变换,gluUnProject()就可以返回这个顶点的源物体坐标。

如果深度范围不是默认的[0, 1],应该使用gluUnProject4()函数。

int gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,const GLdouble modelMatrix[16],const GLdouble projMatrix[16],const GLint viewport[4],GLdouble *objx, GLdouble *objy, GLdouble *objz);这个函数使用由模型视图矩阵(modelMatrix)、投影矩阵(projMatrix)和视口(viewpo rt)定义的变换,把指定的窗口坐标(winx, winy, winz)映射到物体坐标。

它产生的物体坐标是在o bjx、objy和objz中返回的。

这个函数返回GL_TRUE(表示成功)或GL_FALSE(表示失败,例如矩阵不可逆)。

这个函数并不会使用视口对坐标进行裁剪,也不会消除那些位于glDepthRange()范围之外的深度值。

对变换过程进行逆操作存在一些固有的难度。

二维屏幕上的一个位置可以来自于三维空间中一条直线上的任意一点。

为了消除这种歧义,gluUnProject()要求提供一个窗口深度坐标(win z),它是根据glDepthRange()函数指定的。

OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理

OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理

OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理单位矩阵对角线上都是1,其余元素皆为0的矩阵。

在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,我们称这种矩阵为单位矩阵.它是个方阵,除左上角到右下角的对角线(称为主对角线)上的元素均为1以外全都为0.OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x',y',z',h),其中x=x'/h; y=y'/h; z=z'/h. 通常h取1. 比如空间中的点(2,3,4),在OpenGL中将表示成(2,3,4,1). 齐次坐标表示方式适合于矩阵运算,也很方便地表示了无穷远的点,比如(1,0,0,0)就表示x轴上无穷远的点,因为1/0是无穷大,这里约定0/0=0.接着要说点矩阵(线性代数)的知识。

OpenGL里面的平移、旋转、缩放等变换均是线性变换,用矩阵相乘来表示。

以平移变换为例,请见官方对glTranslatef 函数的说明。

假设有点(3,3,3),如果把该点沿x轴移动2单位,沿y轴移动3单位,沿z轴移动4单位,那么该点会是(3+2, 3+3, 4+4) = (5,6,7). 用矩阵表示是:左边的矩阵称为平移变换矩阵,若把2、3、4换成x、y、z,则用它乘以一个齐次坐标表示的向量,就可以将该向量平移(x,y,z). 旋转变换和缩放变换都像平移变换一样可用一个矩阵来表示。

这里可以不用理会这些矩阵长什么样,只需清楚它们乘以一个齐次坐标表示的向量,就可以使该向量发生需要的变换。

把平移变换矩阵记为T(x,y,z),旋转变换矩阵记为R(x,y,z,s),表示绕向量(x,y,z)旋转s角度;把向量记为X。

这里只需要知道它们是矩阵就行了,现在要把一个点X,如(3,3,3,1),移动(2,2,2)单位,再绕y轴旋转30度角,用矩阵表示即R(0,1,0,30)*T(2,2,2)*X,可以理解为离X最近的矩阵最先作用。

OpenGL ES总结(二)OpenGL坐标变换之平移及旋转

OpenGL ES总结(二)OpenGL坐标变换之平移及旋转

OpenGL ES总结(二)OpenGL坐标变换之平移及旋转世界坐标系:在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。

你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。

长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。

当前绘图坐标系:是绘制物体时的坐标系。

程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。

当用glTranslatef(),glScalef(), glRotatef()等对当前绘图坐标系进行平移、伸缩、旋转变换之后,世界坐标系和当前绘图坐标系不再重合。

注意,这里的平移旋转是将当前绘图坐标系看做一个整体在世界坐标系中进行旋转平移。

然后,改变以后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相对当前绘图坐标系来讲的。

其中四种坐标经常要在程序中用到:世界坐标,物体坐标,设备坐标和眼坐标。

1、世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。

我们用这个坐标系来描述物体及光源的位置。

将物体放到场景中也就是将物体平移到特定位置、旋转一定角度,这些操作就是坐标变换。

OpenGL中提供了glTranslate*/glRotate*/glScale*三条坐标变换命令,利用OpenGL的矩阵运算命令,则可以实现任意复杂的坐标变换。

OpenGL中有一个坐标变换矩阵栈(ModelView),栈顶就是当前坐标变换矩阵,进入OpenGL 管道的每个坐标(齐次坐标)都会先乘上这个矩阵,结果才是对应点在场景中的世界坐标。

OpenGL中的坐标变换都是通过矩阵运算完成的,与图形学课本的描述完全一致。

要注意的是变换中的矩阵乘法是左乘,而矩阵乘法与算术乘法不同,不符合交换律(万一不明白去看矩阵代数书好了)。

基于OpenGL三维图形的开发

基于OpenGL三维图形的开发

纹理映射(Texture Mapping):利用OpenGL纹理映射功能可以十分 逼真地表达物体表面细节。 位图显示和图象增强:图象功能除了基本的拷贝和像素读写外,还提 供融合(Blending)、反走样(Antialiasing)和雾(fog)的特殊图 象效果处理。以上三条可是被仿真物更具真实感,增强图形显示的效 果。
用户必须从点、线、面等最基本的图形单 元开始构造自己的三维模型
OpenGL提供了以下的对三维物体的绘制 方式:
网格线绘图方式(wireframe):这种方式仅绘制三维物体的网格轮廓 线。 深度优先网格线绘图方式(depth_cued):用网格线方式绘图,增加 模拟人眼看物体一样,远处的物体比近处的物体要暗些。 反走样网格线绘图方式(antialiased):用网格线方式绘图,绘图时采 用反走样技术以减少图形线条的参差不齐。 平面消隐绘图方式(flat_shade):对模型的隐藏面进行消隐,对模型 的平面单元按光照程度进行着色但不进行光滑处理。
OpenGL具体功能
模型绘制:OpenGL能够绘制点、线和多边形。应用这些基 本的形体,我们可以构造出几乎所有的三维模型。 OpenGL通常用模型的多边形的顶点来描述三维模型。如 何通过多边形及其顶点来描述三维模型,在指南的在后续 章节会有详细的介绍。 模型观察:在建立了三维景物模型后,就需要用OpenGL描 述如何观察所建立的三维模型。观察三维模型是通过一系 列的坐标变换进行的。模型的坐标变换在使观察者能够在 视点位置观察与视点相适应的三维模型景观。在整个三维 模型的观察过程中,投影变换的类型决定观察三维模型的 观察方式,不同的投影变换得到的三维模型的景象也是不 同的。最后的视窗变换则对模型的景象进行裁剪缩放,即 决定整个三维模型在屏幕上的图象。

详解OpenGL的坐标系、投影和几何变换

详解OpenGL的坐标系、投影和几何变换

详解OpenGL的坐标系、投影和几何变换作者:charlee 按:我也是在迷茫中走过来的,初学OpenGL时,略微了解了一些有关变换的基本知识,但是却不知道具体的使用方法,因此经常需要在布置场景时反复调整各种参数。

当我终于有一天明白了它们的用法时,就觉得应该把这些心得体会写下来,让那些和我一样曾经迷茫过的人能够迅速地找到出路。

本文的读者对象为那些初学OpenGL,了解了一些坐标系、几何变换等基本知识,但是又不知道具体应该如何运用这些操作的人。

如果你对OpenGL一无所知,建议你先去学学OpenGL的基本知识。

1 坐标系OpenGL中使用的坐标系有两种,分别为世界坐标系和屏幕坐标系。

世界坐标系即OpenGL内部处理时使用的三维坐标系,而屏幕坐标系即为在计算机屏幕上绘图时使用的坐标系。

通常,OpenGL所使用的世界坐标系为右手型,如下图所示。

从计算机屏幕的角度来看,x轴正方向为屏幕从左向右,y轴正方向为屏幕从下向上,z轴正方向为屏幕从里向外。

而进行旋转操作时需要指定的角度θ的方向则由右手法则来决定,即右手握拳,大拇指直向某个坐标轴的正方向,那么其余四指指向的方向即为该坐标轴上的θ角的正方向(即θ角增加的方向),在上图中用圆弧形箭头标出。

2 投影将世界坐标系中的物体映射到屏幕坐标系上的方法称为投影。

投影的方式包括平行投影和透视投影两种。

平行投影的投影线相互平行,投影的结果与原物体的大小相等,因此广泛地应用于工程制图等方面。

透视投影的投影线相交于一点,因此投影的结果与原物体的实际大小并不一致,而是会近大远小。

因此透视投影更接近于真实世界的投影方式。

B 平行投影B透视投影xzy 02.1 平行投影OpenGL 中使用下面的函数来设置投影方式为平行投影。

glOrtho(xleft, xright, ybottom, ytop, znear, zfar); 各参数的含义如下图所示。

注意,只有位于立方体之内的物体才可见。

实验3 OpenGL几何变换

实验3 OpenGL几何变换

实验3OpenGL几何变换1.实验目的理解并掌握O penGL二维平移、旋转、缩放变换的方法。

2.实验内容(1)阅读实验原理,运行示范实验代码,掌握0penGL程序平移、旋转、缩放变换的方法。

(2)根据示范代码,完成实验作业。

3.实验原理(1)OpenGL下的几何变换在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义。

平移矩阵构造函数为glTranslate<f,d>(t x,ty,tz),作用是把当前矩阵和一一个表示移动物体的矩阵相乘。

t x、 ty、 tz指定这个移动物体的矩阵,它们可以是任意的实数值,后缀为f (单精度浮点fl oat)或d(双精度浮点double),对于二维应用来说, tz=0.0。

旋转矩阵构造函数为glRotate<f,d>(theta, vx, vy, vz),作用是把当前矩阵和一个表示旋转物体的矩阵相乘。

theta, vx, vy, vz指定这个旋转物体的矩阵,物体将围绕(0,0,0)到(x,y,z) 的直线以逆时针旋转, 参数theta表示旋转的角度.向量 v=(v x,vy,vz)的分量可以是任意的实数值,该向量用于定义通过坐标原点的旋转轴的方向,后缀为 f(单精度浮点f l oat)或d (双精度浮点double),对于二维旋转来说, vx=0.0, vy=0.0, vz=1.0。

缩放矩阵构造函数为glScale<f,d>(sx, sy, sz),作用是把当前矩阵和一个表示缩放物体的矩阵相乘。

sx, sy, sz指定这个缩放物体的矩阵,分别表示在x, y, z方向上的缩放比例, 它们可以是任意的实数值,当缩放参数为负值时,该函数为反射矩阵,缩放相对于原点进行,后缀为 f(单精度浮点fl oat)或d(双精度浮点double)。

注意这里都是说“把当前矩阵和一个表示移动<旋转, 缩放>物体的矩阵相乘”, 而不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的, 马上就会讲到。

OpenGL的空间变换(下):空间变换

OpenGL的空间变换(下):空间变换

OpenGL的空间变换(下):空间变换通过本⽂的上篇,我们了解到矩阵的基础概念。

并且掌握了矩阵在空间⼏何中的应⽤。

接下来,我们将结合矩阵来了解 OpenGL 的空间变换。

在使⽤ OpenGL 的应⽤程序中,当我们指定了模型的顶点后,顶点依次会变换到不同的 OpenGL 空间中:世界空间模型空间(也称为对象空间)视图空间(也称为视点空间、摄像机空间)裁剪空间标准设备坐标空间窗⼝空间在经过这⼀系列的空间变换之后,顶点才会被显⽰在屏幕上。

世界空间(World Space)世界空间相对于其他坐标空间来说是固定不变的。

所以,它也被⽤作空间变换的参考系。

我们把它的坐标系称为世界坐标系。

在没有特别说明的情况下,我们⽤来描述⼀个⼏何对象(点、向量或坐标)的数值数据,都是基于世界坐标系来设定的。

世界坐标系⽤矩阵来表⽰就是⼀个单位矩阵。

模型空间(Model Space)模型空间,也称为对象空间。

如果把世界空间⽐作现实世界的话,那么模型就好⽐⼀座房⼦或者房⼦⾥的⼀个⼈等等。

假设以⼈的重⼼为原点,正⾯向前的⽅向为 z-轴,头顶的⽅向为 y-轴,左侧⽅向为 x-轴来构建⼀个坐标系。

我们可以⽤这个坐标系来描述这个⼈⾃⾝的模型空间。

这个坐标系也称为模型坐标系(或对象坐标系)。

模型坐标系并不是绝对的,如果以⼈的⿐尖为原点,头顶的⽅向改为 z-轴,正⾯向前的⽅向为 y-轴,右侧⽅向为 z-轴来构建其模型坐标系。

这个模型坐标系同样可以⽤来描述这个⼈⾃⾝的模型空间。

只不过⽤不同坐标系来描述时,描述出来的数据不⼀定相同。

⼀般来说,我们都是基于世界坐标系来描述模型坐标系的。

在这种情况下,世界坐标系可以看作是模型坐标系的⽗坐标系:其中,⿊⾊的坐标系为世界坐标系;灰⾊的坐标系为模型坐标系。

模型变换(模型-世界变换)默认情况下模型坐标系的原点位于世界坐标系的原点,并且坐标轴的⽅向与世界坐标系的坐标轴⼀致。

我们可以通过⼀系列的缩放、旋转和*移,将模型以任意⾓度摆在任意位置上。

glViewport()和glOrtho()的理解-OpenGL

glViewport()和glOrtho()的理解-OpenGL

glViewport()和glOrtho()的理解-OpenGL在OpenGL中有两个比较重要的投影变换函数,glViewport和glOrtho.ortho实际上是orthographic projection正交投影的缩写。

glViewport是视口变换它是设置视口,它设置的视口的左下角,以及宽度和高度。

glOrtho是窗口变换,设置的是世界窗口俗称窗口。

二维绘图来说世界窗口由gluOrth2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)设定。

三维绘图的世界窗口由glOrtho(left, right, bottom, top, near, far)设定。

glOrtho是创建一个正交平行的视景体。

一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。

比如,常用的工程中的制图等。

需要比较精确的显示。

而作为它的对立情况, glFrustum则产生一个透视投影。

这是一种模拟真是生活中,人们视野观测物体的真实情况。

例如:观察两条平行的火车到,在过了很远之后,这两条铁轨是会相交于一处的。

还有,离眼睛近的物体看起来大一些,远的物体看起来小一些。

glOrtho(left, right, bottom, top, near, far), left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。

这个函数简单理解起来,就是一个物体摆在那里,你怎么去截取他。

这里,我们先抛开glViewport函数不看。

先单独理解glOrtho的功能。

假设有一个球体,半径为1,圆心在(0, 0, 0),那么,我们设定glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽高都是3的框框把这个球体整个都装了进来。

如果设定glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽是1.5,高是3的框框把整个球体的右面装进来;如果设定glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10);就表示用一个宽和高都是1.5的框框把球体的右上角装了进来。

第四章OpenGL图形变换-gluLookAt用法

第四章OpenGL图形变换-gluLookAt用法

gluLookAt 的用法1、设置视点(设置相机位置及形态) 视点设置相当于把相机放到一定的位置上,镜头对准场景。

如图1所示。

图1 视点变换与相机定位在OpenGL 中,默认情况下,设置视点(视点变换)相当于把相机放到世界坐标系的原点(0,0,0),相机水平,镜头指向Z 轴的负方向,相当于从世界坐标系的原点向屏幕内部的虚拟场景观察。

2、选择视景体方式一:通过函数glFrustum()指定,如图2所示。

图2 glFrustum 生成的透视投影体YXZ Y YXZ观察方向方式二:通过函数gluPerspective 指定视景体,如图3所示。

图4-7 平行投影模型图图3 gluPerspective 生成的透视投影体YXZ Y3、移动景物(已实现)(借助于glTranslate 、glRotate 、glScale 等)移动前:图4 移动前物体移动后:图5 移动后物体(模型变换)XYX观察方向4、移动视点(移动相机)此处是我们要实现的功能。

用到的函数是:gluLookAt.函数原型:gluLookAt(GLdouble eyex, GLdouble eyey, Ldouble eyez,GLdouble centerx , GLdouble centery ,GLdouble centerz ,GLdouble upx , GLdouble upy ,GLdouble centerz );图6 gluLookAt示意图移动视点,就是调整相机的位置和形态,然后在新位置和方向处选择视景体,如下图所示。

图7 任意位置和形态的相机原始(默认)的相机位置可用如下语句来表述:gluLookAt(0, 0 , 0 ,0 , 0 , -1 ,0 , 1 ,0);简单的做法是:(1(2)在与Z轴负向平行的方向上选择观察中心点;也就是相机与观察中心点的连线形成的向量与X轴正向夹角为90度。

(3)移动相机假定此时,相机的位置为(eyex , eyey , eyez), 观察中心点的位置为(centerx , centery , centerz),R与X轴的夹角为90度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OpenGL中的几种变换
OpenGL中的各种转换是通过矩阵运算实现的,具体的说,就是当发出一个转换命令时,该命令会生成一个4X4阶的转换矩阵(OpenGL中的物体坐标一律采用齐次坐标,即(x, y, z, w),故所有变换矩阵都采用4X4矩阵),当前矩阵与这个转换矩阵相乘,从而生成新的当前矩阵。

例如,对于顶点坐标v ,转换命令通常在顶点坐标命令之前发出,若当前矩阵为C,转换命令构成的矩阵为M,则发出转换命令后,生成的新的当前矩阵为CM,这个矩阵再乘以顶点坐标v,从而构成新的顶点坐标CMv。

上述过程说明,程序中绘制顶点前的最后一个变换命令最先作用于顶点之上。

这同时也说明,OpenGL编程中,实际的变换顺序与指定的顺序是相反的。

(一)视点变换
视点变换确定了场景中物体的视点位置和方向,就向上边提到的,它象是在场景中放置了一架照相机,让相机对准要拍摄的物体。

确省时,相机(即视点)定位在坐标系的原点(相机初始方向都指向Z负轴),它同物体模型的缺省位置是一致的,显然,如果不进行视点变换,相机和物体是重叠在一起的。

执行视点变换的命令和执行模型转换的命令是相同的,想一想,在用相机拍摄物体时,我们可以保持物体的位置不动,而将相机移离物体,这就相当于视点变换;另外,我们也可以保持相机的固定位置,将物体移离相机,这就相当于模型转换。

这样,在OpenGL中,以逆时针旋转物体就相当于以顺时针旋转相机。

因此,我们必须把视点转换和模型转换结合在一起考虑,而对这两种转换单独进行考虑是毫无意义的。

除了用模型转换命令执行视点转换之外,OpenGL实用库还提供了gluLookAt()函数,该函数有三个变量,分别定义了视点的位置、相机瞄准方向的参考点以及相机的向上方向。

该函数的原型为:
该函数定义了视点矩阵,并用该矩阵乘以当前矩阵。

eyex,eyey,eyez定义了视点的位置;centerx、centery和centerz变量指定了参考点的位置,该点通常为相机所瞄准的场景中
心轴线上的点;upx、upy、upz变量指定了向上向量的方向。

通常,视点转换操作在模型转换操作之前发出,以便模型转换先对物体发生作用。

场景中物体的顶点经过模型转换之后移动到所希望的位置,然后再对场景进行视点定位等操作。

模型转换和视点转换共同构成模型视景矩阵。

(二)模型变换
模型变换是在世界坐标系中进行的。

缺省时,物体模型的中心定位在坐标系的中心处。

OpenGL在这个坐标系中,有三个命令,可以模型变换。

1、模型平移
该函数用指定的x,y,z值沿着x轴、y轴、z轴平移物体(或按照相同的量值移动局部坐标系)。

2、模型旋转
该函数中第一个变量angle制定模型旋转的角度,单位为度,后三个变量表示以原点(0,0,0)到点(x,y,z)的连线为轴线逆时针旋转物体。

例如,glRotatef(45.0,0.0,0.0,1.0)的结果是绕z轴旋转45度。

3、模型缩放
该函数可以对物体沿着x,y,z轴分别进行放大缩小。

函数中的三个参数分别是x、y、z轴方向的比例变换因子。

缺省时都为1.0,即物体没变化。

程序中物体Y轴比例为2.0,其余都为1.0,就是说将立方体变成长方体。

(三)投影变换
经过模型视景的转换后,场景中的物体放在了所希望的位置上,但由于显示器只能用二维图象显示三维物体,因此就要靠投影来降低维数(投影变换类似于选择相机的镜头)。

事实上,投影变换的目的就是定义一个视景体,使得视景体外多余的部分裁剪掉,最终进入图像的只是视景体内的有关部分。

投影包括透视投影(Perspective Projection)
和正视投影(Orthographic Projection)两种。

透视投影,符合人们心理习惯,即离视点近的物体大,离视点远的物体小,远到极点即为消失,成为灭点。

它的视景体类似于一个顶部和底部都被进行切割过的棱椎,也就是棱台。

这个投影通常用于动画、视觉仿真以及其它许多具有真实性反映的方面。

OpenGL透视投影函数有两个,其中函数glFrustum()的原型为:
它创建一个透视视景体。

其操作是创建一个透视投影矩阵,并且用这个矩阵乘以当前矩阵。

这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。

near和far表示离视点的远近,它们总为正值。

该函数形成的视景体如图三所示。

图三、透视投影视景体
另一个透视函数是:
它也创建一个对称透视视景体,但它的参数定义于前面的不同,参数fovy定义视野在X-Z平面的角度,范围是[0.0, 180.0];参数aspect是投影平面宽度与高度的比率;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。

图四、透视投影视景体
以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向。

正射投影,又叫平行投影。

这种投影的视景体是一个矩形的平行管道,也就是一个长方体,如图五所示。

正射投影的最大一个特点是无论物体距离相机多远,投影后的物体大小尺寸不变。

这种投影通常用在建筑蓝图绘制和计算机辅助设计等方面,这些行业要求投影后的物体尺寸及相互间的角度不变,以便施工或制造时物体比例大小正确。

图五、正射投影视景体
OpenGL正射投影函数也有两个,一个函数是:
它创建一个平行视景体。

实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。

其中近裁剪平面是一个矩形,矩形左下角点三维空间坐标是(left,bottom,-near),右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。

所有的near 和far值同时为正或同时为负。

如果没有其他变换,正射投影的方向平行于Z轴,且视点朝向Z负轴。

这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。

另一个函数是:
它是一个特殊的正射投影函数,主要用于二维图像到二维屏幕上的投影。

它的near和far缺省值分别为-1.0和1.0,所有二维物体的Z坐标都为0.0。

因此它的裁剪面是一个左下角点为(left,bottom)、右上角点为(right,top)的矩形。

相关文档
最新文档