2014-03-28 30 views
2

我正在處理一個任務以繪製線框GLUT標準對象。這看起來很簡單,但我們被告知我們不能使用gluAtLook(),glOrtho(),glFrustrum,但我們必須使用glTranslate(),glScale()和glRotate。如何在不使用glMatrixMode(GL_PROJECTION)中的這些函數的情況下投影對象?計算gluLookAt,glOrtho和glFrustum

這是我到目前爲止有:

#include "stdafx.h" 
#include <iostream> 
#include <cstdlib> 
#include <cmath> 
#include <math.h> // for sqrt() 
#include <glut.h> 


void init(void) 
{ 
    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glShadeModel(GL_FLAT); 
} 

void display(void) 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3f(1.0, 1.0, 1.0); 
    glLoadIdentity();    /* clear the matrix */ 
    /* viewing transformation */ 
    glTranslatef(0.0, 0.0, -5.0); 
    glScalef(1.0, 2.0, 1.0);  /* modeling transformation */ 
    glutWireCube(1.0); 
    glFlush(); 

} 

void reshape(int w, int h) 
{ 
    glViewport(0, 0, (GLsizei)w, (GLsizei)h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); 
    //glTranslatef(0.0, 0.0, -5.0); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 

int main(int argc, char** argv) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
    glutInitWindowSize(500, 500); 
    glutInitWindowPosition(100, 100); 
    glutCreateWindow(argv[0]); 
    init(); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutMainLoop(); 
    return 0; 
} 

是否有人可以幫助這一點?

+0

你爲什麼不能使用它們? – Ben

回答

2

你需要做的是計算你自己的投影矩陣和模型視圖矩陣。之後,您可以在撥打glLoadIdentity後立即使用glLoadMatrix加載它們。

7

我們被告知我們不能用gluAtLook(),glOrtho(),glFrustrum但我們必須使用glTranslate(),glScale()和glRotate

gluLookAt樹立全球視野空間改造, glOrtho確實查看到正投影空間轉換和glFrustum確實查看透視投影空間轉換。當你說你的導師不允許使用它時,這顯然意味着他們的意圖是首先了解這些功能是如何工作的。

在互聯網上有許多資源教你。由着名的加州大學伯克利分校教授Ravi Ramamoorthi博士提供的Here's one。 SongHo有good articles這將幫助你做同樣的事情。


我可以在2D中演示一個簡單的例子。假設我們有一個用物體定義的世界(爲了簡單起見,我們得到一個點P);我們希望相機處於(3,3),其X軸和Y軸指向與世界X軸和Y軸相反的方向。爲了簡單起見,我們假定兩個幀具有相同的比例因子,即在X和Y方向上1個單位測量兩個系統的相同距離(幅度)。因此,兩個框架僅根據方位和原點位置不同(W 和V 是表示它們的符號)。

我們需要導出M world-> view即將世界空間中的點映射到空間的矩陣。這就是現在不贊成的gluLookAt函數計算並乘以GL_MODELVIEW矩陣堆棧。這個矩陣將被用來從相機的角度來看待世界。

We know that中號世界 - >視圖 = T 視圖 - >世界。將幀A的點映射到幀B的矩陣也將是將B的幀變換成A的幀的矩陣。推導是這樣的

Step by step transformation of view's frame into world's frame

在世界上的點P有(1,2)= P瓦特爲座標,我們有效地找到一個矩陣,其中當以P W相乘會給出P v即在視圖幀中的相同點的座標。該點被寫爲3D點,因爲2D點的均勻擴展將是3D點;因爲它是一個點,齊次座標將是1;它是一個矢量,它會是0。

第一步是旋轉;將視圖的框架旋轉-180°(右旋系統,其中+ ve旋轉爲逆時針);現在這兩個座標軸都沿着相同的方向。我們必須解決原始差異,這是通過翻譯完成的,這是第2步。乘以兩者都會得到所需的矩陣。請注意,每個步驟將視圖的幀更加接近後乘數。另外,每個轉換都基於當前我們所在的本地框架,而不是基於開始的全局(世界)框架。

同樣的想法也可以擴展到3D,還需要更多的努力。在上面的推導中,我只需要旋轉矩陣,平移矩陣和矩陣乘法;沒有gluLookat。我給你的鏈接應該有助於計算3D的相同。投影矩陣的推導有點涉及。但是,您仍然可以在不使用glOrtho的情況下獲得結果;我給出的鏈接有最終矩陣的公式;您可以使用該矩陣組合一個矩陣,並將其乘以GL_PROJECTION矩陣堆棧。

注意:上述推導假設列向量,因此轉換矩陣(如旋轉)和乘法順序基於此進行。如果假定那麼行向量約定轉所有矩陣和反向multplication的順序,因爲

(AB)^ T = B^TA^T

+0

非常感謝您的演示幫助了很多!下面我已經做了一個解決方案。 – user2303699

+0

我很高興它幫助,保持它! – legends2k

1
#include "stdafx.h" 
#include <iostream> 
#include <cstdlib> 
#include <cmath> 
#include <math.h> // for sqrt() 
#include <glut.h> 

static GLfloat Xvalue = 0.0f; 
static GLfloat Yvalue = 0.0f; 
static GLfloat xRot = 0.0f; 
static GLfloat yRot = 0.0f; 
static GLfloat zRot = 0.0f; 
static GLfloat xScale = 1.0f; 
static GLfloat yScale = 1.0f; 
static GLfloat zScale = 1.0f; 

void init(void) 
{ 
glClearColor(1.0, 1.0, 1.0, 1.0); 
glShadeModel(GL_FLAT); 
} 

void display(void) 
{ 
glClear(GL_COLOR_BUFFER_BIT); 
glColor3f(0.0, 0.0, 0.0); 
glLoadIdentity(); //clear the matrix 
glTranslatef(Xvalue, Yvalue, -3.0); // viewing transformation 
glScalef(xScale, yScale, zScale); // modeling transformation 
glRotatef(xRot, 1.0f, 0.0f, 0.0f); 
glRotatef(yRot, 0.0f, 1.0f, 0.0f); 
glRotatef(zRot, 0.0f, 0.0f, 1.0f); 
glutWireCube(1.0); 
glFlush(); 
} 

void reshape(int w, int h) 
{ 
GLfloat identity[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; 

if (h == 0) // don't want a divide by zero 
{ 
    h = 1; 
} 

glViewport(0, 0, (GLsizei)w, (GLsizei)h); 

glMatrixMode(GL_PROJECTION); 
glLoadMatrixf(identity); 
GLfloat fovy = 52.0f; // in degrees 
GLfloat c = 1.0/(GLfloat)tan(fovy/4.0), a = (GLfloat)w/(GLfloat)h, n = 1.0f, f = 1000.0f; 
GLfloat projection[16] = { c/a, 0.0, 0.0, 0.0, 
    0.0, c, 0.0, 0.0, 
    0.0, 0.0, -(f + n)/(f - n), -1.0, 
    0.0, 0.0, -2.0*f*n/(f - n), 0.0 }; 
glMultMatrixf(projection); 

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
} 

void keyInput(unsigned char key, int x, int y) 
{ // Keyboard input processing routine. 
switch (key) 
{ 
case 'b': // move left 
    Xvalue -= 0.1; 
    glutPostRedisplay(); 
    break; 
case 'B': // move right 
    Xvalue += 0.1; 
    glutPostRedisplay(); 
    break; 
case 'c': // move down 
    Yvalue -= 0.1; 
    glutPostRedisplay(); 
    break; 
case 'C': // move up 
    Yvalue += 0.1; 
    glutPostRedisplay(); 
    break; 
case 'e': // scale down 
    zScale -= 0.1; 
    xScale -= 0.1; 
    yScale -= 0.1; 
    glutPostRedisplay(); 
    break; 
case 'E': // scale up 
    zScale += 0.1; 
    xScale += 0.1; 
    yScale += 0.1; 
    glutPostRedisplay(); 
    break; 
case 'f': // rotate x axis CW 
    xRot -= 5.0f; 
    glutPostRedisplay(); 
    break; 
case 'F': // rotate x axis CCW 
    xRot += 5.0f; 
    glutPostRedisplay(); 
    break; 
case 'g': // rotate y axis CW 
    yRot -= 5.0f; 
    glutPostRedisplay(); 
    break; 
case 'G': // rotate y axis CCW 
    yRot += 5.0f; 
    glutPostRedisplay(); 
    break; 
case 'h': // rotate z axis CW 
    zRot -= 5.0f; 
    glutPostRedisplay(); 
    break; 
case 'H': // rotate z axis CCW 
    zRot += 5.0f; 
    glutPostRedisplay(); 
    break; 
} 
} 


int main(int argc, char** argv) 
{ 
glutInit(&argc, argv); 
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
glutInitWindowSize(500, 500); 
glutInitWindowPosition(100, 100); 
glutCreateWindow(argv[0]); 
init(); 
glutDisplayFunc(display); 
glutReshapeFunc(reshape); 
glutKeyboardFunc(keyInput); 
glutMainLoop(); 
return 0; 
} 
+0

+1。你不會'#include '和'#include '。兩者在C++中都是相同的;只是做前者。更多關於[這裏](http://www.parashift.com/c++-faq/include-c-hdrs-system.html)。 – legends2k