Author Topic: Работа с камерой. Полезные полезности.  (Read 1770 times)

0 Members and 1 Guest are viewing this topic.

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Как я и обещал, приведу несколько формул и прочего (возможно, интересного) для работы с камерой.
Ну сперва разберёмся, что такое камера и с чем её едят. Камера - это такой же обычные объект, как и все в 3D приложениях. Будь это сфера, куб или оооочень сложная геометрическая фигура. У камеры есть два основных значения, это её собственные координаты (x, y, z) и координаты точки, в которую должна смотреть камера (как правило совпадают с координатами игрока).
Создадим камеру и укажем её координаты.
Code: [Select]
Dim OurCamera As wCamera
OurCamera = wAddCamera(wNO_OBJECT, 200.0f, 0.5,0,0,0)
' координаты от Балды взяты
wSetNodePosition( OurCamera, x, y, z)
wSetCameraTarget(OurCamera, x2, y2, z2)
wSetActiveCamera(OurCamera)
Итак, приступим к самому интересному, перемещению камеры.
Давайте попробуем сперва её заставить двигаться вперёд/назад. Для этого придётся считывать нажатие клавиш (хотя бы).
Code: [Select]
While wKeyEventAvailable
KeyEvent = wReadKeyEvent
wGetNodePosition(OurCamera, x, y, z)
wGetCameraTarget(OurCamera, x2, y2, z2)
select case as const KeyEvent->key
   Case KEY_KEY_Q
   Case KEY_KEY_E
   Case KEY_KEY_W
   Case KEY_KEY_S
   Case KEY_KEY_A
   Case KEY_KEY_D
   wCloseKEY_ESC()
End Select
wSetNodePosition(OurCamera, x, y, z)
wSetCameraTarget(OurCamera, x2, y2, z2)
Wend
Стандартно для перемещения вперёд/назад будем использовать клавиши "W" и "S". Для перемещения нам нужно будет просто складывать вектора.
Code: [Select]
Dim OurCamera As wCamera
OurCamera = wAddCamera(wNO_OBJECT, 200.0f, 0.5,0,0,0)
' координаты от Балды взяты
wSetNodePosition( OurCamera, x, y, z)
wSetCameraTarget(OurCamera, x2, y2, z2)
wSetActiveCamera(OurCamera)
Для перемещения мы просто сложим два вектора.
Code: [Select]
Case KEY_KEY_W
         ' Получаем направление взгляда (напр-е, куда мы повернуты "лицом")
          x3 = x2-x1
          y3 = y2-y1
          z3 = z2-z1
         ' Двигаем камеру
         x += x3*0.5
         y += y3*0.5
         z += z3*0.5
         x2 += x3*0.5
         y2 += y3*0.5
         z2 += z3*0.5
Здесь 0.5 я использую для более плавного перемещения камеры. Всё выглядит легко, не правда ли?
Ну а теперь заставим камеру двигаться влево/вправо. Здесь уже посложнее будет, ибо отталкиваться от направления камеры уже не получится так легко...
Во первых, что такое шаг влево/вправо? Это перемещение в сторону от направления взгляда на 90 градусов. Как это вычислить? Лично я вычисляю из двух векторов, это первый - направление, а вот второе сами должны выводить. Это вертикальный вектор. Т.е. он должен смотреть вниз  ;) . Зная эти вектора, мы сможет по математической формуле cross вычислить перпендикулярный вектор от  вектора взгляда. Точнее мы вычислим так нормаль вектора  :)
Code: [Select]
vector3.x = (vector1.y * vector2.z) - (vector1.z * vector2.y)
vector3.y = (vector1.z * vector2.x) - (vector1.x * vector2.z)
vector3.z = (vector1.x * vector2.y) - (vector1.y * vector2.x)
Т.е. в коде это будет выглядеть примерно так:
Code: [Select]
Case KEY_KEY_A
     ' Нормализуем вектора
       x1 /= Normal
       y1 /= Normal
       z1 /= Normal
       x2 /= Normal
       y2 /= Normal
       z2 /= Normal
       ' Получаем направление взгляда (напр-е, куда мы повернуты "лицом")
       x3 = 1*z2-1*z1
       z3 = x1*1-x2*1
       wGetNodePosition(OurCamera, x1, y1, z1)
       wGetCameraTarget(OurCamera, x2, y2, z2)
       ' Двигаем камеру
       x1 -= x3*MapSize*MapScale
       z1 -= z3*MapSize*MapScale
       x2 -= x3*MapSize*MapScale
       z2 -= z3*MapSize*MapScale
      'EndIf

Ну а теперь рассмотрим, как вращать камеру вокруг выбранной точки. Для этого уже придётся воспользоваться синусами и косинусами  ;)
Для начала рассмотрим вращение как в стратегиях, т.е. вращение вокруг выбранной оси "за основу взята ось Y)
Code: [Select]

Case KEY_KEY_Q
         angle += 0.1
         If angle >= 360 Then angle = 0
         ' Производим вычисления
         x = x2-Sin(angle)*100
         z = z2-Cos(angle)*100
Здесь всё легко, как в школе. Вращение по системе 2D координат с указанием градусов angle... Другое дело, если мы попробуем вращать камеру ни вокруг оси, а вокруг выбранной точки.
Code: [Select]
Case KEY_KEY_Q
         angle += 0.1
         ' Вычислям cos и sin заранее, что бы потом не повторять по несколько раз эту же операцию
         cos1 = cos(angle);
         sin1 = sin(angle)
         If angle >= 360 Then angle = 0
         ' Производим вычисления
         x = (cos1+(1-cos1)*x*x)*x2
         x += ((1-cos1)*x*y-z*sin1)*y2
         x += ((1-cos1)*x*z+y*sin1)*z2

         y  = ((1-cos1)*x*y+z*sin1)*x2
         y += (cos1+(1-cos1)*y*y)*y2
         y += ((1-cos1)*y*z-x*sin1)*z2
 
         z  = ((1-cos1)*x*z-y*sin1)*x2
         z += ((1-cos1)*y*z+x*sin1)*y2
         z += (cos1+(1-cos1)*z*z)*z2
   
Ну и на последок давайте просто отдохнём и сделаем управление высотой мышки с помощью колёсика
Code: [Select]
While wMouseEventAvailable
          MouseEvent = wReadMouseEvent
          If MouseEvent->action = wME_MOUSE_WHEEL Then
                   m.wheel = MouseEvent->delta
           If m.wheel = 1 And LookAtY1 > 330 And LookAtY1-40 > HightMap[MapArray(LookAtX1\MapScale,LookAtZ1\MapScale)] Then
                     y -= 15
           ElseIf m.wheel = -1 And LookAtY1 < 900 Then
                     y += 15
           EndIf
           pre_m.wheel = m.wheel
           wSetNodePosition(OurCamera, x, y, z)
           EndIf
Wend

Ну так вроде и всё, что я хотел написать. Если есть вопросы - задавайте, пожелания - высказывайте  ;)
« Last Edit: September 03, 2015, 11:50:57 AM by it_is_good »

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Хорошее начало. Хороший урок.  :)
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Marsha

  • Friends
  • Knight
  • *
  • Posts: 128
  • Reputation 11
Да, it_is_good, cпасибо :) Ждем продолжения.

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Re: Работа с камерой. Полезные полезности.
« Reply #3 on: August 03, 2015, 02:16:11 AM »
Ну пока готово только перемещение без вращения. Скоро допишу. А также хотелось бы выслушать ваши пожелания и вопросы по камере и самой статье (может непонятно что)...
« Last Edit: August 03, 2015, 02:20:07 AM by it_is_good »

Offline Marsha

  • Friends
  • Knight
  • *
  • Posts: 128
  • Reputation 11
Re: Работа с камерой. Полезные полезности.
« Reply #4 on: August 10, 2015, 12:04:43 AM »
У меня вопрос, каким способом лучше запретить пролет камеры сквозь объекты, чтобы камера при этом оставалась свободной.

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Работа с камерой. Полезные полезности.
« Reply #5 on: August 10, 2015, 08:17:50 PM »
каким способом лучше запретить пролет камеры сквозь объекты, чтобы камера при этом оставалась свободной.
Сделать проверку столкновения камеры с другими объектами.
Quote
чтобы камера при этом оставалась свободной
Как понять?
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Re: Работа с камерой. Полезные полезности.
« Reply #6 on: August 10, 2015, 08:43:24 PM »
чтобы камера при этом оставалась свободной
Как понять?
Возможно имелось ввиду, что если на пути у камеры есть объект, то камера просто приближается к точке взгляда. Если именно это имелось ввиду, то нужно дополнительно добавить ещё одно значение, которое при столкновении с камерой нужно увеличивать и прибавлять к расположению самой камеры, а при отсутствии препятствия постепенно уменьшать до нуля, что бы камера вернулась в исходное положение...
Надеюсь, понятно объяснил. Если что, то завтра перечитаю свой ответ и подправлю...

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Работа с камерой. Полезные полезности.
« Reply #7 on: August 10, 2015, 09:18:23 PM »
Думаю, в данном топике нужно будет еще рассмотреть вопросы управления камерой/персонажем на основе физ. движка, например Newton.
Алгоритм управления несколько иной, так как там задействован апвектор (Upvector) и воздействие силами (Forces).
Под лежачий камень мы всегда успеем...

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Работа с камерой. Полезные полезности.
« Reply #8 on: August 25, 2015, 05:23:59 PM »
Привет всем. Экспериментирую с созданием игрового контроллера для управлением персонажа на основе Ньютон.
Только сейчас заметил опечатку:
Code: [Select]
OurCamera = wAddCamera(wNO_OBJECT, 200.0f, 0.5,0,0,0)При создании простой камеры (не FPS, не Maya)  НЕ УКАЗЫВАЕТСЯ родительский нод,
т.е. по состоянию на сегодняшний день
Code: [Select]
OurCamera = wAddCamera(0, 200.0f, 0.5,0,0,0)Кстати, это несколько странно, так как все другие камеры при создании имеют возможность указывать родителя.
Ошибки данный код товарища it_is_good не вызывает потому, что wNO_OBJECT тоже равно 0.
Думаю, эту ситуацию нужно исправить (точнее, уже исправлено, но пока не обновлено).
В следующем обновлении будет как положено:
Code: [Select]
OurCamera = wAddCamera(parent as wNode,0, 200.0f, 0.5,0,0,0)
« Last Edit: August 25, 2015, 09:03:49 PM by nikolas »
Под лежачий камень мы всегда успеем...

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Работа с камерой. Полезные полезности.
« Reply #9 on: August 26, 2015, 02:46:33 PM »
Ну да, дополнительный параметр (возможность выбора родителя) этой функции может пригодиться.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Работа с камерой. Полезные полезности.
« Reply #10 on: August 29, 2015, 09:25:43 PM »
По мотивам туториала товарища it_is_good написал пример, иллюстрирующий вышесказанное: перемещение камеры с помощью WASD. За основу
взял пример 5 с картой от кваки.
Правда, есть нюанс.
it_is_good предлагает находить смещение влево/вправо как векторное произведение двух векторов: 1) направление "взгляда" и 2) вертикаль
Но, если следовать логике, вектор вертикали (0,1,0) или (0,-1,0).
Тогда, если следовать приведенной формуле отсюда (https://mirgames.ru/topics/45), должно быть что-то типа:
Code: [Select]
x3=y*0-z*1
z3=x*1-y*0
В туториале написано так:
Code: [Select]

      x3 = 1*z2-1*z1
       z3 = x1*1-x2*1
В общем, вот  иллюстрирующий идею  вышенаписанного пример(надеюсь, it_is_good не сочтет за наглость с моей стороны).
Пока рабочий пример автор не выложил, пусть побудет этот.
« Last Edit: August 29, 2015, 09:36:34 PM by nikolas »
Под лежачий камень мы всегда успеем...

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Работа с камерой. Полезные полезности.
« Reply #11 on: August 30, 2015, 04:43:35 PM »
Сначала я не понял в чём фишка, ведь уже есть пример камеры с управлением WASD, но потом посмотрел внимательнее, стандартный пример с камерой от 1-го лица, а этот пример с обычной камерой. как написано выше в постах. Хороший пример. Можно от него дальше танцевать и сделать ещё 2 напрвления вверх-вниз, будет ещё одна реализация 6 DOF камеры.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Работа с камерой. Полезные полезности.
« Reply #12 on: August 31, 2015, 01:00:15 PM »
Quote
Думаю, в данном топике нужно будет еще рассмотреть вопросы управления камерой/персонажем на основе физ. движка, например Newton.
Алгоритм управления несколько иной, так как там задействован апвектор (Upvector)
Продолжение темы в ДАННОМ направлении здесь: http://worldsim3d.com/Forum/index.php?topic=113.msg1354#new
« Last Edit: August 31, 2015, 01:47:38 PM by nikolas »
Под лежачий камень мы всегда успеем...

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Re: Работа с камерой. Полезные полезности.
« Reply #13 on: September 03, 2015, 10:36:19 AM »
Сначала я не понял в чём фишка, ведь уже есть пример камеры с управлением WASD
Фишка заключается в том, что в играх можно будет перераспределять клавиши. Так же в некоторых проектах возможно и не потребуется перемещение камеры ("WASD"), а просто приближение/удаление. Так же есть возможность самому определить, как будет камера вращаться вокруг выбранной точки, либо как в стратегиях, либо как в космических симуляторах... Ну и конечно же совмещать управление камерой как мышкой, так и клавиатурой для удобства  ;)

И самая главная фишка!!! Я в отпуске с сегодняшнего дня. А это значит, что скоро допишу статью  ;D

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Re: Работа с камерой. Полезные полезности.
« Reply #14 on: September 03, 2015, 10:44:34 AM »
Правда, есть нюанс.
it_is_good предлагает находить смещение влево/вправо как векторное произведение двух векторов: 1) направление "взгляда" и 2) вертикаль
Но, если следовать логике, вектор вертикали (0,1,0) или (0,-1,0).
Тогда, если следовать приведенной формуле отсюда (https://mirgames.ru/topics/45), должно быть что-то типа:
Code: [Select]
   x3=y*0-z*1
      z3=x*1-y*0

Ну да, ступил немного. Просто я вертикаль выбирал не с "минусом", а с нулём. Вот отсюда и небольшие непонятки... То, что я умножаю на 1, дык это для большей наглядности...

А по сути все эти выводы и следствия из логики без самого кода так и остаются предположениями. Ибо уже при написании кода всплывают небольшие погрешности и уже самому приходится чуть-чуть подправлять все эти формулы под свои нужды...

 nikolas, я, кастати, вспомнил, почему я нуль брал за основу. Всё дело из-за моего проекта. Я знал, что камера не опустится по осу Y ниже нуля. Но вот что делать. если камера всё же дошла до нуля? Видимо, нужно будет брать за основу ни нуль и не знак минус, а просто отнимать 1 для точного вычисления, дабы всякие баги не вылезли...
« Last Edit: September 03, 2015, 11:13:53 AM by it_is_good »