Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Вид от 1 лица или квантернионы.

Вид от 1 лица или квантернионы.

Поделиться
ErmitashПользовательwww10 окт. 201722:43#0
Всем привет. Решил создать камеру от 1 лица в Unity и вместо того, чтобы воспользоваться видеоуроками с готовыми функциями я решил испортить себе жизнь. Вот мой код:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FirstPersonScript : MonoBehaviour {

    float vertical;
    float horizontal;
    public float mouse_x;
    float mouse_y;
  // Use this for initialization
  void Start () {

    }
  
  // Update is called once per frame
  void Update () {
        Vector3 new_axes = new Vector3();
        Vector3 rotate = new Vector3(0, 1, 0);
        Vector3 rotate_y = new Vector3(1, 0, 0);
        rotate_y = rotate_y.normalized;
        rotate =rotate.normalized;

        new_axes = this.transform.localPosition;
        vertical = Input.GetAxisRaw("Vertical");
        horizontal = Input.GetAxisRaw("Horizontal");
        mouse_x = Input.GetAxisRaw("Mouse X");
        mouse_y = Input.GetAxisRaw("Mouse Y");
        mouse_x *= (Mathf.PI / 180);
        mouse_y *= -(Mathf.PI / 180);
        new_axes.x -= horizontal;
        new_axes.z -= vertical;
        this.transform.localPosition = new_axes;

         Quaternion new_rotate_x = new Quaternion(Mathf.Sin(mouse_x/2)*rotate.x, Mathf.Sin(mouse_x / 2) * rotate.y, Mathf.Sin(mouse_x / 2) * rotate.z, Mathf.Cos(mouse_x / 2) );
          Quaternion new_rotate_y = new Quaternion(Mathf.Sin(mouse_y / 2) * rotate_y.x, Mathf.Sin(mouse_y / 2) * rotate_y.y, Mathf.Sin(mouse_y / 2) * rotate_y.z, Mathf.Cos(mouse_y / 2));

        this.transform.localRotation *= new_rotate_x*new_rotate_y;
    }
}
Я знаю, что все тут реализовано криво, но чтобы дорабатывать до норм камеры сначала нужно разобраться с поворотом. Вообщем проблема такая, что при повороте камеры меняется ось X и в итоге, когда я хочу повернуть влево относительно старой системы координат, он почему-то поворачивает относительно новой. "this"- это камера, скрипт пишется для камеры.
PA3UJIbПостоялецwww11 окт. 20178:18#1
я хочу повернуть влево относительно старой системы координат, он почему-то поворачивает относительно новой

Логично, если система отсчета сменилась, то трансформации вычисляются относительно новой системы отсчета.
Почему бы не реализовать вращение на векторах и углах? Хранить в камере два угла вращения и их помощью вращать систему отсчета камеры.
DeamonПостоялецwww11 окт. 201715:09#2
PA3UJIb
> Почему бы не реализовать вращение на векторах и углах? Хранить в камере два
> угла вращения и их помощью вращать систему отсчета камеры
У местной фауны кватернионы - это нечто вроде священного грааля. Почему то считают, что если повороты сделаны на кватеринонах - это круто, правильно, тыр пыр восемь дыр
ErmitashПользовательwww11 окт. 201715:43#3
Deamon, дай норм ссылку, где можно почитать об этом и я тебе только спасибо скажу. Думаешь мне приятно сидеть и осознавать, что нынешнее поколение глупее и все что может это пользоваться готовыми функциями? Подозреваю, что надо искать в Лин. алгебре или ТФКП.
DampireПостоялецwww11 окт. 201715:51#4
Допили как-нибудь сам напильником. original можешь брать на в Start. Это не из юнити копипаста. Я этот код таскаю за собой уже несколько лет из проекта в проект. Смысл аналогичен твоему, только косяки в логике отсутствуют.
+ Показать

Правка: 11 окт. 2017 15:52

ErmitashПользовательwww11 окт. 201716:20#5
Dampire, ща попробую, спасибо)
DeamonПостоялецwww11 окт. 201716:32#6
Ermitash
Это чистый линал.
Вот пример моего поликостылизма: https://github.com/Deamon87/WebWowViewerCpp/blob/master/wowViewer… .cpp#L75-L119
Система координат: Z-up.

Что я делаю:
1) беру вектор dir(1, 0, 0)
2) поворачиваю его двумя углами поворота и на строчке 93 получаю вектор направления в котором смотрит камера
3) далее от этого вектора беру вектор вправо на строчке 100. Высчитываю новую позицию камеры
4) В конце получаю точку на которую смотрит камера простым сложением векторов: newCameraPos + dir.

А дальше любая математическая библиотека имеет функцию, которая берет векторая cameraPos, lookAt и выдает lookAtMat4 (aka View Matrix)

ЗЫ: в ближайшем будущем планирую эту функцию переработать. Потому что в случае когда dir[0] = 0 и dir[1] = 0 в той самой фукнции которая дает lookAtMat4 получается деление на ноль. Т.е. нужно вращать не dir, единичную матрицу, чтобы получить на выходе сразу lookAtMat4

Правка: 11 окт. 2017 16:36

ErmitashПользовательwww11 окт. 201718:32#7
Deamon
Пару вопросиков:
Здесь выходит вычисляются расстояния пройденные мышкой, но зачем умножать на то, что находится в скобках? Ведь расстояние S=t*v.
float horizontalDiff = dTime * moveSpeed * (this->MDHorizontalPlus - this->MDHorizontalMinus);
    float depthDiff      = dTime * moveSpeed * (this->MDDepthPlus - this->MDDepthMinus) + this->depthDiff;
    float verticalDiff   = dTime * moveSpeed * (this->MDVerticalPlus - this->MDVerticalMinus);

Вот тут не нашел функций RotationY, RotationX, RotationZ. Ща еще порыскаю в гитхабе.

dir = mathfu::mat3::RotationY(this->av/M_PI_2) * dir;
    dir = mathfu::mat3::RotationZ(-this->ah/M_PI_2) * dir;
    dir = mathfu::normalize(dir);

DeamonПостоялецwww11 окт. 201718:51#8
Ermitash
this->MDHorizontalPlus и прочие - это булевые переменные. 0 или 1. Нужно это чтобы, когда пользователь зажимает одновременно A и D (стрейф влево и вправо) - камера стояла на месте.

mathfu::mat3::RotationY и mathfu::mat3::RotationZ можно найти здесь https://github.com/google/mathfu/blob/e59379a8038ff32b45808c1f63a… x.h#L757-L768

Правка: 11 окт. 2017 18:53

DeamonПостоялецwww11 окт. 201718:53#9
Поправил ссылку в последнем посте
g-contПостоялецwww12 окт. 201713:03#10
С кватернионами для камеры от первого лица имеет смысл заморачиваться, только если PITCH не имеет жесткого клампинга на -89\+89. Иначе хватает и обычных углов Эйлера.
ChebПостоялецwww12 окт. 201713:52#11
Если это шутан, то люди уже *привыкли* к углам Эйлера, и любая другая будет им *неудобна*, даже если объективно лучше.
Dmitry_MilkПостоялецwww12 окт. 201720:03#12
Cheb
> Если это шутан, то люди уже *привыкли* к углам Эйлера, и любая другая будет им
> *неудобна*, даже если объективно лучше.

Есть еще игрулины типа Descent или Shattered Horizon. Там Эйлер не катит. Может топикстартер подобную замышляет?

ErmitashПользовательwww12 окт. 201720:33#13
Я реализовал с квантернионами, единственное, что все равно буду использовать наверное готовый скрипт.

/ Форум / Программирование игр / Графика

2001—2017 © GameDev.ru — Разработка игр