Войти
ПодсказкиСтатьи

Orbit Camera

Автор:

Камера которая крутится вокруг какого-то объекта.

Создание view матрицы:

void miViewportCamera::Update() {
  switch (m_type)
  {
  case miViewportCameraType::Perspective:
    math::makePerspectiveRHMatrix(m_projectionMatrix, m_fov, m_aspect, m_near, m_far);
  break;
  default:
    f32 zoom = m_positionPlatform.w;
    m_near = -m_far;
    math::makeOrthoRHMatrix(m_projectionMatrix, 
      zoom * m_aspect,
      zoom,
      m_near, m_far);
    break;
  }


  Mat4 MX(Quat(m_rotationPlatform.x, 0.f, 0.f));
  Mat4 MY(Quat(0.f, m_rotationPlatform.y, 0.f));
  //Mat4 MZ(Quat(0.f, 0.f, m_rotationPlatform.z));

  m_positionCamera = v3f(0.f, m_positionPlatform.w, 0.f);
  m_positionCamera = math::mul(m_positionCamera, (MY * MX));
  m_positionCamera += v3f(m_positionPlatform.x, m_positionPlatform.y, m_positionPlatform.z);

  Mat4 T;
  T.m_data[3].x = -m_positionCamera.x;
  T.m_data[3].y = -m_positionCamera.y;
  T.m_data[3].z = -m_positionCamera.z;
  T.m_data[3].w = 1.f;

  Mat4 P(Quat(v4f(-m_rotationPlatform.x + math::degToRad(-90.f), 0.f, 0.f, 1.f)));
  Mat4 Y(Quat(v4f(0.f, -m_rotationPlatform.y + math::degToRad(0.f), 0.f, 1.f)));
  Mat4 R(Quat(v4f(0.f, 0.f, m_rotationPlatform.z, 1.f)));

  m_viewMatrix = (R*(P * Y)) * T;
  m_viewProjectionMatrix = m_projectionMatrix * m_viewMatrix;

  auto vi = m_viewMatrix; vi.invert();
  auto pi = m_projectionMatrix; pi.invert();
  m_viewProjectionInvertMatrix = vi*pi;
  m_frust.CalculateFrustum(m_projectionMatrix, m_viewMatrix);
}

Для зума\наезда камеры вперёд\назад используется - m_positionPlatform.w

Вот методы

Panoramic view. Я почему-то назвал Pan Move, наверно потому что камера перемещается.

void miViewportCamera::PanMove() {
  f32 speed = 30.f * (m_positionPlatform.w*0.01f);

  v4f vec(
    speed * -g_app->m_inputContext->m_mouseDelta.x * g_app->m_dt,
    0.f, 
    speed * -g_app->m_inputContext->m_mouseDelta.y * g_app->m_dt,
    0.f);
  Mat4 MX(Quat(m_rotationPlatform.x, 0.f, 0.f));
  Mat4 MY(Quat(0.f, m_rotationPlatform.y, 0.f));
  //Mat4 MZ(Quat(0.f, 0.f, m_rotationPlatform.z));
  vec = math::mul(vec, MY * MX);
  m_positionPlatform += vec;
}

void miViewportCamera::Rotate() {
  m_rotationPlatform.x += g_app->m_inputContext->m_mouseDelta.y * g_app->m_dt;
  m_rotationPlatform.y += g_app->m_inputContext->m_mouseDelta.x * g_app->m_dt;
}

void miViewportCamera::Zoom() {
  f32 mult = 1.f;
  if (g_app->m_keyboardModifier == miKeyboardModifier::Shift)
    mult = 3.f;
  
  if(g_app->m_inputContext->m_wheelDelta > 0)
    m_positionPlatform.w *= 0.9f * (1.f/ mult);
  else
    m_positionPlatform.w *= 1.1f * mult;

  if (m_positionPlatform.w < 0.01f)
    m_positionPlatform.w = 0.01f;
}

void miViewportCamera::ChangeFOV() {
  m_fov += g_app->m_inputContext->m_mouseDelta.x * g_app->m_dt;
  if (m_fov < 0.01f)
    m_fov = 0.01f;
  if (m_fov > math::PI)
    m_fov = math::PI;
}

void miViewportCamera::RotateZ() {
  m_rotationPlatform.z += g_app->m_inputContext->m_mouseDelta.x * g_app->m_dt;
}

void miViewportCamera::Reset() {
  m_near = 0.0001f;
  m_far  = 1000.f;
  m_fov  = math::degToRad(90.f);
  m_aspect = 800.f / 600.f;
  m_positionPlatform = v4f(0.f, 0.f, 0.f, 15.f);
  m_rotationPlatform = v3f(math::degToRad(-45.f), 0.f, 0.f);
}


Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры

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

#камера

12 апреля 2021 (Обновление: 29 мая 2021)