xform.h
来自「RBF平台」· C头文件 代码 · 共 304 行
H
304 行
#ifndef XFORM_H#define XFORM_H/*Szymon RusinkiewiczPrinceton UniversityXForm.hAffine transforms (represented internally as column-major 4x4 matrices)Supports the following operations: xform xf1, xf2; // Initialized to the identity XForm<float> xf3; // xform is XForm<double> xf1=xform::trans(u,v,w);// An xform that translates. xf1=xform::rot(ang,ax); // An xform that rotates. xf1=xform::scale(s); // An xform that scales. glMultMatrixd(xf1); // Conversion to column-major array xf1.read("file.xf"); // Read xform from file xf1.write("file.xf"); // Write xform to file xf1 * xf2 // Matrix-matrix multiplication xf1 * inv(xf2) // Inverse xf1 * vec(1,2,3) // Matrix-vector multiplication rot_only(xf1) // An xform that does the rotation of xf1 trans_only(xf1) // An xform that does the translation of xf1 norm_xf(xf1) // Normal xform: inverse transpose, no trans invert(xf1); // Inverts xform in place orthogonalize(xf1); // Makes matrix orthogonal*/#include "lineqn.h"#include <cmath>#include <algorithm>#include <iostream>#include <fstream>using std::min;using std::max;using std::swap;using std::sqrt;template <class T>class XForm {private: T m[16]; // Column-major (OpenGL) orderpublic: // Constructors: defaults to identity XForm(const T m0 =1, const T m1 =0, const T m2 =0, const T m3 =0, const T m4 =0, const T m5 =1, const T m6 =0, const T m7 =0, const T m8 =0, const T m9 =0, const T m10=1, const T m11=0, const T m12=0, const T m13=0, const T m14=0, const T m15=1) { m[0] = m0; m[1] = m1; m[2] = m2; m[3] = m3; m[4] = m4; m[5] = m5; m[6] = m6; m[7] = m7; m[8] = m8; m[9] = m9; m[10] = m10; m[11] = m11; m[12] = m12; m[13] = m13; m[14] = m14; m[15] = m15; } template <class S> explicit XForm(const S &x) { for (int i = 0; i < 16; i++) m[i] = x[i]; } // Default destructor, copy constructor, assignment operator // Array reference and conversion to array - no bounds checking const T operator [] (int i) const { return m[i]; } T &operator [] (int i) { return m[i]; } operator const T *() const { return m; } operator const T *() { return m; } operator T *() { return m; } // Static members - really just fancy constructors static XForm<T> identity() { return XForm<T>(); } static XForm<T> trans(const T &tx, const T &ty, const T &tz) { return XForm<T>(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1); } template <class S> static XForm<T> trans(const S &t) { return XForm<T>::trans(t[0], t[1], t[2]); } static XForm<T> rot(const T &angle, const T &rx, const T &ry, const T &rz) { // Angle in radians, unlike OpenGL T l = sqrt(rx*rx+ry*ry+rz*rz); if (l == T(0)) return XForm<T>(); T l1 = T(1)/l, x = rx*l1, y = ry*l1, z = rz*l1; T s = sin(angle), c = cos(angle); T xs = x*s, ys = y*s, zs = z*s, c1 = T(1)-c; T xx = c1*x*x, yy = c1*y*y, zz = c1*z*z; T xy = c1*x*y, xz = c1*x*z, yz = c1*y*z; return XForm<T>(xx+c, xy+zs, xz-ys, 0, xy-zs, yy+c, yz+xs, 0, xz+ys, yz-xs, zz+c, 0, 0, 0, 0, 1); } template <class S> static XForm<T> rot(const T &angle, const S &axis) { return XForm<T>::rot(angle, axis[0], axis[1], axis[2]); } static XForm<T> scale(const T &s) { return XForm<T>(s,0,0,0,0,s,0,0,0,0,s,0,0,0,0,1); } static XForm<T> scale(const T &sx, const T &sy, const T &sz) { return XForm<T>(sx,0,0,0,0,sy,0,0,0,0,sz,0,0,0,0,1); } static XForm<T> scale(const T &s, const T &dx, const T &dy, const T &dz) { T dlen2 = dx*dx + dy*dy + dz*dz; T s1 = (s - T(1)) / dlen2; return XForm<T>(T(1) + s1*dx*dx, s1*dx*dy, s1*dx*dz, 0, s1*dx*dy, T(1) + s1*dy*dy, s1*dy*dz, 0, s1*dx*dz, s1*dy*dz, T(1) + s1*dz*dz, 0, 0, 0, 0, 1); } template <class S> static XForm<T> scale(const T &s, const S &dir) { return XForm<T>::scale(s, dir[0], dir[1], dir[2]); } // Read an XForm from a file. bool read(const char *filename) { std::ifstream f(filename); XForm<T> M; f >> M; f.close(); if (f.good()) { *this = M; return true; } return false; } // Write an XForm to a file bool write(const char *filename) const { std::ofstream f(filename); f << *this; f.close(); return f.good(); }};typedef XForm<double> xform;// Matrix multiplicationtemplate <class T>static inline XForm<T> operator * (const XForm<T> &xf1, const XForm<T> &xf2){ return XForm<T>( xf1[ 0]*xf2[ 0]+xf1[ 4]*xf2[ 1]+xf1[ 8]*xf2[ 2]+xf1[12]*xf2[ 3], xf1[ 1]*xf2[ 0]+xf1[ 5]*xf2[ 1]+xf1[ 9]*xf2[ 2]+xf1[13]*xf2[ 3], xf1[ 2]*xf2[ 0]+xf1[ 6]*xf2[ 1]+xf1[10]*xf2[ 2]+xf1[14]*xf2[ 3], xf1[ 3]*xf2[ 0]+xf1[ 7]*xf2[ 1]+xf1[11]*xf2[ 2]+xf1[15]*xf2[ 3], xf1[ 0]*xf2[ 4]+xf1[ 4]*xf2[ 5]+xf1[ 8]*xf2[ 6]+xf1[12]*xf2[ 7], xf1[ 1]*xf2[ 4]+xf1[ 5]*xf2[ 5]+xf1[ 9]*xf2[ 6]+xf1[13]*xf2[ 7], xf1[ 2]*xf2[ 4]+xf1[ 6]*xf2[ 5]+xf1[10]*xf2[ 6]+xf1[14]*xf2[ 7], xf1[ 3]*xf2[ 4]+xf1[ 7]*xf2[ 5]+xf1[11]*xf2[ 6]+xf1[15]*xf2[ 7], xf1[ 0]*xf2[ 8]+xf1[ 4]*xf2[ 9]+xf1[ 8]*xf2[10]+xf1[12]*xf2[11], xf1[ 1]*xf2[ 8]+xf1[ 5]*xf2[ 9]+xf1[ 9]*xf2[10]+xf1[13]*xf2[11], xf1[ 2]*xf2[ 8]+xf1[ 6]*xf2[ 9]+xf1[10]*xf2[10]+xf1[14]*xf2[11], xf1[ 3]*xf2[ 8]+xf1[ 7]*xf2[ 9]+xf1[11]*xf2[10]+xf1[15]*xf2[11], xf1[ 0]*xf2[12]+xf1[ 4]*xf2[13]+xf1[ 8]*xf2[14]+xf1[12]*xf2[15], xf1[ 1]*xf2[12]+xf1[ 5]*xf2[13]+xf1[ 9]*xf2[14]+xf1[13]*xf2[15], xf1[ 2]*xf2[12]+xf1[ 6]*xf2[13]+xf1[10]*xf2[14]+xf1[14]*xf2[15], xf1[ 3]*xf2[12]+xf1[ 7]*xf2[13]+xf1[11]*xf2[14]+xf1[15]*xf2[15] );}// Component-wise equality and inequality (#include the usual caveats// about comparing floats for equality...)template <class T>static inline bool operator == (const XForm<T> &xf1, const XForm<T> &xf2){ for (int i = 0; i < 16; i++) if (xf1[i] != xf2[i]) return false; return true;}template <class T>static inline bool operator != (const XForm<T> &xf1, const XForm<T> &xf2){ for (int i = 0; i < 16; i++) if (xf1[i] != xf2[i]) return true; return false;}// Inversetemplate <class T>static inline XForm<T> inv(const XForm<T> &xf){ T A[4][4] = { { xf[0], xf[4], xf[8], xf[12] }, { xf[1], xf[5], xf[9], xf[13] }, { xf[2], xf[6], xf[10], xf[14] }, { xf[3], xf[7], xf[11], xf[15] } }; int ind[4]; ludcmp(A, ind); T B[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; for (int i = 0; i < 4; i++) lubksb(A, ind, B[i]); return XForm<T>(B[0][0], B[0][1], B[0][2], B[0][3], B[1][0], B[1][1], B[1][2], B[1][3], B[2][0], B[2][1], B[2][2], B[2][3], B[3][0], B[3][1], B[3][2], B[3][3]);}template <class T>static inline void invert(XForm<T> &xf){ xf = inv(xf);}template <class T>static inline XForm<T> rot_only(const XForm<T> &xf){ return XForm<T>(xf[0], xf[1], xf[2], 0, xf[4], xf[5], xf[6], 0, xf[8], xf[9], xf[10], 0, 0, 0, 0, 1);}template <class T>static inline XForm<T> trans_only(const XForm<T> &xf){ return XForm<T>(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, xf[12], xf[13], xf[14], 1);}template <class T>static inline XForm<T> norm_xf(const XForm<T> &xf){ XForm<T> M = inv(xf); M[12] = M[13] = M[14] = T(0); swap(M[1], M[4]); swap(M[2], M[8]); swap(M[6], M[9]); return M;}template <class T>static inline void orthogonalize(XForm<T> &xf){ if (xf[15] == T(0)) // Yuck. Doesn't make sense... xf[15] = T(1); T q0 = xf[0] + xf[5] + xf[10] + xf[15]; T q1 = xf[6] - xf[9]; T q2 = xf[8] - xf[2]; T q3 = xf[1] - xf[4]; T l = sqrt(q0*q0+q1*q1+q2*q2+q3*q3); XForm<T> M = XForm<T>::rot(T(2)*acos(q0/l), q1, q2, q3); M[12] = xf[12]/xf[15]; M[13] = xf[13]/xf[15]; M[14] = xf[14]/xf[15]; xf = M;}// Matrix-vector multiplicationtemplate <class S, class T>static inline const S operator * (const XForm<T> &xf, const S &v){ // Assumes bottom row of xf is [0,0,0,1] return S(xf[0]*v[0] + xf[4]*v[1] + xf[8]*v[2] + xf[12], xf[1]*v[0] + xf[5]*v[1] + xf[9]*v[2] + xf[13], xf[2]*v[0] + xf[6]*v[1] + xf[10]*v[2] + xf[14]);}// iostream operatorstemplate <class T>static inline std::ostream &operator << (std::ostream &os, const XForm<T> &m){ for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { os << m[i+4*j]; if (j == 3) os << std::endl; else os << " "; } } return os;}template <class T>static inline std::istream &operator >> (std::istream &is, XForm<T> &m){ for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) is >> m[i+4*j]; if (!is.good()) m = xform::identity(); return is;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?