Вычислите точку XYZ сферы, учитывая UV-координату ее текстуры.

У меня есть сфера в 3D. Во время выполнения я создаю для него динамическую текстуру 2048x1024. На этой текстуре нарисован крошечный круг, который может быть где угодно. У меня есть x/y этого круга на текстуре и, следовательно, соответствующие координаты UV. Теперь я хотел бы интерполировать, где именно на моей сфере находится этот маленький кружок.

Это код, который я использовал, но он всегда кажется отклоненным на +/- 90 градусов.

// U, V are original UV obtained from dynamic texture.

_u =  Math.PI * U;  
_v =  -2 * Math.PI * V;

_x = Math.cos(_u) * Math.sin(_v) * radius;
_y = Math.sin(_u) * Math.sin(_v) * radius;
_z = Math.cos(_v) * radius;

Спасибо за любую помощь!


person Brad    schedule 20.10.2011    source источник


Ответы (3)


Согласно коду, который вы разместили в комментариях, вот как сгенерировать значения X, Y и Z.

theta = 2 * PI * U;
phi = PI * V;

_x = Math.cos(theta) * Math.sin(phi) * radius;
_y = Math.sin(theta) * Math.sin(phi) * radius;
_z = -Math.cos(phi) * radius;

СТАРЫЙ ОТВЕТ:

Ваш код в порядке. Вы уверены, что сфера генерируется таким же образом, и что полюса расположены вдоль оси Z вот так? «Обычно» сферы генерируются с полюсами вдоль оси Y. Проверь это.

В противном случае, если вы всегда ошибаетесь на +/- 90°, поэкспериментируйте с sin и cos, определяющими x и y. Например:

_x = -Math.sin(_u) * Math.sin(_v) * radius;
_y = Math.cos(_u) * Math.sin(_v) * radius;

Является поворотом оригинала на 90°.

Есть 8 различных способов вычислить sin/cos этих двух компонентов с разными знаками. Не зная, как генерируется ваша сфера, вам придется попробовать их все. Они идут

(x = sin(u), y = cos(u));
(x = sin(u), y = -cos(u));
(x = -sin(u), y = cos(u));
(x = -sin(u), y = -cos(u));

(x = cos(u), y = sin(u));
(x = cos(u), y = -sin(u));
(x = -cos(u), y = sin(u));
(x = -cos(u), y = -sin(u));

Однако это болезненно и хакерски, я настоятельно рекомендую попытаться выяснить, как генерируется ваша сфера. Обычно они генерируют позиции x, y, z, перебирая U и V.

person Hannesh    schedule 20.10.2011
comment
Спасибо за это - полюса находятся на оси Y (Y-UP тоже), если это что-то меняет. - person Brad; 20.10.2011
comment
Боюсь, что до сих пор не понял :( - person Brad; 21.10.2011
comment
Есть много способов нанести UV-координаты на сферу, это зависит от того, как генерируется ваша сфера. Откуда взялась ваша сфера? Вы используете OpenGL или DirectX? - person Hannesh; 21.10.2011
comment
вот как генерируются UV (извините за отсутствие правильного интервала): numUvs = 0; for (j = 0; j ‹= _segmentsH; ++j) { for (i = 0; i ‹= _segmentsW; ++i) { uvData[numUvs++] = i / _segmentsW; uvData[numUvs++] = j / _segmentsH; } } - person Brad; 24.10.2011
comment
Это мало помогает. Если вы опубликуете весь код генерации сферы, я практически гарантирую вам правильный алгоритм ;). Просто отредактируйте свой вопрос еще раз и добавьте код генерации сферы. - person Hannesh; 24.10.2011
comment
github.com/away3d/away3d- core-fp11/blob/master/src/away3d/ — это класс, создающий сферу. - person Brad; 25.10.2011
comment
Извините за задержку, я обновил свой ответ. Дайте мне знать, если это работает. - person Hannesh; 31.10.2011

Убедитесь, что у вас определены правильные оси, т.е.:

ENU - восток север вверх NED - северо восток вниз

Преобразование отличается для NED и ENU, обычно потому, что азимутальный угол определяется одинаково, то есть по часовой стрелке относительно севера.

сделайте 90- на тета в каждом или используйте правило соугла.

Попробуйте вывести формулы самостоятельно. Убедитесь, что вы знаете, какие соглашения используются

person Yugi    schedule 31.10.2011

Уравнение, которое вы используете для создания сферы, рассматривает полюс как ось Z. Если вы используете что-то вроде GLUT, система координат по умолчанию имеет Z плюс нормаль к экрану, где «Вверх» является осью Y. Если вы поменяете местами Z и Y, это может сработать для вас. Я только что закончил делать что-то подобное, и я был доволен результатами.

Я использовал следующее.

double theta = ((2 * PI) / lWidth) * u;
double phi = (PI / lHeight) * v;

double dX = std::cos(theta) * std::sin(phi) * radius;
double dZ = std::sin(theta) * std::sin(phi) * radius;
double dY = std::cos(phi) * radius;

lWidth и lHeight — это размеры растрового изображения, которое я сопоставил со сферой.

person Lynxdom    schedule 09.10.2015