观察
来源:互联网 发布:剑三dbm数据官网 编辑:程序博客网 时间:2024/04/28 05:40
概述
物体坐标----模型变换-----视点变换-----投影变换------视口变换------输出图像
通用变换函数:
glMatrixMode(GLenum mode);//选择要修改的矩阵,mode可以是GL_MODELVIEW(模型视点矩阵), GL_PROJECTION(投影矩阵), GL_TEXTURE(纹理矩阵)
glLoadIdentity();//将矩阵设为4*4单位矩阵
glLoadMatrix*();//将当前矩阵设为指定矩阵(按列排列)
glLoadTransposeMatrix*();//将当前矩阵设为指定矩阵,按行排列(正常情况)
glMultMatrix*();//计算矩阵相乘,按列排列
glMultTransposeMatrix*();//同上,按行排列
坐标变换
指定变换矩阵必须以相反的顺序进行,因此需要先调用视点变换矩阵,再调用模型变换矩阵,这时是对物体先进行模型变换,再进行视点变换。
1. 模型变换
平移
glTranslate{fd}(TYPE x, TYPE y, TYPE z);
旋转
glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z);
缩放
glScale{fd}(TYPE x, TYPE y, TYPE z);
2. 视点变换
使用glTranslate*(), glRotate*();
使用gluLookAt()
自定义函数
3.投影变换
透视投影
glFrustum();//定义棱锥台产生6个裁剪面
gluPerspective();//
正交投影
glOrtho();//产生长方体视景体
gluOrtho2D();二维图形投影
4.视口变换
glViewport();
通常视口宽高比应与视景体宽高比相同,否则出现变形。
5.变换后的深度坐标
视口变换期间,对深度坐标进行编码,存储在深度缓存中,
glDepthRange();设置深度范围,通常1.0~0.0之间。
透视投影中队深度坐标进行透视除法,离裁剪面越远,准确性越低。
变换错误诊断
1.明显错误----如绘制颜色与清屏颜色不能相同, 正确的启用和禁用状态;
2.投影变换时,指定的near , far是否包含了物体;
3.确定视点位置,观察方向, 物体位置;
4.确定旋转的转轴;
5.确定视景体;
6.透视变换时,近裁剪面不应离视点太近,否则会给深度缓存精度带来负面影响。
堆栈
glPushMatrix();压栈
glPopMatrix();出栈
保存当前变换矩阵,供以后调用
效率比重新LoadIdentity再进行变换效率高。
举例:
#include<windows.h>
#include<GL/glut.h>
#include <time.h>
void Delay(ULONG ulMicroSeconds)
{
LARGE_INTEGER timeStop;
LARGE_INTEGER timeStart;
LARGE_INTEGER Freq;
ULONG ulTimeToWait;
if (!QueryPerformanceFrequency( &Freq ))
return;
ulTimeToWait = Freq.QuadPart * ulMicroSeconds / 1000 / 1000;
QueryPerformanceCounter ( &timeStart );
timeStop = timeStart;
while( timeStop.QuadPart - timeStart.QuadPart < ulTimeToWait )
{
QueryPerformanceCounter( &timeStop );
}
}
static int year = 0, day = 0, month = 0, moonDay = 0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.9, 0.1);
glPushMatrix();
glutWireSphere(1.0, 20, 16);
glRotatef((GLfloat)year, 1.0, 1.0, 0.0);
glTranslatef(2.0, 0.0, 0.0);
glRotatef((GLfloat)day, 0.0, 1.0, 1.0);
glPushMatrix();
glColor3f(0.2, 1.0, 0.5);
glutWireSphere(0.2, 10, 8);
glRotatef((GLfloat)month, 0.2,0.5,0.8);
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)moonDay, 1.0, 1.0, 0.0);
glColor3f(0.5, 0.3, 1.0);
glutWireSphere(0.1, 5, 4);
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
Delay(500000);
day = (day+10)%360;
year = (year+5)%360;
month = (month+8)%360;
moonDay = (moonDay + 15)%360;
glutPostRedisplay();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void reshape(int w, int h)
{
glViewport(0.0, 0.0,(GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0 ,0.0);
}
int main(int grac, char** agrv)
{
glutInit(&grac, agrv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100,100);
glutCreateWindow("Planet");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
#include<windows.h>
#include<GL/glut.h>
static int shoulder = 0, elbow = 0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(-1.0, 0.0, 0.0);
glRotatef((GLfloat)shoulder, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutWireCube(1.0);
glPopMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)elbow, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutWireCube(1.0);
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void reshape(int w, int h)
{
glViewport(0.0, 0.0,(GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 's':
shoulder = (shoulder+5)%360;
glutPostRedisplay();
break;
case 'd':
elbow = (elbow+10)%360;
glutPostRedisplay();
break;
default:
break;
}
}
int main(int grac, char** agrv)
{
glutInit(&grac, agrv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100,100);
glutCreateWindow("robot");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
附加裁剪面
使用附加裁剪面补充视景体的6个面;
glClipPlane指定裁剪面;
glEnable启用指定裁剪面;
glDisable禁用指定裁剪面;
举例:
#include<windows.h>
#include<GL/glut.h>
void display()
{
GLdouble eqn[4] = {0.0, 1.0, 0.0, 0.0};
GLdouble eqn2[4] = {1.0, 0.0, 0.0, 0.0};
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(0.0, 0.0, -5.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glClipPlane(GL_CLIP_PLANE0, eqn);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE1, eqn2);
glEnable(GL_CLIP_PLANE1);
glutWireSphere(1.0, 20, 16);
glPopMatrix();
glFlush();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void reshape(int w, int h)
{
glViewport(0.0, 0.0,(GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int grac, char** agrv)
{
glutInit(&grac, agrv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100,100);
glutCreateWindow("Polygons");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
绕x轴旋转90
逆变换
通过矩阵反向变换,获取三维点;有窗口坐标获得三维坐标
gluUnProject
gluUnProject4//当深度不是标准值使用
模拟变换
gluProject获得指定物体的窗口坐标