Перейти к содержанию
    

Перевод из сферической системы координат в декартову.

Добрый день, друзья. Есть у меня 3D библиотека, настроил я ее, нарисовал кубик. Теперь хочу его покрутить (при помощи сенсорного экрана).

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

Я решил поступить по другому - вращать не объект, а перемещать камеру вокруг кубика.  То есть точка прицела камеры всегда в координатах 0,0,0, а сама камера гуляет по поверхности сферы радиусом 10.

Иными словами - ведешь по экрану вверх-вниз - меняется зенитный угол, ведешь вправо-влево -  меняется азимут.

Высчитываю по вот такой формуле

ff18b6086ad611568d8dc6656715a29e0f76c540

 

В коде это выглядит так:

       azimuthal+=(float32_t)d_evt.getDeltaX()/495;  // Преобразуем  горизонтальный пробег пальца по экрану в приращение азимута
            zenital+=(float32_t)d_evt.getDeltaY()/445; // Преобразуем  вертикальные пробег пальца по экрану в приращение зенитного угла
            

            dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal),
                                                  10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal),
                                                  10*arm_cos_f32(zenital)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0)

Вращение камеры почему-то неадекватное. Даже трудно описать в чем, но чем дальше поворачивается кубик, тем неадекватнее его реакция на движение.

 

 

проверял отладкой преобразование пробега пальца по экрану в параметры azimuthal и zenital - оно адекватное.

Саму камеру перемещал вверх-вниз, вправо-влево - тоже адекватно.  Но она при этом движется во фронтальное плоскости перед объектом, что не соответствует желаемому. А желаемое - двигаться в пределах сферы, окружающей объект.

 

В упор не вижу ошибки, в чем она может быть?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, Salamander сказал:

В упор не вижу ошибки, в чем она может быть?

Как отсчитываете зенитный угол:

- угол между осью Z и вектором r

- угол между плоскостью XY и вектором r

У вас формулы для первого случая. Он соответствует всей прочей логике вашей программы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, Darth Vader said:

Как отсчитываете зенитный угол:

- угол между осью Z и вектором r

- угол между плоскостью XY и вектором r

Плоскость XY смотрит на меня

Из нее же на меня направлена ось Z.

В этом случае отличие способа отсчета должно сказаться лишь на том, куда будет смотреть камера при угле, скажем, 0 градусов - на "фасад" или на "крышу". Но на вращение то это не должно влиять.

 

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

https://cloud.mail.ru/public/whtu/BXQvRUxSV

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага.... разница в том, что в моей библиотеке ось Z смотрит на экран, а в формуле - вверх. Переставил оси - вроде заработало почти как надо.   Только вот зенит почему-то работает только в пределах 0-180 градусов.... пытаешься заглянуть под объект, при пересечении 0 или 180 градусов начинается вращение  в обратную сторону. Это как побороть?

   dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal),
                           10*arm_cos_f32(zenital),   
						   10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal));

Вот такая на данный момент формула

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Salamander сказал:

пытаешься заглянуть под объект, при пересечении 0 или 180 градусов начинается вращение  в обратную сторону. Это как побороть?

Не понятно, что значит в обратную сторону? При переходе через 0 и 180 градусов у вас множитель

 

3 часа назад, Salamander сказал:

arm_sin_f32(zenital)

также переходит через 0 и меняет знак на противоположный. Может это и воспринимается визуально, как вращение в обратную сторону.

Сделайте картинку с расположением осей и углов. Особо обратите внимание на зенитный угол - как он отсчитывается. Проверьте, чтобы везде, где он используется в программе его отсчет был одинаков - это угол между вектором r и осью Z.

Функция dsp3D_setCameraPosition(х,y,z) - подразумевает, что плоскость экрана монитора совпадает с плоскостью XY, а ось Z перпендикулярна ему и смотрит НА наблюдателя.

Вы же считаете, что экран расположен в плоскости XZ, а ось Y перпендикулярна экрану и направлена ОТ наблюдателя.

В этом случае формула преобразования координат будет такой:

x=x1; y=z1; z=-y1;

Здесь (x1,y1,z1) - координаты в вашей системе, а (x,y,z) - координаты для функции  dsp3D_setCameraPosition. У вас же для координаты z в формуле пропущен минус.

Изменено пользователем Darth Vader

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Darth Vader said:

В этом случае формула преобразования координат будет такой:

x=x1; y=z1; z=-y1;

Здесь (x1,y1,z1) - координаты в вашей системе, а (x,y,z) - координаты для функции  dsp3D_setCameraPosition. У вас же для координаты z в формуле пропущен минус.

Сделал, работает. Не совсем так как думалось изначально - если камеру поднять высоко, то она по азимуту описывает воронку - но так даже лучше.

 

Но все равно с зенитом фигня - не хочет камера подныривать по горизонтальную плоскость. То есть угол в -1 градус воспринимается как угол в 1 градус и так далее. Угол в 181 градус воспинимается как угол в 179 градусов

Изменено пользователем Salamander

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 минут назад, Salamander сказал:

То есть угол в -1 градус воспринимается как угол в 1 градус и так далее. Угол в 181 градус воспинимается как угол в 179 градусов

Вы определитесь, какой угол вы сейчас описываете. Чему он равен в сферической системе координат? Ваш -1 градус соответствует зенитному углу 91 градус, а 181 - это -91 градус (или 269 градусов). Т.е. здесь вы считаете угол между вектором r и вашей горизонтальной  плоскостью XY. Может из-за этого у вас такие проблемы? Я специально обращал ваше внимание на зенитный угол - чтобы он везде во всех частях программы отсчитывался единообразно. Проверьте это.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, Darth Vader сказал:

сферической системе координат?

Что за система такая? "Полярную" - знаю ещё со школы, про "сферическую" - впервые слышу.  :umnik2:

Это случайно не та, в которой вакуумный конь расположен?  :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, Darth Vader said:

Ваш -1 градус соответствует зенитному углу 91 градус, а 181 - это -91 градус (или 269 градусов). Т.е. здесь вы считаете угол между вектором r и вашей горизонтальной  плоскостью XY. Может из-за этого у вас такие проблемы?

Вы уверены, что в этом случае будут какие-то проблемы помимо неправильного положения объекта перед камерой? Точнее в ошибке поворота, составляющей 90 градусов?

Смотрите, я отклоняю камеру  в зените на некий угол - отклоняю бесконечно, и неважно, что у меня идет после 360 - 361 или 1 - камера должна идти по кругу. У меня же почему то движение только в пределах полупериода, в следующем полупериоде направление движения меняется.

2 minutes ago, jcxz said:

Это случайно не та, в которой вакуумный конь расположен?  

Она самая

http://900igr.net/up/datas/183262/021.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, jcxz сказал:

"Полярную" - знаю ещё со школы, про "сферическую" - впервые слышу.

Полярная - это двумерная, на плоскости. А сферическая - трехмерная, в пространстве.

15 минут назад, Salamander сказал:

отклоняю бесконечно, и неважно, что у меня идет после 360 - 361 или 1 - камера должна идти по кругу. У меня же почему то движение только в пределах полупериода, в следующем полупериоде направление движения меняется.

Такое впечатление, что какая-то из функций приводит значение входного аргумента к какому-то диапазону, например от 0 до 180 градусов. И это приведение преобразует угол -1 градус в 1, 181 в 1 и т.д. Надо смотреть отладчиком такие случаи. Не видя входных и выходных данных расчетов не разберешься.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 minutes ago, Darth Vader said:

Такое впечатление, что какая-то из функций приводит значение входного аргумента к какому-то диапазону, например от 0 до 180 градусов.

А вот и нет. Входной параметр у меня в норме. Смотрю его отладчиком

Вот окончательный вариант

   dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal),
                               10*arm_cos_f32(zenital),   
															 -10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0)
			dsp3D_setLightPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal),
                               10*arm_cos_f32(zenital),   
															 -10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0)

			

 

Смена направления у меня происходит как раз, когда значение zenital переходит через ноль.

Блин.... так все правильно - Z у меня рассчитывается по формуле sin*sin, при отрицательном угле зенита оба синуса отрицательные, в произведении это дает плюс.

Я понял.... надо в зависимости от полярности зенитного угла менять полярность Z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, Salamander сказал:

Входной параметр у меня в норме. Смотрю его отладчиком

Имеется ввиду как его внутри обрабатывают функции dsp3D_setCameraPosition,  dsp3D_setLightPosition. Надо посмотреть, какие они дают результаты для ваших характерных "подгоризонтных" сферических координат (zenital более 90 градусов).

Для отладки сделайте 3 структуры:

- сферические координаты камеры исходные

- прямоугольные координаты в СК исходного объекта (на который смотрит камера)

- прямоугольные координаты в СК функции dsp3D_setCameraPosition

 

Задавайте значения сферических координат в первой структуре, меняя только zenital, и смотрите, что будет в двух других при переходе через 90 и минус 90  градусов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

1 hour ago, Darth Vader said:

 

 

Задавайте значения сферических координат в первой структуре, меняя только zenital, и смотрите, что будет в двух других при переходе через 90 и минус 90  градусов.

Ахахах, уписаться можно))))

Сделал я как вы сказали - с численными значениями координат все нормально. Они меняются как надо.

А смена направления вращения - это ИЛЛЮЗИЯ! Камера при переходе через горизонт почему-то переворачивается на 180 градусов вокруг оси, соответствующей направлению взгляда. И кубик, который только что "падал" от нас, начинает на нас "заваливаться".

Да.... с этой то проблемой я разобрался, теперь нужно лезть в библиотеку и искать где там настройки поворота камеры.

Изменено пользователем Salamander

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...