VS2012下基于Glut 矩阵变换示例程序2:
在VS2012下基于Glut 矩阵变换示例程序:中我们在绘制甜圈或者圆柱时使用矩阵对相应的坐标进行变换后自己绘制甜圈或者圆柱。我们也可以使用glLoadMatrixf、glLoadMatrixd载入变换矩阵后直接使用Glut提供的函数绘制甜圈。这里我在载入变换矩阵后再去绘制坐标轴,所以在程序运行时坐标轴会随着定时器绕Y轴旋转。点击鼠标右键在弹出的菜单里面可以选择是否显示坐标轴、正视图还是透视视图、是否打印变换矩阵。
源代码在VS2012下基于Glut 矩阵变换示例程序:只修改了:
GlutTransformDemo.cpp
// GlutTransformDemo.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <gl/glut.h>
#include <math.h>
#include "math3d.h"
//圆周率宏
#define GL_PI 3.1415f
//获取屏幕的宽度
GLint SCREEN_WIDTH=0;
GLint SCREEN_HEIGHT=0;
//设置程序的窗口大小
GLint windowWidth=400;
GLint windowHeight=300;
//绕x轴旋转角度
GLfloat xRotAngle=0.0f;
//绕y轴旋转角度
GLfloat yRotAngle=0.0f;
//受支持的点大小范围
GLfloat sizes[2];
//受支持的点大小增量
GLfloat step;
//最大的投影矩阵堆栈深度
GLint iMaxProjectionStackDepth;
//最大的模型视图矩阵堆栈深度
GLint iMaxModeviewStackDepth;
//最大的纹理矩阵堆栈深度
GLint iMaxTextureStackDepth;GLint iCoordinateaxis=2;//是否显示坐标轴
GLint iProjectionMode=1;//投影模式
GLint iPrintMatrix=1;//是否打印变换矩阵
void changSize(GLint w,GLint h);void DrawTorus(M3DMatrix44f mTransform){ // 大圆只存在于 xy 平面, // 小圆存在于 xyz 空间中, // 其圆心是大圆圆周上的点。 // 小圆环大圆半径方向为起始旋转一周形成的。 // 由于 z 轴垂直于 xy 平面, // 又因为大圆的半径位于 xy 平面, // 因此,z 轴垂直于大圆的半径(垂直于面,垂直于线), // 因此,z 轴与大圆的半径方向是正交的。 // 小圆位于 z 轴与大圆半径方向形成的平面, // 后面计算具体点的位置是基于上面的描述。 // 大圆半径 GLfloat majorRadius = 55.0f; // 小圆半径 GLfloat minorRadius = 15.0f; // 大圆圆周被切分的点数 GLint numMajor = 50; // 小圆圆周被切分的点数 GLint numMinor = 20; M3DVector3f objectVertex; // Vertex in object/eye space M3DVector3f transformedVertex; // New Transformed vertex // 每个点对应的弧度数 double majorStep = 2.0f*M3D_PI / numMajor; double minorStep = 2.0f*M3D_PI / numMinor; int i, j; // 对于大圆上的点进行迭代 for (i=0; i<numMajor; ++i) { // 第一个点对应的弧度 double a0 = i * majorStep; // 第二个点对应的弧度 double a1 = a0 + majorStep; // 第一个点在 x 与 y 轴上的单位长度 GLfloat x0 = (GLfloat) cos(a0); GLfloat y0 = (GLfloat) sin(a0); // 第二个点在 x 与 y 轴上的单位长度 GLfloat x1 = (GLfloat) cos(a1); GLfloat y1 = (GLfloat) sin(a1); glBegin(GL_TRIANGLE_STRIP); // 对小圆上的点进行迭代 for (j=0; j<=numMinor; ++j) { // 小圆上点对应的弧度 double b = j * minorStep; // 小圆上点在半径方向的单位长度 GLfloat c = (GLfloat) cos(b); // 小圆上点,在xy 平面的分量长度 GLfloat r = minorRadius * c + majorRadius; // 小圆上点在 z 轴上的长度 GLfloat z = minorRadius * (GLfloat) sin(b); // 小圆上点坐标确认的过程:将该点分为在 z 轴 与 大圆半径方向,由于大圆半径只存在于 xy 平面,就相对容易求到 x , y 坐标。 // First point objectVertex[0] = x0*r;// 小圆上点对应的 x 坐标 objectVertex[1] = y0*r;// 小圆上点对应的 y 坐标 objectVertex[2] = z; // 小圆上点对应的 z 坐标 m3dTransformVector3(transformedVertex, objectVertex, mTransform); glVertex3fv(transformedVertex); // Second point objectVertex[0] = x1*r; objectVertex[1] = y1*r; objectVertex[2] = z; m3dTransformVector3(transformedVertex, objectVertex, mTransform); glVertex3fv(transformedVertex); } glEnd(); }
} void DrawCylinder(M3DMatrix44f mTransform){ // 大圆半径 GLfloat majorRadius = 55.0f; // 大圆圆周被切分的点数 GLint numMajor = 100; M3DVector3f objectVertex; // Vertex in object/eye space M3DVector3f transformedVertex; // New Transformed vertex // 每个点对应的弧度数 double majorStep = 2.0f*M3D_PI / numMajor; glBegin(GL_TRIANGLE_STRIP); // 对于大圆上的点进行迭代 for (int i=0; i<=numMajor; ++i) { // 第一个点对应的弧度 double a0 = i * majorStep; // 第二个点对应的弧度 double a1 = a0 - majorStep; // 第一个点在 x 与 y 轴上的单位长度 GLfloat x0 = (GLfloat) cos(a0); GLfloat y0 = (GLfloat) sin(a0); // 第二个点在 x 与 y 轴上的单位长度 GLfloat x1 = (GLfloat) cos(a1); GLfloat y1 = (GLfloat) sin(a1); // First point objectVertex[0] = x0*majorRadius;// 小圆上点对应的 x 坐标 objectVertex[1] = y0*majorRadius;// 小圆上点对应的 y 坐标 objectVertex[2] = 50.0f; // 小圆上点对应的 z 坐标 m3dTransformVector3(transformedVertex, objectVertex, mTransform); glVertex3fv(transformedVertex); // Second point objectVertex[0] = x1*majorRadius; objectVertex[1] = y1*majorRadius; objectVertex[2] = -50.0f; m3dTransformVector3(transformedVertex, objectVertex, mTransform); glVertex3fv(transformedVertex); }glEnd();
} //菜单回调函数
void processMenu(int value){switch(value){case 1:iCoordinateaxis=1;break;case 2:iCoordinateaxis=2;break;case 3:iProjectionMode=1;//强制调用窗口大小变化回调函数,更改投影模式为正交投影changSize(glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));break;case 4:iProjectionMode=2;//强制调用窗口大小变化回调函数,更改投影模式为透视投影changSize(glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));break;case 5:iPrintMatrix=1;break;case 6:iPrintMatrix=2;break;default:break;}//重新绘制glutPostRedisplay();
}//显示回调函数
void renderScreen(void){M3DMatrix44f transformationMatrix; // Storeage for rotation matrixstatic GLfloat yRot = 0.0f; // Rotation angle for animationyRot += 0.5f;//将窗口颜色清理为黑色glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//把整个窗口清理为当前清理颜色:黑色;清除深度缓冲区。glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//将当前Matrix状态入栈glPushMatrix();//坐标系绕x轴旋转xRotAngleglRotatef(xRotAngle,1.0f,0.0f,0.0f);//坐标系绕y轴旋转yRotAngleglRotatef(yRotAngle,0.0f,1.0f,0.0f);//进行平滑处理 glEnable(GL_POINT_SMOOTH);glHint(GL_POINT_SMOOTH,GL_NICEST);glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH,GL_NICEST);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);memset(transformationMatrix,0,sizeof(transformationMatrix));//打印变换矩阵if(2==iPrintMatrix){printf("--------------------------------------\n");for(int i=0;i<4;i++){for(int j=0;j<4;j++){printf("%9.6f ",transformationMatrix[4*j+i]);}printf("\n");}}m3dRotationMatrix44(transformationMatrix, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);//transformationMatrix[12]、transformationMatrix[13] = 0.0f、transformationMatrix[14] = 0.0f是平移参数,分别代表x、y、 z轴的偏移参数。//transformationMatrix[15]代表缩放为原来的1/transformationMatrix[15]if(2==iProjectionMode){transformationMatrix[12] = 0.0f;transformationMatrix[13] = 0.0f;transformationMatrix[14] = -250.0f;//透视投影为便于观察整个坐标系往内移动250个单位transformationMatrix[15] = 1.0f; }//打印变换矩阵if(2==iPrintMatrix){printf("--------------------------------------\n");for(int i=0;i<4;i++){for(int j=0;j<4;j++){printf("%9.6f ",transformationMatrix[4*j+i]);}printf("\n");}}//载入变换矩阵glLoadMatrixf(transformationMatrix);//绘制坐标系if(1==iCoordinateaxis){glColor3f(1.0f,1.0f,1.0f);glBegin(GL_LINES);glVertex3f(-90.0f,00.0f,0.0f);glVertex3f(90.0f,0.0f,0.0f);glVertex3f(0.0f,-90.0f,0.0f);glVertex3f(0.0f,90.0f,0.0f);glVertex3f(0.0f,0.0f,-90.0f);glVertex3f(0.0f,0.0f,90.0f);glEnd();glPushMatrix();glTranslatef(90.0f,0.0f,0.0f);glRotatef(90.0f,0.0f,1.0f,0.0f);glutSolidCone(3,6,10,10);glPopMatrix();glPushMatrix();glTranslatef(0.0f,90.0f,0.0f);glRotatef(-90.0f,1.0f,0.0f,0.0f);glutSolidCone(3,6,10,10);glPopMatrix();glPushMatrix();glTranslatef(0.0f,0.0f,90.0f);glRotatef(70.0f,0.0f,0.0f,1.0f);glutSolidCone(3,6,10,10);glPopMatrix();}glColor3f(0.5f,0.5f,1.0f);glutWireTorus(15.0f,50.0f,40,30); //恢复压入栈的MatrixglPopMatrix();//交换两个缓冲区的指针glutSwapBuffers();
}//设置Redering State
void setupRederingState(void){glEnable(GL_DEPTH_TEST); //使能深度测试glFrontFace(GL_CCW); //多边形逆时针方向为正面//glEnable(GL_CULL_FACE); //不显示背面glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);//背面正面均使用线填充//设置清理颜色为黑色glClearColor(0.0f,0.0,0.0,1.0f);//设置绘画颜色为绿色glColor3f(1.0f,1.0f,0.0f);//使能深度测试glEnable(GL_DEPTH_TEST);//获取受支持的点大小范围glGetFloatv(GL_POINT_SIZE_RANGE,sizes);//获取受支持的点大小增量glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);//获取最大的投影矩阵堆栈深度glGetIntegerv( GL_MAX_PROJECTION_STACK_DEPTH,&iMaxProjectionStackDepth);//获取最大的模型视图矩阵堆栈深度glGetIntegerv( GL_MAX_MODELVIEW_STACK_DEPTH,&iMaxModeviewStackDepth);//获取最大的纹理矩阵堆栈深度glGetIntegerv( GL_MAX_TEXTURE_STACK_DEPTH,&iMaxTextureStackDepth);printf("point size range:%f-%f\n",sizes[0],sizes[1]);printf("point step:%f\n",step);printf("iMaxProjectionStackDepth=%d\n",iMaxProjectionStackDepth);printf("iMaxModeviewStackDepth=%d\n",iMaxModeviewStackDepth);printf("iMaxTextureStackDepth=%d\n",iMaxTextureStackDepth);
}//窗口大小变化回调函数
void changSize(GLint w,GLint h){//横宽比率GLfloat ratio;//设置坐标系为x(-100.0f,100.0f)、y(-100.0f,100.0f)、z(-100.0f,100.0f)GLfloat coordinatesize=100.0f;//窗口宽高为零直接返回if((w==0)||(h==0))return;//设置视口和窗口大小一致glViewport(0,0,w,h);//对投影矩阵应用随后的矩阵操作glMatrixMode(GL_PROJECTION);//重置当前指定的矩阵为单位矩阵 glLoadIdentity();ratio=(GLfloat)w/(GLfloat)h;//正交投影if(1==iProjectionMode){printf("glOrtho\n");if(w<h)glOrtho(-coordinatesize,coordinatesize,-coordinatesize/ratio,coordinatesize/ratio,-coordinatesize,coordinatesize);elseglOrtho(-coordinatesize*ratio,coordinatesize*ratio,-coordinatesize,coordinatesize,-coordinatesize,coordinatesize);//当前矩阵设置为模型视图矩阵glMatrixMode(GL_MODELVIEW);//重置当前指定的矩阵为单位矩阵 glLoadIdentity();}else{printf("gluPerspective\n");gluPerspective(45,ratio,10.0f,500.0f);//当前矩阵设置为模型视图矩阵glMatrixMode(GL_MODELVIEW);//重置当前指定的矩阵为单位矩阵 glLoadIdentity();}}//按键输入处理回调函数
void specialKey(int key,int x,int y){if(key==GLUT_KEY_UP){xRotAngle-=5.0f;}else if(key==GLUT_KEY_DOWN){xRotAngle+=5.0f;}else if(key==GLUT_KEY_LEFT){yRotAngle-=5.0f;}else if(key==GLUT_KEY_RIGHT){yRotAngle+=5.0f;}//重新绘制glutPostRedisplay();
}void timerFunc(int value)
{glutPostRedisplay();glutTimerFunc(10, timerFunc, 1);
}int main(int argc, char* argv[])
{//菜单GLint iMainMenu;GLint iCoordinateaxisMenu;GLint iOrthoOrPerspectMenu;GLint iPrintmatrix;//初始化glut glutInit(&argc,argv);//使用双缓冲区、深度缓冲区。glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);//获取系统的宽像素SCREEN_WIDTH=glutGet(GLUT_SCREEN_WIDTH);//获取系统的高像素SCREEN_HEIGHT=glutGet(GLUT_SCREEN_HEIGHT);//创建窗口,窗口名字为OpenGL Transform DemoglutCreateWindow("OpenGL Transform Demo");//设置窗口大小glutReshapeWindow(windowWidth,windowHeight);//窗口居中显示glutPositionWindow((SCREEN_WIDTH-windowWidth)/2,(SCREEN_HEIGHT-windowHeight)/2);//窗口大小变化时的处理函数glutReshapeFunc(changSize);//设置显示回调函数 glutDisplayFunc(renderScreen);//设置按键输入处理回调函数glutSpecialFunc(specialKey);//菜单回调函数iCoordinateaxisMenu=glutCreateMenu(processMenu);//添加菜单glutAddMenuEntry("Display coordinate axis",1);glutAddMenuEntry("Don't dispaly coordinate axis",2);iOrthoOrPerspectMenu=glutCreateMenu(processMenu);glutAddMenuEntry("Ortho",3);glutAddMenuEntry("Perspect",4);iPrintmatrix=glutCreateMenu(processMenu);glutAddMenuEntry("Don't print Matrix",5);glutAddMenuEntry("Print Matrix",6);iMainMenu=glutCreateMenu(processMenu);glutAddSubMenu("Whether Display coordinate axis",iCoordinateaxisMenu);glutAddSubMenu("Ortho Or Perspect",iOrthoOrPerspectMenu);glutAddSubMenu("Whether Print Matrix",iPrintmatrix);//将菜单榜定到鼠标右键上glutAttachMenu(GLUT_RIGHT_BUTTON);glutTimerFunc(10,timerFunc, 1);//设置全局渲染参数setupRederingState();glutMainLoop();return 0;
}
VS2012下基于Glut 矩阵变换示例程序2:相关推荐
- VS2012下基于Glut 矩阵变换示例程序:
也可以使用我们自己的矩阵运算来实现OpenGL下的glTranslatef相应的旋转变换.需要注意的是OpenGL下的矩阵是列优先存储的. 示例通过矩阵运算使得圆柱或者甜圈自动绕Y轴旋转,可以单击鼠标 ...
- VS2012下基于Glut OpenGL GL_STENCIL_TEST示例程序:
模板测试是把像素存储在模板缓冲区的值与一个参考值进行比较.根据测试的结果,对模板缓冲区中得这个值进行相应的修改. Note:模板测试只有在存在模板缓冲区的情况下才会执行,如果不存在模板缓冲区,模板测试 ...
- VS2012下基于Glut OpenGL GL_QUADS示例程序:
OpenGL 使用GL_QUADS绘制四边形示例程序,显示效果如下所示. GL_QUADS连续点生成四边形的规则如下图所示: 源代码如下: // GlutQuadsDemo.cpp : 定义控制台应用 ...
- VS2012下基于Glut OpenGL显示一些立体图形示例程序:
Glut下提供了一些现成的绘制立体的API,如glutWireSphere绘制球,glutWireCone绘制椎体,glutWireCube绘制立体,glutWireTorus绘制甜圈,glutWir ...
- VS2012下基于Glut 绘制矩形管示例程序:
使用GL_QUADS来绘制一个矩形空心管,其中用到了glFrontFace函数.可以按键盘UP,DOWN,LEFT,RIGHT按键旋转坐标系查看3D图形.也可以通过鼠标单击右键弹出的菜单选择正交和透视 ...
- VS2012下基于Glut glRotatef glTranslatef示例程序:
Demo使用glRotatef ,glTranslatef来实现一个太阳.地球.月亮运动的3D图形. 1.glTranslatef() --模型变换函数移动 voidglTranslatef(GLfl ...
- VS2012下基于Glut OpenGL GL_POLYGON示例程序:
很多书介绍GL_POLYGON连续点生成多边形时这下点必须是凸多边形的,规则如下图所示.写个Demo验证了下似乎不是凸多边形的也可以. Demo的正面与背面显示效果: 源代码如下所示: // Glut ...
- VS2012下基于Glut OpenGL glScissor示例程序:
剪裁测试用于限制绘制区域.我们可以指定一个矩形的剪裁窗口,当启用剪裁测试后,只有在这个窗口之内的像素才能被绘制,其它像素则会被丢弃.换句话说,无论怎么绘制,剪裁窗口以外的像素将不会被修改.有的朋友可能 ...
- VS2012下基于Glut 绘制立方体示例程序:
使用glBegin(GL_QUADS)绘制六个侧面来组成一个立方体:并使用glFrontFace(GL_CW).glFrontFace(GL_CCW)来设置每个面的正面:使用glColor3ub来设置 ...
最新文章
- python新手入门教程-Python简明入门教程
- 【蓝桥杯Java_C组·从零开始卷】第二节(附)、if与switch效率比较(千万次/一亿次)
- Learning中的代数结构的建立
- pdoModel封装
- 面试中的智力题及编程实践
- Java中的锁原理、锁优化、CAS、AQS
- excel 删除大量空白行
- 编写函数,求字符串的长度
- http://blog.csdn.net/myy629464/article/list/1
- 快速学习一门技术的逻辑
- 正则表达式如何匹配括号
- GreenPlum数据库卸数、装数
- strtolower() 把字符串转换为小写字母
- Excel函数 - 提取月份,转换月份格式
- chatty: uid=10549(u0_a549) com.exampleidentical 40 lines
- idea通过maven使用docker插件生成镜像并推送到harbor仓库
- “阿里云大数据技术实战训练营”江苏省大学生万人计划学术冬令营活动成功举行...
- bom成本分析模型_各位成本会计,请问用BOM表算成本的大致思路是什么?
- 编程之余—80后夫妻公约
- 花 40 块搞个游戏机「GitHub 热点速览 v.22.27」
热门文章
- 华为机试HJ91:走方格的方案数
- java面试题整理_2018年最新java面试题整理。。。持续更新中。。。
- mysql注释符号_MySQL基础知识(2021最新版教程)
- php ado 建立注册,如何注册ADO与DAO [Access软件网]
- 骑马与砍杀服务器修复,骑马与砍杀修复存档损坏的办法
- docker mysql 漂移_Centos7系统Docker环境下Mysql部署
- Shell脚本基本用法
- php 读取管道,php – 使用proc_open时从STDIN管道读取
- 万万没 想到,Redis性能测试还能这样做
- 『学了就忘系列』Linux基础命令 — 搜索操作相关命令