Войти
ПрограммированиеФорумГрафика

Превод экранных координат в 3Д-пространство. Или наоборот!

#0
20:13, 25 апр. 2015

Здравствуйте!
Весь день пытаюсь раскурить пример "PICK"  в ДиректХ примерах. Вроде бы и код не большой, и алгоритм понятен..но нифига не получается(:
я сделал простую сценку с квадратом из двух трианглов в центре, для ориентации, отодвинул камеру:

D3DXVECTOR3 vEyePt   ( 0.0f, 3.0f,14.0f );
  D3DXVECTOR3 vLookatPt( 0.0f, 3.0f, 0.0f );
  D3DXVECTOR3 vUpVec   ( 0.0f, 1.0f, 0.0f );
  D3DXMatrixLookAtLH( &dx->camPos, &vEyePt, &vLookatPt, &vUpVec );
короче, сценка простая - можно и на пальцах этапы алгоритма проверить.
в примере они первым делом переводят координаты курсора в экранное пространство:
D3DXVECTOR3 v;
        v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
        v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
        v.z = 1.0f;
-по сути, если я понял здесь происходит "обратное проецирование". По крайней мере, я не поленился и параллельно перемножил мектор на обратную матрицу проекции, и получил такие же числа.
При этом получается направление, начало которого это центр экрана. При ос Y- наверх, а ось Х - вправо. Тогда, если мы тикаем мышкой в зону верхней правой четверти экрана, но на выходе должны получится положительные v.x v.y. а если пикаем в левую нижнюю четверть экрана, то значения отрицательные.
Дальше по коду:
        D3DXMATRIX mWorldView = matWorld * matView;
        D3DXMATRIX m;
        D3DXMatrixInverse( &m, NULL, &mWorldView );

        // Transform the screen space pick ray into 3D space
        vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
        vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
        vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
Дальше происходит обратное преобразование по положение камеры и объекта. В моём случае для объекта это единичная матрица и ее можно исключить в принципе.
по идее, vPickRayDir - это и есть вектор направления луча, который проходит через точку, которую я кликнул на экране?
Вот после этого преобразования у меня получается какая то муть.
значаения вектора v не меняются, но меняются знаки: когда пикаю мышкой в левую часть экрана - то Х-компонента получается положительной, а в правой части-отрицательной - хотя должно быть наоборот.
Не пойму в чём замутка.
Написал простой алгоритм пересечения этого луча с плоскостью Y=0; Ну и т.к. у меня нарисован полигон как раз в этой плоскости, то тыкая в его углы я по идее должен получать координаты вершин. Но значения получаются не не..((


#1
12:22, 26 апр. 2015

Товарищи, неужели никого не интересует больше этот вопрос?
я решил проверить, как преобразуются 3д координаты в экранные:
взял точку в пространстве:

D3DXVECTOR4 point0(6,0,-6,1);
и попытался перевести ее в экранные координаты. для этого получил общую матрицу преобразований:
 D3DXMATRIX rezMatr = obj*view*perspective;
ну и перемножил вектор на матрицу:
   D3DXVECTOR4 scrPnt;
   D3DXVec4Transform(&scrPnt,&point0, &rezMatr);
в результате получился некий вектор, который явно не похож на экранные координаты: (-9.86 , -7.24 , 19.9 , 20)
из этих чисел очевидно 20 - это координата Z удаления точки от камеры (поскольку камера глобально находится в координатах 0, 3, 14)
третий параметр, который по идее и должен быть Z равен: -19.9. похоже на 20, но все же приличная погрешность, не правда ли?

поломав мозг, я отмасштабировал этот вектор на 1/20. Стало интереснее. Координаты XY в векторе стали похожи на нормированные экранные [-1;1] с той лиш разницей, что у координаты Х число с обратным знаком. Будто ось Х идет по экрану справа на лево.
тут я решил, что нашел алгоритм, как 3Д координаты преобразуются в экранные.

Но по скольку у меня эта точка прорисована на экране, я написал процедурку, которая по клику показывает нормированные координаты.
перевод 3Д в экранные нормированные: 0.3823 , 0.3621
перевод от мышки в нормированные    : 0.3728 , 0,3179
я мог ожидать погрешностей на уровне 3-го знака после запятой, но никак не таких. Вернее, это скорее всего не погрешности, а ошибка в рассуждениях. Вот только где они не верны?? Хелп плиз

#2
15:01, 26 апр. 2015

Denis
> Товарищи, неужели никого не интересует больше этот вопрос?

Никого, это сильно простой вопрос ответ на который легко гуглится, нет смысла мусолить очевидное
http://www.toymaker.info/Games/html/picking.html

#3
23:14, 26 апр. 2015

чёрт побери, у меня какие то проблемы с матрицами, или настройкой перспективы, я не могу понять. Помогите понять в чём дело плиииз:
вот матрица трансформации объекта (собственно, в единичном виде - и ничто никуда не трансфотмируется):

_11  = 1.0f; _12  = 0.0f; _13  = 0.0f; _14  = 0.0f;
_21  = 0.0f; _22  = 1.0f; _23  = 0.0f; _24  = 0.0f;
_31  = 0.0f; _32  = 0.0f; _33  = 1.0f; _34  = 0.0f;
_41  = 0.0f; _42  = 0.0f; _43  = 0.0f; _44  = 1.0f;
матрица перспективы устанавливается как левосторонняя: D3DXMatrixPerspectiveFovLH при ней у нас ось Х смотрит направо,а ось Z смотрит на нас, т.е. мы смотрим на отрицательное Z-пространство. Ось Y направлена вверх.
т.е. хочу опустить объект - ставлю  _42  = -2.0f; Объект опускается. все норм. Хочу сдвинуть вправо, ставлю _41  = 5.0f; Всё норм, объект двигается вправо на 5.
А вот с координатой Z непонятно. По идее, если хочу отодвинуть, то должен выставить отрицательное значение. Но нет - если выставлю  _43  = -10.0f; то объект уходит мне за спину, а если ставлю _43  = +10.0f; то объект отодвигается он меня, как будто ось Z  направлена от меня на экран.
пробовал ставить перспективу как правостороннюю систему координат, но там вообще мясо какое то - небо и земля меняются местами.
Вопрос в том, что у меня не так с Z-осью? почему объект так себя ведёт?
беда еще в том что с матрицей камеры тоже беда, но иначе: по оси Z камера себя ведет правильно, а оси X и Y  будто инвертированы. т.е. чтобы переместить камеру вверх по оси  У, нужно поставить отрицательные значения. Что же это такое?

#4
23:30, 26 апр. 2015

Denis
> По идее, если хочу отодвинуть, то должен выставить отрицательное значение. Но
> нет - если выставлю  _43  = -10.0f; то объект уходит мне за спину, а если
> ставлю _43  = +10.0f; то объект отодвигается он меня, как будто ось Z 
> направлена от меня на экран.

Если хочешь так то
D3DXMatrixPerspectiveFovRH

тебе в помощь

ты уж определись сначала какую систему координат ты используешь.

#5
23:48, 26 апр. 2015

так я и хочу использовать ну что по умолчанию, т.е. LH,  но почему когда я задаю координаты объекта и камеры, то они двигаются в разных направлениях, как будто объект находится в одной системе координат, а камера в другой?
по идее если я задал смещение по оси Z =10  и для камеры и для объекта - то ведь их взаимное положение не должно никак поменяться - а они у меня разлетаются в разные стороны.

#6
1:53, 27 апр. 2015

Denis
> так я и хочу использовать ну что по умолчанию, т.е. LH,  но почему когда я
> задаю координаты объекта и камеры,
Тогда смирись с тем что +z от камеры вперед, а -z назад. В чем собственно сложности.
Ты странные вещи пишешь. Очевидно если камера и объект в одной системе координат например в мировой, и ты смещаешь их на +10 по Z то относительное положение не поменяется.
Но если оно у тебя меняется, а чудес на свете , как известно не бывает, особенно в области комп. графики. То есть 2 варианта:
1) ты смещаешь их по-разному
2) ты смещаешь их в разных системах координат
Чтобы не заниматься тут сеансами телепатии, все таки лучше бы ты как-то определился что тебе надо - перевод координат туда-сюда-обратно, или смещение по Z и выложил бы матрицы/код.

#7
0:43, 28 апр. 2015

Спасибо за терпение! Разобрался я в чём дело :)
Всё оказалось у меня гораздо запущеннее, чем я предполагал. Во первых я ошибался с направлением оси Z в левосторонней системе координат. Действительно, вперед она +Z. А не заметил я это, потому что у меня на полигоне ещё и текстура была инвертирована по координате V, которая совпала с Z. Инвертирование координат + инвертирование текстуры меня запутало. т.к. тестировал на квадратном полигоне, то всё казалось нормально. ппц. я еще на этом модели и шейдер с бликами потестить сумел, и даже всё вроде работало..
короче не суть. После того как разобрался с системой координат, то преобразование координат тоже стало работать.
Единственное, что я отказался от алгоритма, в котором луч испускается от центра камеры и находится вектор направления этого луча. Потому что на мой взгляд это бред. Если мы пикаем в экран, то луч, пересекающий все объекты под курсором будет проходить через позицию камеры только в случае, если мы пикнем точно по центру экрана (вернее, алгоритм конечно, будет работать, но точность будет +- трамвайная остановка). А в общем случае  такой луч будет проецироваться в точку, в которую мы как раз и кликаем. По этому я взял экранную точку и разделил на две, добавив им разные координаты по Z. И преобразовав их в реальное 3Д пространство получается тот самый луч, который уже можно проверять на пересечение с объектами.

ПрограммированиеФорумГрафика

Тема в архиве.

Тема закрыта.