Я работаю в небольшой программе OpenGL — GLUT (я полностью нуб), и у меня много проблем с переключением между gluPerspective и glOrtho, нажимающим клавишу (например, «p»).
Я взял несколько скриншотов, чтобы проиллюстрировать проблему … используя gluPerspective а также glOrtho
А вот и мой код …
#if defined(__APPLE__)
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#else
#include <GL/gl.h>
#include <GL/greeglut.h>
#endif
#include <iostream>
#include <math.h>
#include "model.h"
using namespace std;
// actual vector representing the camera\'s direction
float lx = 0.0f,lz = -1.0f;
// XZ position of the camera
float x = 0.0f,z = 5.0f;
// angle for rotating triangle
float angle = 0.0f;
float fov = 45.0;
Model m;
Model m1;
Model m2;
Model m3;
double maxX, maxY, maxZ;
double minX, minY, minZ;
double centX, centY, centZ;
double maxTam;
bool persp = true;
double min(double x, double y) {
if(x < y) return x;
return y;
}
double max(double x, double y) {
if(x > y) return x;
return y;
}
void setMinMaxXYZ(void) {
maxX = minX = m.vertices()[0];
maxY = minY = m.vertices()[1];
maxZ = minZ = m.vertices()[2];
for(int i = 3; i < m.vertices().size(); i += 3) {
maxX = max(maxX,m.vertices()[i]);
minX = min(minX,m.vertices()[i]);
maxY = max(maxY,m.vertices()[i+1]);
minY = min(minY,m.vertices()[i+1]);
maxZ = max(maxZ,m.vertices()[i+2]);
minZ = min(minZ,m.vertices()[i+2]);
}
centX = ((maxX - minX)/2) + minX;
centY = ((maxY - minY)/2) + minY;
centZ = ((maxZ - minZ)/2) + minZ;
}
void changeView(void) {
int w = glutGet(GLUT_WINDOW_WIDTH);
int h = glutGet(GLUT_WINDOW_HEIGHT);
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(persp) gluPerspective(fov, ratio, 0.1f, 100.0f);
else glOrtho(-1,1,-1,1,-0.5,100.0);
glMatrixMode(GL_MODELVIEW);
}
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0) h = 1;
if(w == 0) w = 1;
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(persp) gluPerspective(fov, ratio, 0.1f, 100.0f);
else glOrtho(-1,1,-1,1,0.1,100.0);
glViewport(0,0,w,h);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Posicionament de la càmera
gluLookAt( x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f);
glClearColor(0.5,0.5,1.0,1.0);
// dibuix terra
glColor3f(0.0f, 255.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-5.0f, 0.0f, -5.0f);
glVertex3f(-5.0f, 0.0f, 5.0f);
glVertex3f( 5.0f, 0.0f, 5.0f);
glVertex3f( 5.0f, 0.0f, -5.0f);
glEnd();
// Models .obj
for (int i = 0; i < 3; ++i) {
float transX, transY, transZ;
if(i == 0) {
m = m1;
transX = -1.25; transY = 0.5; transZ = -2.0;
} else if(i == 1) {
m = m2;
transX = -0.5; transY = 0.5; transZ = 2.5;
} else {
m = m3;
transX = 2.5; transY = 0.25; transZ = -0.5;
}
setMinMaxXYZ();
maxTam = max(max(maxX - minX, maxY - minY), maxZ - minZ);
glPushMatrix();
glTranslated(-(centX / maxTam), -(centY / maxTam), -(centZ / maxTam));
glTranslated(transX,transY,transZ);
glScaled(1.0/maxTam,1.0/maxTam,1.0/maxTam);
glBegin(GL_TRIANGLES);
for(int i = 0; i < m.faces().size(); i++){
const Face &f = m.faces()[i];
glColor3f(Materials[f.mat].diffuse[0],Materials[f.mat].diffuse[1],Materials[f.mat].diffuse[2]);
for(int j = 0; j < 3; j++)
glVertex3dv(&m.vertices()[f.v[j]]);
}
glEnd();
glPopMatrix();
}
glutSwapBuffers();
}
void processKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
else if(key == 'p'){
persp = not persp;
changeView();
}
}
void processSpecialKeys(int key, int xx, int yy) {
float fraction = 0.1f;
switch (key) {
case GLUT_KEY_LEFT :
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_RIGHT :
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_UP :
x += lx * fraction;
z += lz * fraction;
break;
case GLUT_KEY_DOWN :
x -= lx * fraction;
z -= lz * fraction;
break;
}
}
void idle(void) {
glutPostRedisplay();
}
void iniView(void) {
int w = glutGet(GLUT_WINDOW_WIDTH);
int h = glutGet(GLUT_WINDOW_HEIGHT);
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
//glOrtho(-1,1,-1,1,0.01,1000);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
// init GLUT i creació finestra
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("IDI: Bloc 3 - Càmeres i perspectives");
// Carregar models .obj
m1.load("model/legoman-assegut.obj");
m2.load("model/Shaun_Hastings.obj");
m3.load("model/porsche.obj");
// crides
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(idle);
glutKeyboardFunc(processKeys);
glutSpecialFunc(processSpecialKeys);
iniView();
// OpenGL init
glEnable(GL_DEPTH_TEST);
// loop
glutMainLoop();
return 1;
}
Предполагается, что я должен увидеть зеленый «пол» в обзоре glOrtho … что я делаю не так ??
пс. Объектами модели являются файлы .obj, предоставленные преподавателем.
редактировать:
Наконец, glOrtho работает правильно. Но теперь … у меня есть еще один вопрос, как я могу сделать, чтобы максимизировать окно и (в режиме glOrtho) изображение не деформируется?
В функции changeSize () … когда я использую gluPerspective, он работает нормально, но не с glOrtho !!
тот факт, что вы не видите слово с ортогональной проекцией, на самом деле ожидается с учетом того, как вы настроили матрицу вида модели:
это происходит потому, что ваш пол параллелен плоскости XZ — и ваш вектор обзора тоже.
// Posicionament de la càmera
gluLookAt( x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f);
первые 3 аргумента gluLookAt — это xyz-компоненты положения камеры, следующие 3 аргумента — это xyz «центра интересов». вектор между этими двумя точками является вектором представления, а его y-компонент равен 0, что означает, что он параллелен XZ и, следовательно, вашему полу.
если вы хотите увидеть пол + ортографическую проекцию, вам придется наклонить камеру так, чтобы она смотрела вниз.
Других решений пока нет …