1. 程式人生 > >OpenGl 學習——三種變換的理解

OpenGl 學習——三種變換的理解

    剛開始學OpenGL, 沒有認真看書,結果似懂非懂,其實一點都沒有搞懂,尤其是被裡面的各種變換搞得暈來轉去的。沒辦法,反覆的讀《OpenGL 程式設計指南》紅寶書中關於變換的章節,終於有了點眉目了。瞬間感覺:啊,世界變得清明瞭許多!微笑 

   廢話不多說,直接切入正題。

   首先,應該知道的是:1)、OpenGL中所有的變換對應的都是矩陣的乘法運算,每個變換對應一個變換矩陣。

                                           2)、OpenGL維護了不同的矩陣堆疊。

   具體的說,就是,OpenGL中的所有變換,包括平移、選擇、縮放等變換都是基於矩陣的乘法運算的,每次變換都是把變換矩陣與相應矩陣堆疊的當前矩陣相乘,並再把它們的乘積作為該矩陣堆疊的當前矩陣。此外,不同的變換改變不同的矩陣堆疊。OpenGL維持了三個不同的矩陣,分別是GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE,在施加不同的變換前需要切換到對應的堆疊模式上,該切換需要呼叫glMatrixMode()函式。

  操縱模型檢視矩陣堆疊的變換包括模型變換和檢視變換。模型變換包括移動、旋轉、縮放物體,相應的需要呼叫glTranslate*()、glRotate*()、glScale*()函式,檢視變換主要是用於修改觀察點的位置和方向。需要注意的是,檢視變換函式一定要出現在模型變換函式之前,以確保首先作用於物體的是模型變換。

下面的的程式建立了兩個定時旋轉的三角形:

# -*- coding: cp936 -*-
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


angle=0

def Draw():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
    glColor3f(1.0,0.0,0.0)
    glLoadIdentity()
    gluLookAt(0,0,5,0,0,0,0,1,0)  #檢視變換:把觀察點移動到(0,0,5)位置,指向原點,y軸正方向作為朝上方向

    glTranslatef(0,0,-10)  #模型變換:平移物體到(0,0,-10)位置
    glRotatef(angle,0,1,0)  #模型變換:繞y軸旋轉物體angle角度
    
    glBegin(GL_TRIANGLES)
    glVertex3f(-2.5, -2.5, 0.0)
    glVertex3f(2.5, -2.5, 0.0)
    glVertex3f(0, 0.0, 0.0)
    glEnd()

    
    glLoadIdentity()  #將單位矩陣壓到棧頂,恢復到原點位置開始繪製
    glTranslatef(0,3,-20)
    glRotatef(angle,1,0,0)
    
    glColor3f(0.0,0.0,1.0)
    glBegin(GL_TRIANGLES)    
    glVertex3f(-2.5, -2.5, 0.0)
    glVertex3f(2.5, -2.5, 0.0)  
    glVertex3f(-2.5, 2.0, 0.0)
    glEnd()   

    glFlush()

def init():
    glClearColor(0.0,0.0,0.0,0.0)
    glEnable(GL_COLOR_MATERIAL)
    
def reshape(w,h):
    ratio=w/h
    glViewport(0,0,w,h)   
    glMatrixMode(GL_PROJECTION) #切換矩陣模式為投影矩陣,以後的操作影響的是投影矩陣堆疊
    glLoadIdentity()
    gluPerspective(40,w/h,0.1,200) #建立一個視景體
    glMatrixMode(GL_MODELVIEW)  #切換矩陣模式為模型檢視矩陣,以後的操作影響的是模型檢視矩陣堆疊
   

def update(value):
    global angle
    angle+=0.4
    if angle>360:
        angle-=360
    glutPostRedisplay()
    glutTimerFunc(25,update,0)

glutInit()
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(400, 400)
glutCreateWindow("test")
init()
glutDisplayFunc(Draw)
glutReshapeFunc(reshape)
glutTimerFunc(25,update,0)
glutMainLoop()