スポンサーリンク

glTranslatef,glScalefを自前実装する

この二つは行列が単純すぎて別記事にする気にならないのでまとめてやる。

glTranslatef

glTranslatefが作成する行列

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

glScalef

glScalefが作成する行列

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

ソースコード

ソースコード

namespace nu {

  typedef float real_t;

  inline real_t to_radian(real_t degree) {
    return degree * (real_t)3.14159265358979 / (real_t)180.0;
  }

  void mytranslate(
    real_t* m,
    real_t x,
    real_t y,
    real_t z
  ) {
    m[0] = 1.0;
    m[1] = 0.0;
    m[2] = 0.0;
    m[3] = 0.0;

    m[4] = 0.0;
    m[5] = 1.0;
    m[6] = 0.0;
    m[7] = 0.0;

    m[8] = 0.0;
    m[9] = 0.0;
    m[10] = 1.0;
    m[11] = 0.0;

    m[12] = x;
    m[13] = y;
    m[14] = z;
    m[15] = 1.0;

  }



  void myscale(
    real_t* m,
    real_t sx,
    real_t sy,
    real_t sz
  ) {
    m[0] = sx;
    m[1] = 0.0;
    m[2] = 0.0;
    m[3] = 0.0;

    m[4] = 0.0;
    m[5] = sy;
    m[6] = 0.0;
    m[7] = 0.0;

    m[8] = 0.0;
    m[9] = 0.0;
    m[10] = sz;
    m[11] = 0.0;

    m[12] = 0.0;
    m[13] = 0.0;
    m[14] = 0.0;
    m[15] = 1.0;

  }

}

テストコード( translate )

#include <windows.h>
#include <gl/GLU.h>
#include <gl/freeglut.h>
#include <cstdio>
#include <cmath>

//検証用
#include <cassert>

//自前実装版glTranslate* / glScale*
#include "mytranslatescale.h"

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

void display(void)
{
  
  GLfloat glmat[16]; //gl関数で生成
  GLfloat mymat[16]; //自分関数で生成

  //gltranslate,mytranslateへの入力の値を色々変える
  static int i = 0;
  i++;

  GLfloat x = 1.0+i;
  GLfloat y = 1.0 * (i * 0.1);
  GLfloat z = 1.0 * (i / 0.2);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  //openglで計算
  glTranslatef( x, y, z);
  glGetFloatv(GL_MODELVIEW_MATRIX, glmat);

  //自前計算
  nu::mytranslate(mymat,x,y,z);

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

    //自前計算とgltranslate計算の値があまりにかけ離れていたらassertで落ちる
    assert(std::abs(glmat[k] - mymat[k]) < 0.0001);

  }
  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;

}

テストコード( scale )

#include <windows.h>
#include <gl/GLU.h>
#include <gl/freeglut.h>
#include <cstdio>
#include <cmath>

//検証用
#include <cassert>

//自前実装版glTranslate* / glScale*
#include "mytranslatescale.h"

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

void display(void)
{
  
  GLfloat glmat[16]; //gl関数で生成
  GLfloat mymat[16]; //自分関数で生成

  //glscalef,myscaleへの入力の値を色々変える
  static int i = 0;
  i++;

  GLfloat x = 1.0+i;
  GLfloat y = 1.0 * (i * 0.1);
  GLfloat z = 1.0 * (i / 0.2);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  //openglで計算
  glScalef( x, y, z);
  glGetFloatv(GL_MODELVIEW_MATRIX, glmat);

  //自前計算
  nu::myscale(mymat,x,y,z);

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

    //自前計算とglScalef計算の値があまりにかけ離れていたらassertで落ちる
    assert(std::abs(glmat[k] - mymat[k]) < 0.0001);

  }
  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: