观察

来源:互联网 发布:剑三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获得指定物体的窗口坐标