我正在进行绘制线框GLUT标准对象的赋值。这看起来很简单,但我们被告知我们不能使用gluAtLook(),glOrtho(),glFrustrum,但我们必须使用glTranslate(),glScale()和glRotate。如何在不使用glMatrixMode(GL_PROJECTION)中的这些函数的情况下投影对象?
这是我到目前为止所做的:
#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 :(得分:7)
我们被告知我们不能使用gluAtLook(),glOrtho(),glFrustrum但我们必须使用glTranslate(),glScale()和glRotate
gluLookAt
设置世界以查看空间变换,glOrtho
查看正投影空间变换,glFrustum
查看透视投影空间变换。当你说你的导师不允许使用它时,它显然意味着首先要了解这些功能是如何工作的。
互联网上有很多资源可以教你这么做。 Here's one由着名的加州大学伯克利分校教授Ravi Ramamoorthi博士撰写。 SongHo good articles可以帮助你做同样的事情。
我可以在2D中演示一个简单的案例。假设我们有一个用对象定义的世界(为简单起见,我们采用P点);我们希望相机处于(3,3),其X和Y轴指向与世界X和Y轴相反的方向。为简单起见,我们假设两个帧具有相同的缩放因子,即X和Y方向上的1个单位测量两个系统的相同距离(幅度)。因此,两个帧的区别仅在于方向和原点位置(W 0 ,V 0 是表示它们的符号)。
我们需要导出M world-&gt; view ,即将世界空间中的点映射到视图空间的矩阵。这就是现在已弃用的gluLookAt
函数计算并乘以GL_MODELVIEW矩阵堆栈。该矩阵将用于从相机的角度来看世界。
We know that M world-&gt; view = T view-&gt; world 。将帧A的点映射到帧B的矩阵也将是将B的帧变换为A的帧的矩阵。推导就像这样
世界上的点P有(1,2)= P w 作为坐标,我们有效地找到一个矩阵,当乘以P <sub> w 时,它将给出P v 即视图框中的相同点坐标。该点被写为3D点,因为2D点的均匀扩展将是3D点;齐次坐标为1,因为它是一个点;如果它是一个矢量,那就是0。
第一步是轮换;旋转视图的框架-180°(右旋系统+ ve旋转逆时针);现在,两个帧的轴都沿着相同的方向。我们要解决原点差异,这是通过翻译完成的,这是第2步。将两者相乘将得到所需的矩阵。请注意,每个步骤都会通过后乘将视图的帧更接近世界的帧。此外,每个转换都基于我们所在的当前本地帧,而不是基于起始全局(世界)帧。
同样的想法也可以扩展到3D,需要更多努力。在上面的推导中我只需要旋转矩阵,平移矩阵和矩阵乘法;没有gluLookat
。我给你的链接应该有助于计算相同的3D。投影矩阵推导更复杂一些。但是,您仍然可以在不使用glOrtho
的情况下实现结果;我上面给出的链接有最终矩阵的公式;您可以使用它来组合矩阵并将其乘以GL_PROJECTION矩阵堆栈。
注意:上面的推导假定了列向量,因此转换矩阵(如旋转)和乘法顺序基于此完成。如果您假设行向量约定,则转置所有矩阵并反转自从
以来的乘法顺序(AB)^ T = B ^ T A ^ T
答案 1 :(得分:2)
您需要做的是计算您自己的投影矩阵和模型视图矩阵。之后,您可以在致电glLoadMatrix
后立即使用glLoadIdentity
加载它们。
答案 2 :(得分: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;
}