2013-10-03 2 views
3

я исследовал кватернионные реализации SSE, чтобы понять, как они работают (так как я реализации мои собственные), и я наткнулся на эту реализацию Пули для умножения кватернионов:Пули реализация Физика кватернионов ссе сомнения

VECTORMATH_FORCE_INLINE const Quat Quat::operator *(const Quat &quat) const 
{ 
    __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; 
    __m128 product, l_wxyz, r_wxyz, xy, qw; 
    ldata = mVec128; 
    rdata = quat.mVec128; 
    tmp0 = _mm_shuffle_ps(ldata, ldata, _MM_SHUFFLE(3,0,2,1)); 
    tmp1 = _mm_shuffle_ps(rdata, rdata, _MM_SHUFFLE(3,1,0,2)); 
    tmp2 = _mm_shuffle_ps(ldata, ldata, _MM_SHUFFLE(3,1,0,2)); 
    tmp3 = _mm_shuffle_ps(rdata, rdata, _MM_SHUFFLE(3,0,2,1)); 
    qv = vec_mul(vec_splat(ldata, 3), rdata); 
    qv = vec_madd(vec_splat(rdata, 3), ldata, qv); 
    qv = vec_madd(tmp0, tmp1, qv); 
    qv = vec_nmsub(tmp2, tmp3, qv); 
    product = vec_mul(ldata, rdata); 
    l_wxyz = vec_sld(ldata, ldata, 12); 
    r_wxyz = vec_sld(rdata, rdata, 12); 
    qw = vec_nmsub(l_wxyz, r_wxyz, product); 
    xy = vec_madd(l_wxyz, r_wxyz, product); 
    qw = vec_sub(qw, vec_sld(xy, xy, 8)); 
     VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; 
    return Quat(vec_sel(qv, qw, sw)); 
} 

Бит I беспокоит эти две линии:

l_wxyz = vec_sld(ldata, ldata, 12); 
r_wxyz = vec_sld(rdata, rdata, 12); 

реализация Макросы:

#define _mm_ror_ps(vec,i)  \ 
    (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) 

#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) 

Если я правильно понимаю, для числа, которое не делится на 4 (3 не [12/4 = 3]), то vec_sld макрос сведет к:

l_wxyz = ldata;//vec_sld(ldata, ldata, 12); 
r_wxyz = rdata;//vec_sld(rdata, rdata, 12); 

Который эффективно ничего не делать.

И если значение делится на 4:

q = vec_sld(x, x, 16); 

Макрос сведет к:

q = _mm_shuffle_ps(x, x, _MM_SHUFFLE(3,2,1,0)); 

Который, опять же, как ничего не делать, так как _MM_SHUFFLE (3,2,1 , 0) оставляют x, y, z и w в своих текущих местах.

Если vec_sld ничего не делает, в чем его цель?

Я ничего не пропустил?

EDIT: Вот два файла исходного кода происходит от

+0

Можете ли вы сказать нам, где вы нашли этот код? – AakashM

+0

Я отредактировал сообщение со ссылками на соответствующий исходный код Bullet Physics. –

ответ

3

Я думаю, где вы запутались, так это то, что ((i)%4) оценил (а) TRUE, когда i был не несколько раз, поэтому вы получаете _mm_shuffle_ps для не кратных 4, иначе вы просто получите исходный вектор (так как поворот на несколько из 4-это не-op).

Некоторые фона, которые могут быть полезны:

В vec_XXX макросы указывают, что этот код изначально был перенесен с PowerPC/AltiVec. vec_sld является внутренним элементом AltiVec, который сдвигает пару векторов на заданное число байтов. В этом контексте представляется, что vec_sld используется для вращения одного вектора, поскольку два входных вектора являются одинаковыми, и кажется, что 12 передается как сдвиг (т. Е. Вращается на 3 поплавка).

Так vec_sld(v, v, 12) переводится на _mm_ror_ps(v, 12/4) = _mm_ror_ps(v, 3) которая затем расширена:

_mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 1, 0, 3); 

так это выглядит, как если код делает правильную вещь.

+1

Правильно! В самом деле, я запутался в '((i)% 4)?'. Я делал несколько тестов вручную, и я упустил из виду, что на самом деле он оценивает истину для всех правильных случаев. Благодаря! –

Смежные вопросы