Jump to content

    
Sign in to follow this  
Salamander

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

Recommended Posts

Добрый день, друзья. Есть у меня 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 ведь должен меняться...

Share this post


Link to post
Share on other sites
5 часов назад, Salamander сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
8 hours ago, Darth Vader said:

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

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

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

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

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

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

 

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

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

Share this post


Link to post
Share on other sites

Ага.... разница в том, что в моей библиотеке ось 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));

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

Share this post


Link to post
Share on other sites
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 в формуле пропущен минус.

Edited by Darth Vader

Share this post


Link to post
Share on other sites
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 градусов

Edited by Salamander

Share this post


Link to post
Share on other sites
15 минут назад, Salamander сказал:

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

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

Share this post


Link to post
Share on other sites
5 часов назад, Darth Vader сказал:

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

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

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
13 минут назад, jcxz сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
2 минуты назад, Salamander сказал:

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

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

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

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

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

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

 

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

Share this post


Link to post
Share on other sites

 

1 hour ago, Darth Vader said:

 

 

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

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

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

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

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

Edited by Salamander

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this