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. JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内

    /* *JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内 *@param date1 date2(形如:'2015-01-01'类 ...

  2. PHP 以POST方式提交XML、获取XML,最后解析XML

    以POST方式提交XML // Do a POST $data="<?xml version='1.0' encoding='UTF-8'?> <TypeRsp> & ...

  3. JAVA 代码生成。SimpleCaptcha

    去官方网站下载Jar包: http://simplecaptcha.sourceforge.net/ Javadocs: http://simplecaptcha.sourceforge.net/ja ...

  4. Node.js连接MySQL数据库及构造JSON的正确姿势

    做一下整理,以前也很随意的引入包链接数据库,后来发现常常连接出问题,异常退出,后来使用在网上一个方法解决问题,网址由于书签丢失,抱歉不能引用了.再有就是简单的模块化下,使得目录合理点,再有就是说明一下 ...

  5. Windows 下安装 Oracle 12c 教程

    原文 Windows 下安装 Oracle 12c 教程 申明:本文原作者:Jmq   本文给大家带来的是 Oracle 12C 的安装教程. 1.准备 1.1 下载 Oracle 12c 安装程序 ...

  6. Linux系统编程:dup2()重定向

    对于Dup2 的理解: 源代码: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #inclu ...

  7. CLR中的垃圾回收机制

    CLR中采用代(generation)来作为其垃圾回收的一种机制,其唯一的目的是提升程序的性能.基予代的垃圾回收器有以下假设: ·对象越新,其生存周期越短. ·对象越老,其生存周期越长. ·回收堆的一 ...

  8. worker进程中线程的分类及用途

    worker进程中线程的分类及用途 欢迎转载,转载请注明出版,徽沪一郎. 本文重点分析storm的worker进程在正常启动之后有哪些类型的线程,针对每种类型的线程,剖析其用途及消息的接收与发送流程. ...

  9. python 开发利器

    UliPad 初体验----python 开发利器 Posted on 2013-10-28 22:36 虫师 阅读(436) 评论(3) 编辑 收藏 学习python 有段时间,最近博客更新比较慢了 ...

  10. POJ 3667 & 1823 Hotel (线段树区间合并)

    两个题目都是用同一个模板,询问最长的连续未覆盖的区间 . lazy代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度. 区间合并很恶心啊 ...