Проблема пользовательского преобразования OpenGL - PullRequest
0 голосов
/ 01 октября 2011

Я пытаюсь отбросить тень с помощью преобразования проекции. Но похоже, что OpenGL не нравится моя матрица, так как он ничего не рисует после glMultMatrix. После того, как я вставил свою матрицу, все в порядке. Я также использую JOGL, возможно, проблема в этом, но я сомневаюсь в этом, поскольку мои пользовательские матрицы перевода и вращения работают нормально.

Матрица выглядит так:

lightPosition = {x, y, z, 1}
planeEquation = {a, b, c, d}
pl = a*x + b*y + c*z + d

a*x-pl  b*x     c*x     d*x
a*y     b*y-pl  c*y     d*y
a*z     b*z     c*z-pl  d*z
a       b       c       d-pl

Теперь это матрица, которую я рассчитал, но я также использовал два других варианта, которые искал в Интернете; один немного другой, а другой точно так же, как мои времена -1. Это достаточно информации? Или я должен также предоставить код?

Может быть, это мое уравнение плоскости?

three points on plane = p0, p1, p2

v0 = p1 - p0
v1 = p2 - p0

n = {a, b, c} = v0 (cross) v1
d = -(n (dot) p0)

planeEquation = {a, b, c, d}

Звучит ли это кому-нибудь знакомо? Или это просто код?

РЕДАКТИРОВАТЬ: есть этот тест, который я пытаюсь выполнить, и который заключается в рисовании одной точки вершины с матрицей и без нее (для плоскости xz и светового пятна {0, 20, 0}) и с матрица ортогональной проекции. Кроме того, я пытаюсь самостоятельно вычислить нормализованные координаты устройства этой вершины, получая матрицы проекций и модельного представления OpenGL, умножая их на них и нормализуя с помощью координаты w.

Что я получаю, так это то, что без моей «матрицы теней» она хорошо отображает точку, и кажется, что мои расчеты вершины совпадают с тем, что я вижу. Но с моей «матрицей теней» я ничего не получаю, хотя координаты вершины лежат в диапазоне [-1,1] по всем осям.

Это слишком странно ...

РЕДАКТИРОВАТЬ: здесь добавлена ​​тестовая программа: https://gist.github.com/e0c54d5ab3cbc92dffe6

Ответы [ 2 ]

0 голосов
/ 02 октября 2011

разобрался (это автор вопроса).Это была просто опечатка, я не рассчитал нормальную плоскость в правильном направлении ... Я не сказал, что это было (v0 X v1), это было случайно (v1 ​​X v0).Вы можете увидеть это в коде.Так что, если самолет направлен в другую сторону, вы не можете проецировать на него.

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

Прежде чем начать, я предполагаю немного грубое знание линейной алгебры.Не нужно много.

Скажем, у нас есть плоскость с нормальным N с точкой Q на ней.Для каждой точки P (P-Q).N=0 (это точечное произведение), если (и только если) P находится на плоскости, поскольку векторы (P-Q) и N перпендикулярны.

Теперь давайте предположим, что у нас также есть(фиксированный точечный источник света) точка S. Мы хотели бы проецировать точку P на нашу плоскость из этого точечного источника света.Это означает, что мы хотели бы найти точку R, которая находится где-то на прямой, определенной точками P и S, и это также на плоскости.Другими словами, найдите скаляр t, такой что S+t(P-S)=R, такой, что R находится на плоскости.(P-S) - это вектор направления от точечного источника света через точку P. Мы "проходим" по этому вектору определенную величину t, начиная с точки S, пока не приземлимся на плоскости.

От 2 параграфов назадмы узнали хороший трюк, чтобы узнать, находится ли точка на плоскости или нет.Поэтому, если мы применим это к R, мы получим, что R находится на плоскости, если (и только если):

N.(R-Q)=0  
N.R-N.Q=0  
N.R=N.Q  
N.(S+t(P-S))=N.Q  
N.S+tN.(P-S)=N.Q  
t=(N.Q-N.S)/(N.(P-S))

Теперь, если мы вернем это в определение R:

R=S+(N.Q-N.S)*(1/(N.(P-S))*(P-S)

Давайте определим N.(P-S) как k

kR=(N.(P-S))*S+(N.Q-N.S)*P-(N.Q-N.S)*S  
kR=(N.P)*S+(N.Q-N.S)*P-(N.Q-N.S)*S-(N.S)*S    
kR=(N.P)*S+(N.Q-N.S)*P-(N.Q)*S  

Давайте напомним себе, что мы знаем, что мы не знаем, и что мы хотим знать.Мы знаем, что N и Q и S. P дан нам, и мы хотели бы найти R. Другими словами, мы хотели бы выразить R для P, используя N, Q и S. Давайте продолжим разбираться с этим немногодалее,

kR=(N_x*P_x+N_y*P_y+N_z*P_z)*S+(N.Q-N.S)*P-(N.Q)*S

R - точка, поэтому давайте определим каждую из ее координат, с координатами P (а также S, потому что у нас он также находится в правой части уравнения).

kR_x=[N_x*S_x+(N.Q-N.S)]P_x+[N_y*S_x]P_y+[N_z*S_x]P_z-(N.Q)*S_x
kR_y=[N_x*S_y]P_x+[N_y*S_y+(N.Q-N.S)]P_y+[N_z*S_y]P_z-(N.Q)*S_y  
kR_z=[N_x*S_z]P_x+[N_y*S_z]P_y+[N_z*S_z+(N.Q-N.S))]P_z-(N.Q)*S_z  

Может показаться, что мы ничего не получили, так как мы получили это k на левой стороне, и нам все еще нужно делить на него (и это k определяется P, тем не менее!).Не беспокойтесь, потому что OpenGL использует четыре элемента, а не три.Этот последний четвертый элемент используется для матриц перевода и интерполяции глубины перспективы.Для наших нужд сейчас все, что мы должны знать, это то, что openGL делит координаты каждой вершины на четвертый элемент.Это означает, что эта страшная k - наш четвертый элемент.мы получаем:

R_w=k  
R_w=N.(P-S)  
R_w=N.P-N.S  
R_w=[N_x]P_x+[N_y]P_y+[N_z]P_z-N.S  

Хорошо, мы определили наши R через P, используя N, S и Q. Давайте поместим это в матрицу M. Мы хотим:

M * P = R

Итак,

M=
N_x*S_x + (N.Q-N.S),  N_y*S_x,             N_z*S_x,             -(N.Q)*S_x 
N_x*S_y,              N_y*S_y + (N.Q-N.S), N_z*S_y,             -(N.Q)*S_y
N_x*S_z,              N_y*S_z,             N_z*S_z + (N.Q-N.S), -(N.Q)*S_z
N_x,                  N_y,                 N_z,                 -(N.S)

Помня об этом, помните, что, поскольку P - точка, четвертый элемент равен 1. (! = 0, если быть точным, но мы можем предположить, что это устройствонормализованная вершина)

Об уравнении плоскости.Уравнение плоскости - это вектор, в котором первые три элемента имеют нормаль.И его четвертый элемент - это расстояние от начала координат со знаком.Другой способ вычислить расстояние от плоскости до начала координат:

При заданной точке Q на плоскости с нормальным N расстояние плоскости от начала координат составляет | NQ |

Довольно просто,право?Это верно, поскольку:

N.Q=|N|*|Q|*cos(N,Q) 

и |N|=1, что дает нам:

N.Q=|Q|*cos(N,Q)=|Q|*d/|Q|=d

где d - расстояние до плоскости от начала координат.Или это размер вектора N;и величина N - это величина расстояния до плоскости от начала координат.Это можно увидеть, нарисовав плоскость, выбрав некоторую точку Q на плоскости, нарисовав нормаль N, идущую к плоскости из начала координат, и посмотрев на треугольник, образованный линиями двух векторов и плоскости.

В приведенной выше матрице замените -N.Q на d (последний элемент в уравнении плоскости), и все готово. (д = -N.Q). Эта матрица, заданная точкой P, будет проецировать ее на плоскость, определяемую N и Q, из светового пятна, определяемого S.

Надеюсь, что научит вас чему-то новому. Если я допустил ошибку, прокомментируйте, и я исправлю это.

0 голосов
/ 01 октября 2011

Может случиться так, что вы просто перенесли матрицу, переданную в OpenGL. Поначалу индексирование в OpenGL немного противоречит интуиции (хотя это имеет смысл, если вы понимаете матрицу как вектор строк векторов столбцов) OpenGL индексирует следующее:

0 4 8 c
1 5 9 d
2 6 a e
3 7 b f

В отличие от основного ряда C-порядка

0 1 2 3 
4 5 6 7
8 9 a b
c d e f
...