Привет. В который раз убеждаюсь, что оффорум юнити существует только для вопросов типа "где найти кнопку билда?". Ответ на что-то посложнее получить там просто невозможно. Может быть здесь кто-нибудь сталкивался с подобной задачей: перевод координат точки из мировых в вьюпорт/экран? Обычно для этого используется стандартный метод камеры 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 1 | [Решено]Проекция точек на экран. Unity3d. Воссоздание метода WorldToViewportPoint](https://gamedev.ru/files/images/101331_1415097521_1.png)
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 вопроса.
Как вы посчитали скорость работы 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
есть все необходимые ответы)))
Удачи))
> Как вы посчитали скорость работы 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
судя по всему закончилось печально((
Belfegnar
> Профайлером, естественно. 10k объектов
При таком количестве объектов, конечно да, все что в Update - печально.
Попробуйте через шейдерный код экспериментально определить как матрица MVP получается, там вроде есть все необходимые компоненты для этого.
Belfegnar
эээ... ну...
1. Порядок умножения матриц точно правильный?
2. Вектор 1x3 умножается на матрицу 4x4 - точно ли оно работает именно так как нужно, с делением на w?
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; }
Понял в чем проблема. Опытным путем определил, что, в результате всех манипуляций с вектором, получаем позицию в системе координат вьюпорта с нулем "в центре экрана". Правильные экранные координаты:
int x = (int)( ( pos.x + 1.0f) * 0.5f * sizeW); int y = ( int)( ( 1.0f - pos.y) * 0.5f * sizeH);
Тема в архиве.