OpenGLをC++11でラップしてみんとてするなり 第6.5回
そういえば、gl::Matrixクラスの各種操作がMatrix<4, 4, float>にしか対応していなかったので、Matrix<4, 4, double>にも対応するようにしましょう。
まずは、行列操作関数をまとめた次のようなクラスを作り、必要な型(floatとdouble)に対して特殊化をします。それ以外の型に対してはメンバ変数の定義をしていないため、コンパイル時エラーが発生します。
template <class T> struct MatrixFunctions {} ; template <> struct MatrixFunctions<GLfloat> { inline static void set(const ::Matrix<4, 4, GLfloat> &mat) { glLoadMatrixf((const GLfloat*)mat) ; } inline static void get(GLenum pname, ::Matrix<4, 4, GLfloat> &mat) { glGetFloatv(pname, (GLfloat*)mat) ; } inline static void mult(const ::Matrix<4, 4, GLfloat> &mat) { glMultMatrixf((const GLfloat*)mat) ; } } ; template <> struct MatrixFunctions<GLdouble> { inline static void set(const ::Matrix<4, 4, GLdouble> &mat) { glLoadMatrixd((const GLdouble*)mat) ; } inline static void get(GLenum pname, ::Matrix<4, 4, GLdouble> &mat) { glGetDoublev(pname, (GLdouble*)mat) ; } inline static void mult(const ::Matrix<4, 4, GLdouble> &mat) { glMultMatrixd((const GLdouble*)mat) ; } } ;
これに伴い、gl::Matrixクラスのメンバ関数は次のようにテンプレート形式に変更されます。
gl/Matrix.h
/** * 行列値を設定する。 * * @param enabled 新しい行列値。 * @return オブジェクト自身。 */ template <class T> Matrix &operator = (const ::Matrix<4, 4, T> &mat) { // matrix modeを変更 GLint mode ; glGetIntegerv(GL_MATRIX_MODE, &mode) ; if (mode != SetterConst) glMatrixMode(SetterConst) ; // 行列値の設定 MatrixFunctions<T>::set(mat) ; // matrix modeを元に戻す if (mode != SetterConst) glMatrixMode(mode) ; return *this ; } /** * 行列値を取得。 * * @return 現在の行列値。 */ template <class T> operator ::Matrix<4, 4, T>() const { ::Matrix<4, 4, T> mat ; MatrixFunctions<T>::get(GetterConst, mat) ; return mat ; } /** * 行列を乗算する。 */ template <class T> Matrix &operator *= (const ::Matrix<4, 4, T> &mat) { // matrix modeを変更 GLint mode ; glGetIntegerv(GL_MATRIX_MODE, &mode) ; if (mode != SetterConst) glMatrixMode(SetterConst) ; // 乗算 MatrixFunctions<T>::mult(mat) ; // matrix modeを元に戻す if (mode != SetterConst) glMatrixMode(mode) ; return *this ; }