ПрограммированиеФорумОбщее

[Решено]Проекция точек на экран. Unity3d. Воссоздание метода WorldToViewportPoint

#0
13:44, 4 ноя 2014

Привет. В который раз убеждаюсь, что оффорум юнити существует только для вопросов типа "где найти кнопку билда?". Ответ на что-то посложнее получить там просто невозможно. Может быть здесь кто-нибудь сталкивался с подобной задачей: перевод координат точки из мировых в вьюпорт/экран? Обычно для этого используется стандартный метод камеры WorldToViewportPoint, однако скорость его работы меня абсолютно не устраивает (да и в фон не засунешь). Преобразование векторов "руками" - гораздо быстрее, проверено опытным путем. Проблема, для меня - достать правильную матрицу и я пока не понял, как это сделать. Итак, что я пробовал (точки пишу в текстуру, для наглядности):
1) Трансформ позиции вершины куба в мировые координаты, затем WorldToViewportPoint

Vector3 v = goTransform.TransformPoint(vertices[i]);
Vector3 pos = mCamera.WorldToViewportPoint(v);
texture.SetPixel((int)(pos.x*textureSizeW), (int)(pos.y*textureSizeH), Color.white);

Результат, как и ожидалось, правильный:
1 | [Решено]Проекция точек на экран. Unity3d. Воссоздание метода WorldToViewportPoint

2) Считаю матрицу ModelViewProjection и умножаю на нее локальные координаты вершины

Matrix4x4 M = goTransform.localToWorldMatrix;
Matrix4x4 V = mCamera.worldToCameraMatrix;
Matrix4x4 P = mCamera.projectionMatrix;
Matrix4x4 MVP = P*V*M;
 
Vector3 pos = MVP.MultiplyPoint(vertices[j]);
texture.SetPixel((int)(pos.x*textureSizeW), (int)(pos.y*textureSizeH), Color.white);

В результате получается что-то слабо похожее на куб:
2 | [Решено]Проекция точек на экран. Unity3d. Воссоздание метода WorldToViewportPoint
Ну и собсна вопрос: что я упускаю, чего не хватает? Спасибо за помощь!

#1
16:23, 4 ноя 2014

У меня в связи с вашим постом пока 2 вопроса.
Как вы посчитали скорость работы WorldToViewPort (мой опыт показывает, что даже на 1 айпаде вызов этой функции в Update никоим образом не влияет на fps)
Как вы пришли к выводу, что ваш код будет быстрее?

Насчет того, что вы нигде ничего не нашли, как минимум
тут http://answers.unity3d.com/questions/12713/how-do-i-reproduce-the… p-matrix.html
и тут http://unity3d.ru/distribution/viewtopic.php?f=5&t=908
есть все необходимые ответы)))

Удачи))

#2
16:42, 4 ноя 2014

> Как вы посчитали скорость работы WorldToViewPort (мой опыт показывает, что даже
> на 1 айпаде вызов этой функции в Update никоим образом не влияет на fps)
> Как вы пришли к выводу, что ваш код будет быстрее?
Профайлером, естественно. 10k объектов, отсекаю невидимые по фруструму и aabb каждого проецирую "на экран". Производительность упирается в WorldToViewportPoint. Пробовал свою (матрицу х вектор) - не упирается. Ну и вообще, потокобезопасность не помешала бы.
> тут http://answers.unity3d.com/questions/12713/how-do-i-reproduce-the…
> p-matrix.html
отсюда я и спер код для второго способа =)
добавление

if (d3d) {
    // Invert Y for rendering to a render texture
    for (int i = 0; i < 4; i++) {
        p[1,i] = -p[1,i];
    }
    // Scale and bias from OpenGL -> D3D depth range
    for (int i = 0; i < 4; i++) {
        p[2,i] = p[2,i]*0.5f + p[3,i]*0.5f;
    }
}

на результат не влияет, т.к. я на мобилках проверяю.
> и тут http://unity3d.ru/distribution/viewtopic.php?f=5&t=908
судя по всему закончилось печально((

#3
19:47, 4 ноя 2014

Belfegnar
> Профайлером, естественно. 10k объектов
При таком количестве объектов, конечно да, все что в Update - печально.

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

#4
21:35, 4 ноя 2014

Belfegnar
эээ... ну...
1. Порядок умножения матриц точно правильный?
2. Вектор 1x3 умножается на матрицу 4x4 - точно ли оно работает именно так как нужно, с делением на w?

#5
10:47, 9 ноя 2014

Fate Li
> Попробуйте через шейдерный код экспериментально определить как матрица MVP
> получается, там вроде есть все необходимые компоненты для этого.
хм... как ни странно, когда передаю свою матрицу MVP в шойдер и умножаю на нее позицию вершины, в GameView кубик отображается верно...
-Eugene-
> Вектор 1x3 умножается на матрицу 4x4 - точно ли оно работает именно так как
> нужно, с делением на w?
расковырял илспаем, внутрях у них там вот такое:

public Vector3 MultiplyPoint(Vector3 v)
    {
      Vector3 result;
      result.x = this.m00 * v.x + this.m01 * v.y + this.m02 * v.z + this.m03;
      result.y = this.m10 * v.x + this.m11 * v.y + this.m12 * v.z + this.m13;
      result.z = this.m20 * v.x + this.m21 * v.y + this.m22 * v.z + this.m23;
      float num = this.m30 * v.x + this.m31 * v.y + this.m32 * v.z + this.m33;
      num = 1f / num;
      result.x *= num;
      result.y *= num;
      result.z *= num;
      return result;
    }
#6
12:11, 9 ноя 2014

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

int x = (int)((pos.x + 1.0f) * 0.5f * sizeW);
int y = (int)((1.0f - pos.y) * 0.5f * sizeH);
ПрограммированиеФорумОбщее

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