Войти
ПрограммированиеПодсказкиОбщее

Компактное представление матрицы

Внимание! Этот документ ещё не опубликован.

Автор:

Предлагаю способ компактного представления ортогональной матрицы 3x3,  в виде вектора

размерности 3
Функции конвертации не используют тригонометрические функции и извлечения корня, только

арифм.действия
Возможная область применения - представление скелетной анимации и представление карты

нормалей в текстурах

Идея в том ортогональную матрицу 3x3 всегда можно представить как вращение вокруг некой

оси, если обохначить единичный направляющий вектор это оси - l, угол поворота - fi

(0<=fi<PI), то мы храним l*tg(fi/2) для fi<PI/2 и l*tg((fi-PI)/2) для fi>=PI/2
В результате тангенс вычисляется на промежутке [-PI/4,PI/4], знач-я от 0 до 1, и

изменяется достаточно равномерно, что позваоляет применить доп. квантизацию к результату

для еще большего сжатия данных

Матрица поворота вокруг оси (l,m,n) на угол fi

cosf=cos(fi)
sinf=sin(fi)

| l^2*(1-cosf)+cosf    l*m*(1-cosf)-n*sinf  l*n*(1-cosf)+m*sinf |
| l*m*(1-cosf)+n*sinf  m^2*(1-cosf)+cosf    m*n*(1-cosf)-l*sinf |
| l*n*(1-cosf)-m*sinf  m*n*(1-cosf)+l*sinf  n^2*(1-cosf)+cosf  |

Далее код:

// Преобразует матрицу в вектор
template<class T,class T2>
void MatrixToVector(Matrix3<T>& matr,Vector3<T2>& vec)
{
  // (l,m,n) - ось вращения, мы берем (l',m',n')=(l,m,n)*tg(fi/2)
  // cos(fi)=(m.a11+m.a22+m.a33-1.)/2
  // t=tg(fi/2)
  // cf=cos(fi)=(1-t^2)/(1+t^2)
  // t^2=(1-cf)/(1+cf)
  // a32-a23=2*l*sin(fi)=l*4*t/(1+t^2)=l'*4/(1+t^2)
  // 4/(1+t^2)=4/(1+(1-cf)/(1+cf))=2*(1+cf)=m.a11+m.a22+m.a33+1
  T d=matr.a11+matr.a22+matr.a33+1;
  vec.x=(matr.a32-matr.a23)/d;
  vec.y=(matr.a13-matr.a31)/d;
  vec.z=(matr.a21-matr.a12)/d;
}
//---------------------------------------------------------------------------

// Преобразует вектор в матрицу
template<class T,class T2>
void VectorToMatrix(Vector3<T2>& vec,Matrix3<T>& matr)
{
// t=tg(fi/2)
// (l',m',n')=(l,m,n)*t
// t^2=l'^2+m'^2+n'^2
// cos(fi)=(1-t^2)/(1+t^2)
// 1-cos(fi)=2*t^2/(1+t^2)
// sin(fi)=2*t/(1+t^2)
//               | l'^2+(1-t^2)/2   l'*m'-n'         l'*n'+m'       |
// = 2/(1+t^2) * | l'*m'+n'         m'^2+(1-t^2)/2   m'*n'-l'       |
//               | l'*n'-m'         m'*n'+l'         n'^2+(1-t^2)/2 |

  T l=vec.x;
  T m=vec.y;
  T n=vec.z;

  T t=l*l+m*m+n*n; // tg(fi/2)^2, -pi/2<=fi/2<pi/2
  
  T d=2./(1.+t);

  T L=l*d;
  T M=m*d;
  T N=n*d;

  T Ll=L*l;
  T Lm=L*m;
  T Ln=L*n;
  T Mm=M*m;
  T Mn=M*n;
  T Nn=N*n;

  d-=1.;

  matr.a11=Ll+d; matr.a12=Lm-N; matr.a13=Ln+M;
  matr.a21=Lm+N; matr.a22=Mm+d; matr.a23=Mn-L;
  matr.a31=Ln-M; matr.a32=Mn+L; matr.a33=Nn+d;
}
//---------------------------------------------------------------------------

#графика, #математика, #матрицы

24 марта 2011 (Обновление: 16 янв 2012)