2015-02-08 5 views
0

Я совершенно новичок в OpenGL и полностью ржавый на C++. Для школьного задания мне нужно изменить код стартового кода C++, чтобы создать рудиментарную 2D-анимацию.OpenGL: применить гомографическое преобразование к стеку матрицы

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

Существующий код вида:

// Draw rectangle 
glLoadIdentity(); 
glPushMatrix(); 
glScalef(HEIGHT, WIDTH, 1.0) 
// C++ code to set colour 
// C++ code to draw square 
glPopMatrix() 

рисует прямоугольник, масштабированное по высоте и ширине с выбранным цветом, как и ожидалось.

Один из homographies является:

1.0 0.0  0.0 
0.0 9.0/4.0 3.0/4.0 
0.0 1.0/12.0 1.0/4.0 

Он преобразует точки: (1, 1), (-1, 1), (-1, -1), (1, -1), чтобы (3, 9), (-3, 9), (-6, -9), (6, -9) соответственно.

Я представляю это в столбцах порядка, как:

float homographyBody[9] = {1.0, 0.0, 0.0, 0.0, 9.0/4.0, 1.0/12.0, 0.0, 3.0/4.0, 1.0/4.0} 

Однако, подставляя:

glMultMatrixf(homographyBody) 

для:

glScalef(HEIGHT, WIDTH, 1.0) 

не имеет желаемый эффект.

Никакая комбинация умножения и масштабирования, по-видимому, не может отображать ничего, кроме длинного клина, простирающегося от точки, близкой к началу вверх и вправо.

Я подозреваю, что я просто не осведомлен о какой-то базовой концепции. Любые советы приветствуются.

ответ

2

glMultMatrix() ожидает матрицу 4x4 в качестве аргумента. Кроме того, как вы уже заметили, OpenGL хранит матрицы в главном порядке столбцов.

Для выполнения этой работы вам необходимо расширить матрицу до 4x4. Вам нужна матрица 4x4, которая преобразует 3D-точки, представленные в однородных координатах, так же как ваша оригинальная матрица 3x3 преобразует двумерные точки в однородные координаты.

Для вашей матрицы 3х3, преобразование применяется как:

[ a00 a01 a02 ] [ x ] [ a00 * x + a01 * y + a02 ] 
[ a10 a11 a12 ] * [ y ] = [ a10 * x + a11 * y + a12 ] 
[ a20 a21 a22 ] [ 1 ] [ a20 * x + a21 * y + a22 ] 

Из этого, после деления на w (3-й компонент результирующего вектора), вы получите в результате точку как:

x' = (a00 * x + a01 * y + a02)/(a20 * x + a21 * y + a22) 
y' = (a10 * x + a11 * y + a12)/(a20 * x + a21 * y + a22) 

Расширение это матрица 4х4, где мы на самом деле не заботиться о z координате:

[ a00 a01 0.0 a02 ] [ x ] [ a00 * x + a01 * y + a02 ] 
[ a10 a11 0.0 a12 ] * [ y ] = [ a10 * x + a11 * y + a12 ] 
[ 0.0 0.0 1.0 0.0 ] [ z ] [ z      ] 
[ a20 a21 0.0 a22 ] [ 1 ] [ a20 * x + a21 * y + a22 ] 

После деления на w (который теперь является четвертым компонентом результирующего вектора), вы получаете ту же самую точку, что и раньше.

Для примера, это:

float homographyBody[16] = { 
    1.0f, 0.0f,  0.0f, 0.0f, 
    0.0f, 9.0f/4.0f, 0.0f, 1.0f/12.0f, 
    0.0f, 0.0f,  1.0f, 0.0f, 
    0.0f, 3.0f/4.0f, 0.0f, 1.0f/4.0f 
}; 
+0

Спасибо. Да, дополнительная «=» была опечаткой. Моя матрица 3x3 для гомографии находится в стандартной форме, но мой массив с плавающей точкой преобразует ее в порядок столбцов, как указано в OP. Я не могу понять карту с любого из этих заказов на тот, который вы дали для представления 4x4. Не могли бы вы объяснить это сопоставление? – Schemer

+1

@Schemer Я добавил несколько объяснений. –

+0

Большое спасибо за это. Гуглинг для ответа был приключением и половиной, прежде чем я отправился в SO. Я применил вашу расширенную матрицу, и теперь гомография теперь отображается правильно. – Schemer

Смежные вопросы