Last time I found out about the proportions of a 2D object. Now I am concerned about the same question, but with a 3D object.

enter image description here

Code:

#include <GL/glut.h> GLfloat xRotated, yRotated, zRotated; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); //Сглаживание glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } void DrawCube(void) { glMatrixMode(GL_MODELVIEW); // очистить буфер рисования. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0,0.0,-5); glRotatef(yRotated,1.0,1.0,0.0); glBegin(GL_QUADS); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glColor3f(1.0f,0.5f,0.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(1.0f,1.0f,0.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glEnd(); glFlush(); } void animation(void) { yRotated += 0.03; DrawCube(); } void reshape(int x, int y) { if (y == 0 || x == 0) return; // Устанавливаем новую проекционную матрицу glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Угол обзора: 40 градусов // Возле плоскости отсечения расстояние: 0,5 // Дальний отсечения плоскости расстояние: 20,0 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); //glMatrixMode(GL_MODELVIEW); glViewport(0,0,x,y); // Использование всего окна для rendering } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(DrawCube); glutReshapeFunc(reshape); glutIdleFunc(animation); glutMainLoop(); return 0; } 

As I understood the whole thing in perspective.

 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); 

So ok:

enter image description here

So not normal:

enter image description here

BONUS QUESTION:

Is there any universal perspective feature that is often used? In the plan, we enter some one parameter (for example, the viewing angle), and based on it, the rest are calculated by themselves (placement distance, clipping plane, etc.).

  • so what's the problem ? What is your result coming out of those two? Are the proportions preserved or not preserved? - ampawd
  • @ampawd This is all one result when resizing a window. - Artik Slayer
  • How is this one result? One and the same code can not produce different results ... - ampawd
  • @ampawd the same code can and usually will produce different results with different input parameters (for example, the size of the rendering area), which we observe here. - Kromster

1 answer 1

To calculate the perspective matrix, the vertical angle of view and the aspect ratio are (GLdouble)x/(GLdouble)y are usually used.

To save the relative size of the model in the render window, in the case when the window is narrower, you need to build a perspective with a given horizontal viewing angle. Not sure if there is such a function in glu , so in Delphi I use this one to build the perspective matrix:

 class function TMatrix3D.NewPerspectiveFovRH(const AFOV, AAspect, AZNear, AZFar: Single; const AHorizontalFOV: Boolean = False): TMatrix3D; var XScale, YScale: Single; begin if AHorizontalFOV then begin XScale := 1 / Tangent(AFOV / 2); YScale := XScale / AAspect; end else begin YScale := 1 / Tangent(AFOV / 2); XScale := YScale / AAspect; end; Result := TMatrix3D.Identity; // Получаем единичную матрицу Result.m11 := XScale; Result.m22 := YScale; Result.m33 := AZFar / (AZNear - AZFar); Result.m34 := -1; Result.m43 := AZNear * AZFar / (AZNear - AZFar); Result.m44 := 0; end; 

As you can see, the code is quite simple. Next, this matrix must be transferred to OpenGL for use as a projection matrix.

The answer does not pretend to be complete, but I hope you will cope with the translation of the code in C ++ and the transfer of the constructed matrix to OpenGL.


There is no easier way to set perspectives, since All 4 parameters are independent and necessary. But you can write your own wrapper function, which will build the perspective only by aspect ratio, with a constant viewing angle (for example, 45) and Z clipping planes (for example, 0.001 and 1000).