OpenGL - относительное/абсолютное положение GlVertex

Imagen У меня есть список 2D-точек (x,y), которые описывают 2D-территорию в моей простой игре. Затем у меня есть glVertex(), чтобы нарисовать все эти точки в режиме GL_POINTS.

Затем у меня есть мяч, который также имеет координаты (x, y).

Я хочу, чтобы мяч имел определенный размер по отношению ко всему остальному (например, к местности). Как мне установить значения координат (x, y), чтобы нарисовать все, что мне нужно? Наличие экрана 600х400.

Меня беспокоит также то, что glVertex2f(1,1) будет рисовать примитивную точку в правом верхнем углу. Таким образом, 1 означает переход на 100% вправо или вверх. Но экран 600x400, поэтому я не могу иметь размеры одинаковой длины по осям x и y.


person N.Peart    schedule 27.04.2011    source источник


Ответы (2)


Поскольку 0 — это 0% (абсолютно слева/внизу), а 1 — это 100% (абсолютно справа/вверху), вам просто нужно найти точку между ними, которая будет совпадать с пикселями.

Например. Скажем, ваш мяч имеет размер 20x20 пикселей. Это означает, что он составляет 5% экрана в высоту и 3,33% в ширину. Следовательно, квадрат, окружающий ваш шар, будет иметь следующие вершины:

void drawBall()
{
   glVertex2f(ball.x - (20/600)/2, ball.y - (20/400)/2);
   glVertex2f(ball.x - (20/600)/2, ball.y + (20/400)/2);
   glVertex2f(ball.x + (20/600)/2, ball.y + (20/400)/2);
   glVertex2f(ball.x + (20/600)/2, ball.y - (20/400)/2);
}

Посмотрите, как я делю ширину мяча на ширину экрана, чтобы получить значение с плавающей запятой, которое работает с glVertex2f? Кроме того, ball.x и ball.y должны быть значениями с плавающей запятой от 0 до 1.

Я делю эти числа на 2, потому что предполагаю, что (ball.x, ball.y) — это координата центра мяча, поэтому половина прибавления приходится на обе стороны от центра.

person Andrew Rasmussen    schedule 27.04.2011
comment
Вы хорошо объясняете. Но является ли стандартом и обычным делом делать такие деления все время? Это было бы неэффективно. Даже если бы я определил константы Kx = 1/600 , Ky = 1/400, запись в коде была бы проще, но у меня много неэффективных умножений. - person N.Peart; 27.04.2011
comment
Затем сохраните это значение (20/600) как ball.width и (20/400) как ball.height. Я просто использовал все деления, чтобы вы могли видеть, откуда берутся числа. - person Andrew Rasmussen; 27.04.2011
comment
Вы можете пойти дальше и сохранить (20/600)/2 как ball.halfwidth, чтобы вам не приходилось каждый раз делить на 2. Кроме того, пожалуйста, проголосуйте + примите, если это ответило на ваш вопрос :) - person Andrew Rasmussen; 27.04.2011
comment
Я только что попробовал что-то еще arasmussen ... скажите, что вы думаете. glScalef(0,5*P, 0,5, 0,0) - person N.Peart; 27.04.2011
comment
Я только что попробовал кое-что еще: 'code' P = ResY / ResX //число с плавающей запятой glScalef(Scale*P, Scale, 0) ... glVertex2f(ball.x - 10, ball.y - 10) 'code' Это понижено мой fps, хотя (из-за умножения или glScale (). Этот подход в порядке? - person N.Peart; 27.04.2011
comment
Я думаю, что я бы придерживался метода, который я предложил. В противном случае вы рисуете большой шар и уменьшаете его. В то время как с моим методом вы просто рисуете мяч. glScale больше подходит для тех случаев, когда вы хотите масштабировать объекты нормального размера до другого размера, потому что что-то в вашей игре временно повлияло на размер вашего объекта. - person Andrew Rasmussen; 27.04.2011
comment
да, я думаю, что я в порядке сейчас. Большое спасибо за твою помощь! - person N.Peart; 28.04.2011
comment
Ждать. Если я делаю поворот, фигура деформируется (при условии, что разрешение окна не квадратное) 'glRotatef(45,0,0,1) //поворот с использованием оси Z... как я могу исправить это поведение? Может быть, я могу подумать об этом и понять это. Но я сомневаюсь, что написание этого для каждой программы openGL является стандартной вещью. Держу пари, есть более простой способ. Любые комментарии? - person N.Peart; 28.04.2011
comment
Ты прав. Используйте масштаб. Тем не менее, я думаю, вам нужно повернуть, а затем масштабировать? Можно поиграться с порядком. - person Andrew Rasmussen; 28.04.2011
comment
Кроме того, более простым решением для всего этого шума является использование glVertex3f. И тогда все должно работать с любым размером экрана. - person Andrew Rasmussen; 28.04.2011
comment
В самом деле? Я собираюсь попробовать это сейчас. - person N.Peart; 28.04.2011
comment
Возможно, вам действительно придется сделать несколько других вещей. Если это не сработает, попробуйте добавить в инициализацию OpenGL следующее: glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); Я не уверен, как на самом деле работает 2D, я когда-либо работал только с 3D. Кроме того, вы делаете gluPerspective()? - person Andrew Rasmussen; 28.04.2011
comment
И я все равно отвечу на ваш вопрос, даже если вы меня не откажете ;) - person Andrew Rasmussen; 28.04.2011
comment
хахах, хорошо... сейчас... не получилось. Я просто добавил то, что вы сказали. У меня есть следующее: // только что добавленный glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glClearDepth(1.0) ... ... // ранее glClearColor(0.0,0.0,0.0,0.0) glViewport(0 , 0, resX, resY) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0.0, resX, 0.0, resY) glMatrixMode(GL_MODELVIEW) glLoadIdentity() - person N.Peart; 28.04.2011
comment
и я до сих пор не визуализировал 3D-объекты. Также хочу отметить, что я рисую с помощью GL_POLYGON. - person N.Peart; 28.04.2011
comment
Хм. Между glMatrixMode(GL_PROJECTION) и glLoadIdentiy() вызовите gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); - person Andrew Rasmussen; 28.04.2011
comment
буу. Это не сработало. Тем не мение. Можешь не волноваться... Попробую на днях разобраться в чем дело. Вероятно, мне не хватает чего-то фундаментального в том, как работает openGL. Я пока проигнорирую эти раздражающие повороты. Все равно спасибо, вы мне очень помогли. - person N.Peart; 28.04.2011
comment
Вам нужно добавить .0 после каждого числа и (double) перед каждым числом типа int (например, первая строка должна быть glVertex2f((double)ball.x - (20.0/600.0)/2.0, (double)ball.y - (20.0/400.0)/2.0);), потому что в противном случае он будет рассчитывать только с использованием целых чисел, и вы получите результат, округленный до ближайшего целого числа. Поскольку окно находится только между -1 и 1, вершины будут только в углу или в середине, если вы считаете только с целыми числами. - person Donald Duck; 02.08.2016

Вы можете написать свою собственную функцию, которая отрисовывает вершины и принимает пиксели в качестве аргументов:

#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
void glVertex_pixels(const double x,const double y){
    glVertex2d(x * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - y * 2.0 / (double)WINDOW_HEIGHT);
}

Вы также можете использовать макрос:

#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
#define glVertex_pixels(x,y) glVertex2d((double)(x) * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - (double)(y) * 2.0 / (double)WINDOW_HEIGHT);

Независимо от того, какой из приведенных выше кодов вы используете, использование этой функции простое. Например, следующий код рисует вершину на расстоянии 10 пикселей от левой стороны и 20 пикселей от верхней стороны:

glVertex_pixels(10,20);
person Donald Duck    schedule 02.08.2016