3D-графика: изменение положения объекта в мире относительно его положения на экране.

Я реализую игру с видом из камеры, как в Diablo 3 (3D-объекты на 3D-поверхности, вид сверху), но у меня есть одно ограничение:

Мне нужно, чтобы моя игра не учитывала дистанцию ​​ни в каком отношении.

Это включает в себя то, что все 3D-модели обращены к камере под одним и тем же углом в ЛЮБОМ месте экрана, имеют одинаковый размер в любом месте экрана и движутся с одинаковой скоростью (в экранном пространстве).

Мне это нужно из-за конкретной механики, которую я имею в виду, и мне нужно, чтобы это было в 3D-мире, потому что мне нужны точные тени в игре.

Я знаю, как реализовать каждую функцию (в основном, используя ортогональную проекцию и немного магии шейдеров), но последняя, ​​то есть я не могу понять, как перемещать трехмерный объект, расположенный на трехмерной плоскости, с той же скоростью в экранном пространстве. .

Если объект находится в верхней части экрана, он будет двигаться медленнее, и наоборот, поэтому мне нужен какой-то код, чтобы компенсировать это.

Ребята, вы хоть представляете, как это можно сделать?

P.S. Кстати, спасибо за редактирование, так лучше.

Изменить: я кодирую в С#/XNA


person cubrman    schedule 08.05.2013    source источник


Ответы (2)


Не очень аккуратная математика, но я надеюсь, что она сработает для вас:

Вход

Предположим, вам дали

  • worldViewPerspectiveMatrix M (Преобразует мировое пространство в пространство перспективы, ортогональные матрицы тоже должны работать!)
  • постоянная скорость (точнее, расстояние на кадр) в пространстве экрана v_screen
  • (нормализованный) вектор направления V_dir в мировом пространстве, это даст направление движения вашего объекта. Фактическая длина вектора будет вычислена.
  • позиция X, где находится ваш Объект в мировом пространстве.

Результат

  • коэффициент масштабирования a для перемещения единиц вашего объекта 'v_screen' в экранном пространстве вдоль V_dir в мировом пространстве. Таким образом, вы хотите переместить ваш объект на самом деле X += a*V_dir.

Сначала мы используем формулу сопоставления мирового пространства с экранным пространством с использованием однородных координат и w-отсечения. . обозначает оператор умножения матриц.

X_proj := M.(x,y,z,1);
X_screen := (x_proj/w_proj,y_proj/w_proj);

Оттуда мы можем указать положение объекта X в пространстве экрана и положение после применения направленного движения X+(a*V_dir).

Длина в экранном пространстве и, следовательно, желаемое расстояние (на кадр) просто

Length[(X+(a*dir))_screen - X_screen] == v_screen.

Давайте решим это для a. Я использовал свою Mathematica, чтобы вычислить a для вас. Если вам нужны подробности, я могу уточнить ответ. Предположим, что M, X и V_dir есть

         / xp \          / vx \                        / vxp \
X_proj = | yp |  V_dir = | vy |    V_proj = M.V_dir =  | vyp |
         | zp |          | vz |                        | vzp |
         \ wp /          \ 0  /                        \ vwp /

А v_screen — это желаемая пространственная скорость экрана. Тогда a равно:

vlen = v_screen*v_screen;
a = (-dwp*vlen*wp + dxp*xp + dyp*yp + 
    0.5*Sqrt(
       Power(-2*dwp*vlen*wp + 2*dxp*xp + 2*dyp*yp,2)  - 
       4*(dxp*dxp + dyp*dyp - dwp*dwp*vlen)*(xp*xp + yp*yp - wp*wp*vlen)
       )
    ) /
    (dxp*dxp + dyp*dyp - dwp*dwp*vlen);

Помните, что -a также является решением.

person Inuniku    schedule 13.05.2013
comment
Я не упомянул, что пишу код на c#/XNA, может быть, там есть встроенная функция, которая уже это вычисляет? Потому что для меня попытка закодировать ваше объяснение действительно пугает :). - person cubrman; 15.05.2013
comment
Эээ, да, я думаю, что это так :) ... Я только что нашел проблему интересной: найти постоянную пространственную скорость экрана. Я пытаюсь изменить свой ответ на код XNA/C#, если хотите. Еще одно решение, которое я бы предложил, состоит в том, чтобы определить все движения в пространстве экрана. Затем вы сопоставляете положение экрана с вашей 3D-плоскостью с помощью кастинг лучей - person Inuniku; 15.05.2013
comment
В моей игре есть определенные механики, которые мне нужно реализовать, а также некоторые визуальные эффекты. А именно, мне нужно, чтобы персонажи двигались со скоростью экранного пространства, чтобы обеспечить плавное прицеливание (прицеливание будет происходить посредством движения), но также мне нужно, чтобы персонажи взрывались множеством кровавых битов, когда умирали :). И поскольку вторая часть, скорее всего, будет реализована вручную (интеграция физического движка была бы излишней и слишком сложной), я бы предпочел, чтобы персонажи были фактически расположены на плоскости в трехмерном мире, чтобы у меня было больше гибкости при реалистичном создании. -выглядит кровью :). - person cubrman; 15.05.2013
comment
В любом случае, я был бы ОЧЕНЬ признателен за код С# или, по крайней мере, за некоторые полезные функции, и я бы определенно углубился в предоставленную вами ссылку для литья лучей. - person cubrman; 15.05.2013
comment
Не обращайте внимания на мой пост № 3, теперь я понял вашу точку зрения :). Скорее всего, приведение лучей - это путь, если нет готовой реализации С#/xna. - person cubrman; 15.05.2013
comment
Извините за ссылку на немецкую страницу... вот английская msdn.microsoft.com/en-us/library/ . Там можно рассчитать расстояние до самолета. Осталось только вычислить луч из положения в пространстве экрана. Но это решаемый вопрос :( ... нажми на меня - person Inuniku; 15.05.2013

Угадайте, что из-за специфики ортогонального вида простое указание ортогональной матрицы как Projection решило все проблемы само собой. Модели движутся с одинаковой скоростью и сохраняют размер независимо от того, где они расположены. Однако единственная проблема заключается в том, что при смене разрешения экрана мир не подстраивается под него. Таким образом, мы должны использовать коэффициенты масштабирования, зависящие от текущего разрешения экрана, чтобы масштабировать наш мир вручную при загрузке игры.

person cubrman    schedule 15.07.2013