Изменение размера круга в openGL, сохраняя соотношение сторон

Я написал этот код, который печатает круг. Проблема возникает, когда я пытаюсь изменить размер окна. Соотношение сторон не сохраняется, и круг становится овальным.

#include<GL/glut.h>
#include<GL/glu.h>
#include<GL/gl.h>
#include<string.h>
#include<stdio.h>
#include <math.h>
#define PI 3.1415

const float DEG2RAD = 3.14159 / 180;
// Keep track of windows changing width and height
GLfloat windowWidth;
GLfloat windowHeight;

void drawCircle(float radius)
{
glBegin(GL_LINE_LOOP);
for (int i = 0; i <= 300; i++) {
double angle = 2 * PI * i / 300;
double x = radius * cos(angle);
double y = radius * sin(angle);
glVertex2d(x, y);
}
glEnd();
}

///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT );

// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
//glPushMatrix();
glColor3d(1, 0, 0);drawCircle(100);

glutSwapBuffers();
}
///////////////////////////////////////////////////////////
// This function does any needed initialization on the
// rendering context.
void SetupRC()
{
// Light values and coordinates
//glEnable(GL_DEPTH_TEST);  // Hidden surface removal

glClearColor(0,0,0,0);
}void ChangeSize(int w, int h)
{
GLfloat aspectRatio;
GLfloat nRange = 200.0f;
// Prevent a divide by zero
if (h == 0)
h = 1;

// Set Viewport to window dimensions
glViewport(0, 0, w, h);

// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Establish clipping volume (left, right, bottom, top, near, far)
aspectRatio = (GLfloat)w / (GLfloat)h;
if (w <= h)
{
glOrtho(-nRange, nRange, -nRange*aspectRatio, nRange*aspectRatio, -nRange*2, nRange * 2);
}
else
{
glOrtho(-nRange /aspectRatio, nRange /aspectRatio, -nRange, nRange, -nRange * 2, nRange * 2);
}

// Specify the orthographic (or perpendicular) projection,
// i.e., define the viewing box.

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////
// Entry point of the program
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glClear(GL_COLOR_BUFFER_BIT);
glutInitWindowSize(800, 800);
glutCreateWindow("Circle");
glutReshapeFunc(ChangeSize);

glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();

return 0;
}

Это код. Я думаю, что проблема в ChangeSize() функция. Кто-нибудь может мне помочь? Я попытался разделить и воспроизвести диапазон по соотношению сторон, которое определяется как ширина / высота в зависимости от проблемы.

0

Решение

Матрица проекции описывает отображение от трехмерных точек сцены к двухмерным точкам области просмотра. Матрица проекции преобразуется из пространства просмотра в пространство клипа.
Координаты в пространстве клипа преобразуются в нормализованные координаты устройства (NDC) в диапазоне (-1, -1, -1) в (1, 1, 1) путем деления на w компонент координат клипа.

В ортогональной проекции координаты в пространстве глаза линейно отображаются на нормализованные координаты устройства, а координаты области отсечения равны нормализованным координатам устройства, поскольку w Компонент равен 1 (для картезианской координаты).

введите описание изображения здесь

Ортографическая матрица проекции:

r = right, l = left, b = bottom, t = top, n = near, f = far

2/(r-l)         0               0               0
0               2/(t-b)         0               0
0               0               -2/(f-n)        0
-(r+l)/(r-l)    -(t+b)/(t-b)    -(f+n)/(f-n)    1

Предположим, у вас есть окно Full HD:

w = 1920.0;
h = 1080.0;

Окно имеет соотношение Aspcet 1,77778

aspectRatio = w / h = 1.77778

Если вы настроите матрицу ортографической проекции следующим образом:

glOrtho(-nRange*aspectRatio, nRange*aspectRatio, -nRange, nRange, -nRange*2, nRange*2 );

это приведет к следующей матрице ортографических проекций (1.0 / 1.77778 == 0.5625):

0.5625/nRange   0            0.0          0.0
0.0             1.0/nRange   0.0          0.0
0.0             0.0          0.5/nRange   0.0
0.0             0.0          0.0          1.0

Когда рисуется геометрия, каждая точка геометрии преобразуется матрицей проекции. Если круг нарисован в плоскости XY области просмотра,
тогда X-координата масштабируется 0,5625 / nRange:

X' = X * prjMat[0][0] = X * 0.5625/nRange

в то время как Y-координата масштабируется 1.0 / nRange

Y' = Y * prjMat[1][1] = Y * 1.0/nRange

Это означает, что матрица ортографической проекции применяет обратное соотношение сторон окна просмотра к геометрии, когда геометрия преобразуется из пространства просмотра в нормализованное пространство устройства.
Это приводит к тому, что идеальный круг искажается в эллипсе в нормализованном пространстве устройства и выглядит так:

введите описание изображения здесь

Если вы вытянете этот эллипс обратно в прямоугольную область просмотра, вы увидите идеальный круг в окне или на экране:

введите описание изображения здесь

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]