読者です 読者をやめる 読者になる 読者になる

OpenGLをC++11でラップしてみんとてするなり 第6.5回

OpenGL C++

 そういえば、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 ;
    }