Отображение трехмерной вершины в пиксель с использованием pyreder/pyglet/openGL
Я реализую новый алгоритм для оценки трехмерных точек с использованием изображений, и прямо сейчас я пытаюсь протестировать его на трехмерных виртуальных моделях, прежде чем перейти к реальным объектам.
Входные данные алгоритма - это пиксели до последнего преобразования в размеры области просмотра, поэтому для тестирования алгоритма на визуализированных изображениях мне нужно знать обратное преобразование из пикселя в форме ([0,witdh],[0,height]).
Я использую перспективную проекцию из библиотеки pyrender для рендеринга 2D-изображений 3D-сетки, насколько мне известно, эта библиотека использует методы OpenGL для рендеринга.
Пример: у меня есть сетка коробки с размерами =(3,1,5), center=(0,0,0), и у меня есть матрицы проекции и вида
View Matrix= [[ 0.96592583, -0.0669873 , 0.25 , 3. ],
[ 0. , 0.96592583, 0.25881905, 4. ],
[-0.25881905, -0.25 , 0.9330127 , 10. ],
[ 0. , 0. , 0. , 1. ]]
Projection Matrix= [[ 2.4142135, 0. , 0. , 0. ],
[ 0. , 2.41421356, 0. , 0. ],
[ 0. , 0. , -1.0010005 , -0.10005003],
[ 0. , 0. , -1. , 0. ]]
это мой расчет для отображения трехмерной точки / вершины в пиксель:
def map_to_pixel(point3d,w,h,projection,view):
p=projection@view@point3d # openGL perspective projection
p=p/p[3] # divide by the w element
p[0]=w/2*p[0]+w/2 # transformation from [-1,1] -> [0,width]
p[1]=h/2*p[1]+h/2 # transformation from [-1,1] -> [0,height]
return p
протестируйте его на вершине слева вверху-закрытие окна =[-1.5, 0.5, 2.5, 1.], когда viewport_sizes=(width,height)=(512512)
результаты =
когда фактические результаты pyrender для этой вершины - пиксель ~ (90,342)
Если кто-то знает, как работает pyrender / OpenGL, или знает, как правильно отображать пиксели, это будет очень полезно.
btw: я знаю, что моя функция использует отображение левого нижнего угла, когда библиотека использует отображение левого верхнего угла, но она все равно дает неожиданный результат.
1 ответ
Я понял, как идет расчет, я не знаю почему, но библиотека pyrender (которая использует методы OpenGL) использует обратную матрицу матрицы представления, которую я установил в качестве входных данных.
точная функция для установки пикселя:
from numpy.linalg import inv
def map_to_pixel(point3d,w,h,projection,view):
p=projection@inv(view)@point3d.T
p=p/p[3]
p[0]=(w/2*p[0]+w/2) #tranformation from [-1,1] ->[0,width]
p[1]=h-(h/2*p[1]+h/2) #tranformation from [-1,1] ->[0,height] (top-left image)
return p
Я протестировал визуализированные изображения с помощью этой функции, и все вершины были идеально сопоставлены с пикселями.