スポンサーリンク

glOrthoを自前実装する

glOrthoが作成する行列

C/C++の配列にした場合

C++で実装

ソースコード

#include <cmath>

namespace nu {

  typedef float real_t;

  //! @brief 平行投影行列を作成する
  //! @param [out] m 作成した行列を格納する要素数16の配列
  //! @return なし
  inline void myortho(
    real_t* m,
    real_t left,
    real_t right,
    real_t bottom,
    real_t top,
    real_t znear,
    real_t zfar) {

    real_t tx = -(right + left) / (right - left);
    real_t ty = -(top + bottom) / (top - bottom);
    real_t tz = -(zfar + znear) / (zfar - znear);

    //infが出たときは単位行列を返す模様
    if (std::isinf(tx) || std::isinf(ty) || std::isinf(tz)) {
      m[0] = m[5] = m[10] = m[15] = (real_t)1.0;

      m[1] = m[2] = m[3] =
      m[4] = m[6] = m[7] =
      m[8] = m[9] = m[11] = (real_t)0.0;

      m[12] = m[13] = m[14] = (real_t)0.0;

      return;
    }



    m[0] = (real_t)2.0 / (right - left);
    m[1] = 0.0;
    m[2] = 0.0;
    m[3] = 0.0;

    m[4] = 0.0;
    m[5] = (real_t)2.0 / (top - bottom);
    m[6] = 0.0;
    m[7] = 0.0;

    m[8] = 0.0;
    m[9] = 0.0;
    m[10] = (real_t)-2.0/(zfar-znear);
    m[11] = 0.0;

    m[12] = tx;
    m[13] = ty;
    m[14] = tz;
    m[15] = 1.0;

  }

}

テスト用コード

//検証用
#include <cassert>

//自前実装版glortho
#include "myortho.h"

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"freeglut.lib")

void display(void)
{
  
  GLfloat glomat[16]; //glu関数で生成
  GLfloat myomat[16]; //自分関数で生成

  //glOrtho,myorthoへの入力の値を色々変える
  static int i = 0;
  static float j = 0.0f;

  GLdouble left=-10+i;
  GLdouble right=+23 + i*1.5;
  GLdouble bottom=-10 - i / 2.0;
  GLdouble top=10 - i;
  GLdouble znear=5+j;
  GLdouble zfar=30+j*2;

  i++;
  j += 0.01;


  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  //openglで計算
  glOrtho(left, right, bottom, top, znear, zfar);
  glGetFloatv(GL_PROJECTION_MATRIX, glomat);

  //自前計算
  nu::myortho(myomat,left, right, bottom, top, znear, zfar);

  puts("----------------------------------------------");
  printf("** %d \n", i);
  for (int k = 0; k < 16; k++) {
    //比較
    printf("m[%2d] %+5.10lf %+5.10lf \n", k,glomat[k], myomat[k]);

    //自前計算とglOrtho計算の値があまりにかけ離れていたらassertで落ちる
    assert(abs(glomat[k] - myomat[k]) < 0.00001);

  }
  puts("----------------------------------------------");

}
void mouse(int button, int state, int x, int y) {
  display();
}

int main(int argc, char* argv[])
{

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutInitWindowPosition(0, 0);
  glutInitWindowSize(100,100);
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutMainLoop();

  return 0;

}

テスト結果

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: