Рассчитать матрицу вращения для преобразования одного вектора в другой? - PullRequest
0 голосов
/ 05 сентября 2018

Есть несколько вопросов по этому поводу в Stack Overflow, но большинство используют Quaternions, и я ищу что-то, чего нет. И этот вопрос существует во всем Интернете, но на удивление трудно найти простой пример в коде. Я ищу решение C / C ++ или GLSL / Metal для матрицы вращения для преобразования одного вектора в другой. Я нашел это, которое, кажется, отвечает на вопрос: http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38

Однако на практике это не работает для меня. При этом я получаю правильные преобразования под углами в девяносто градусов (то есть, трансформируя от 0,0,1 до 0,1,0), но между ними он поворачивается в неправильном направлении. Вот код, который я использую - кто-нибудь видит, что с ним не так?

В этом случае я всегда выполняю преобразование из фиксированной начальной нормали (0,0,1).

// matrix to rotate from (0,0,1) to specified direction

float4x4 directionMatrix(float3 direction) {

    float3 normal = float3(0.0,0.0,1.0);
    float3 V = normalize(cross(normal, direction));
    float phi = acos(dot(normal,direction));

    float rcos = cos(phi);
    float rsin = sin(phi);

    float4x4 M;

    M[0].x =        rcos + V.x * V.x * (1.0 - rcos);
    M[1].x =  V.z * rsin + V.y * V.x * (1.0 - rcos);
    M[2].x = -V.y * rsin + V.z * V.x * (1.0 - rcos);
    M[3].x = 0.0;

    M[0].y = -V.z * rsin + V.x * V.y * (1.0 - rcos);
    M[1].y =        rcos + V.y * V.y * (1.0 - rcos);
    M[2].y = -V.x * rsin + V.z * V.y * (1.0 - rcos);
    M[3].y = 0.0;

    M[0].z =  V.y * rsin + V.x * V.z * (1.0 - rcos);
    M[1].z = -V.x * rsin + V.y * V.z * (1.0 - rcos);
    M[2].z =        rcos + V.z * V.z * (1.0 - rcos);
    M[3].z = 0.0;

    M[0].w = 0.0;
    M[1].w = 0.0;
    M[2].w = 0.0;
    M[3].w = 1.0;

    return M;
}

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

РЕДАКТИРОВАТЬ: Проблема здесь оказалась в том, что этот код работает для левосторонней системы координат, где моя правша. Таким образом, чтобы это сработало, вам просто нужно умножить фи на -1. Я также отредактировал код, чтобы добавить нормализацию кросс-вектора, как это предлагается в комментариях.

...