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 matrix
static GLfloat yRot = 0.0f; // Rotation angle for animation
yRot += 0.5f;
//将窗口颜色清理为黑色
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//把整个窗口清理为当前清理颜色:黑色;清除深度缓冲区。
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //将当前Matrix状态入栈
glPushMatrix();
//坐标系绕x轴旋转xRotAngle
glRotatef(xRotAngle,1.0f,0.0f,0.0f);
//坐标系绕y轴旋转yRotAngle
glRotatef(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);
//恢复压入栈的Matrix
glPopMatrix();
//交换两个缓冲区的指针
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);
else
glOrtho(-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 Demo
glutCreateWindow("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:的更多相关文章

  1. VS2012下基于Glut 矩阵变换示例程序:

    也可以使用我们自己的矩阵运算来实现OpenGL下的glTranslatef相应的旋转变换.需要注意的是OpenGL下的矩阵是列优先存储的. 示例通过矩阵运算使得圆柱或者甜圈自动绕Y轴旋转,可以单击鼠标 ...

  2. VS2012下基于Glut OpenGL glEdgeFlag示例程序:

    glEdgeFlag (GLboolean flag)表示一个顶点是否应该被认为是多边形的一条边界边的起点.flag为GL_TRUE后面的点都被认为是边界上的点,flag为GL_FALSE则之后的点不 ...

  3. VS2012下基于Glut OpenGL glDepthMask示例程序:

    glDepthMask (GLboolean flag)函数可以决定将他之后的数据不写入深度缓冲区.当flag为GL_TRUE时之后的数据不写入深度缓冲区,即使启用了深度缓冲区测试功能. 使用上一个D ...

  4. VS2012下基于Glut OpenGL glScissor示例程序:

    剪裁测试用于限制绘制区域.我们可以指定一个矩形的剪裁窗口,当启用剪裁测试后,只有在这个窗口之内的像素才能被绘制,其它像素则会被丢弃.换句话说,无论怎么绘制,剪裁窗口以外的像素将不会被修改.有的朋友可能 ...

  5. 部署Bookinfo示例程序详细过程和步骤(基于Kubernetes集群+Istio v1.0)

    部署Bookinfo示例程序详细过程和步骤(基于Kubernetes集群+Istio v1.0) 部署Bookinfo示例程序   在下载的Istio安装包的samples目录中包含了示例应用程序. ...

  6. 基于阿里云容器服务用docker容器运行ASP.NET 5示例程序

    小试阿里云容器服务 之后,接下来有一个挡不住的小试冲动--用docker容器运行程序.首先想到的程序是 ASP.NET 5示例程序,于是参考msdn博客中的这篇博文 Running ASP.NET 5 ...

  7. 大数据下基于Tensorflow框架的深度学习示例教程

    近几年,信息时代的快速发展产生了海量数据,诞生了无数前沿的大数据技术与应用.在当今大数据时代的产业界,商业决策日益基于数据的分析作出.当数据膨胀到一定规模时,基于机器学习对海量复杂数据的分析更能产生较 ...

  8. 基于Struts2.3.x+Spring3.2.x+Hibernate4.2.x+EasyUI1.3.4+Maven架构的示例程序

    基于Struts2.3.x+Spring3.2.x+Hibernate4.2.x+EasyUI1.3.4+Maven架构的示例程序 不知道为什么,保存的时候显示有一个连接为违禁内容,可能是…………. ...

  9. ok6410[002] ubuntu1604系统下搭配ckermit和dnw基于RAM的裸机程序调试环境

    ubuntu1604系统下搭配ckermit和dnw基于RAM的裸机程序调试环境 系统:  ubuntu16.04 裸板: 飞凌公司OK6410开发板 目标:搭建基于ubuntu1604系统和基于RA ...

随机推荐

  1. ASP.NET状态服务及session丢失问题解决方案总结

    原文:ASP.NET状态服务及session丢失问题解决方案总结[转载] asp.net Session的实现: asp.net的Session是基于HttpModule技术做的,HttpModule ...

  2. Linq to Sql : 三种事务处理方式

    原文:Linq to Sql : 三种事务处理方式 Linq to SQL支持三种事务处理模型:显式本地事务.显式可分发事务.隐式事务.(from  MSDN: 事务 (LINQ to SQL)).M ...

  3. 关于WIN32.EXE变态木马下载器的解决办法

    一.WIN32.EXE的来源:http://fdghewrtewrtyrew.biz/adv/130/win32.exe 二.运行后的表现:此WIN32.EXE通过80和8080端口访问若干个IP,若 ...

  4. solrnet的使用

    solr与.net系列课程(五)solrnet的使用    solr与.net系列课程(五)solrnet的使用 最近因项目比较忙,所以这篇文章出的比较晚,离上一篇文章已经有半个月的时间了,这节课我们 ...

  5. Bootstrap 网格系统

    自版本 2.3.2 起,Bootstrap 提供了两种类型的网格,默认网格系统和流动网格系统.默认的网格系统是 940px 宽和 12 列.本文主要讲解第一种. 首先让我们看,怎么来应用默认网格系统 ...

  6. 话谈c#拷贝

    c#中类型分为值类型和引用类型,值类型对象赋值是本身就是赋的自身的一个副本,而引用类型赋值时则赋的是指向堆上的内存,假如我们不想赋这个地址而想将对象赋过去要怎么做呢?首先要知道拷贝分为浅表拷贝和深层拷 ...

  7. AjaxPro2

    AjaxPro2完整入门教程   一.目录 简单类型数据传送(介绍缓存,访问Session等) 表类型数据传送 数组类型数据传送(包含自定义类型数据) 二.环境搭建 1.这里本人用的是VS2012. ...

  8. ubuntu-使用终端配置网络

    文件说明: IP.网关.掩码的配置文件:/etc/network/interfaces DNS配置文件:/etc/resolv.conf 配置步骤: 1)配置有关IP文件 配置IP.网关.掩码这些信息 ...

  9. Html 导航

    首页,来一个比较简单的例子热热身,相信有点css基础的人都可以看懂的.自所以,写一些教程,或许这样的教程已经泛滥啦,但是,还是想理理自己的思想来帮助自己及引导初学者更好的理解css. 1.竖直排列导航 ...

  10. Coursera台大机器学习基础课程1

    Coursera台大机器学习基础课程学习笔记 -- 1 最近在跟台大的这个课程,觉得不错,想把学习笔记发出来跟大家分享下,有错误希望大家指正. 一 机器学习是什么? 感觉和 Tom M. Mitche ...