[ create a new paste ] login | about

Link: http://codepad.org/fsNYCEoO    [ raw code | output | fork ]

C++, pasted on May 23:
/*
 * r            位置リセット
 * m            射影切り替え
 * w, a:        平行移動 Y
 * s, d:        平行移動 X
 * q, e:        平行移動 Z
 * j, J:        回転 X
 * k, K:        回転 Y
 */

#include <iostream>
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>

const double PI = 3.14159265;

/* 視点の位置 */
const double eye_pos[3] = {0.0, 0.0, 1.9};

//変換行列
double transformation_mat[4][4]={
  {1.0, 0.0, 0.0, 0.0},
  {0.0, 1.0, 0.0, 0.0},
  {0.0, 0.0, 1.0, 0.0},
  {0.0, 0.0, 0.0, 1.0}
};

// 変形させる対象
const int object_nv = 4; // 頂点数
const double object_vertices[][object_nv][3] = { // 頂点の座標
  { {+0.5, -0.5, +0.5},       // +X
    {+0.5, -0.5, -0.5},
    {+0.5, +0.5, -0.5},
    {+0.5, +0.5, +0.5}, },
  { {-0.5, -0.5, +0.5},       // -X
    {-0.5, +0.5, +0.5},
    {-0.5, +0.5, -0.5},
    {-0.5, -0.5, -0.5}, },
  { {+0.5, +0.5, +0.5},       // +Y
    {+0.5, +0.5, -0.5},
    {-0.5, +0.5, -0.5},
    {-0.5, +0.5, +0.5}, },
  { {+0.5, -0.5, +0.5},       // -Y
    {-0.5, -0.5, +0.5},
    {-0.5, -0.5, -0.5},
    {+0.5, -0.5, -0.5}, },
  { {-0.5, -0.5, +0.5},       // +Z
    {+0.5, -0.5, +0.5},
    {+0.5, +0.5, +0.5},
    {-0.5, +0.5, +0.5}, },
  { {-0.5, -0.5, -0.5},       // -Z
    {-0.5, +0.5, -0.5},
    {+0.5, +0.5, -0.5},
    {+0.5, -0.5, -0.5}, },
};

// 面数
const int object_nf = sizeof(object_vertices)/sizeof(object_vertices[1]);

/* 色 */
double object_color[object_nf][3] = {
  {  1.0,  0.0,  0.0},
  {  0.0,  1.0,  0.0},
  {  0.0,  0.0,  1.0},
  {  0.0,  1.0,  1.0},
  {  1.0,  0.0,  1.0},
  {  1.0,  1.0,  0.0},
};

/* 面情報構造体 */
typedef struct Face_ {
  double depth;
  int index;
} Face;

// 面情報
Face faces[object_nf];

// 射影
int projection_mode = 0;

/* 頂点コピー */
void copy_object(double dest[][object_nv][3], const double src[][object_nv][3], int nf) {
  for (int i = 0; i < nf; i++) {
    for (int j = 0; j < object_nv; j++) {
      for (int k = 0; k < 3; k++) {
        dest[i][j][k] = src[i][j][k];
      }
    }
  }
}

//引数を強制的に単位行列にする
void setIdentity44(double mat[4][4]){
  for(int i = 0; i < 4; i++){
    for(int j = 0; j < 4; j++){
      if(i == j) mat[i][j] = 1.0;
      else mat[i][j] = 0.0;
    }
  }
}

void copy44(double out_mat[4][4], const double in_mat[4][4]){
  for(int i = 0; i < 4; i++){
    for(int j = 0; j < 4; j++){
      out_mat[i][j] = in_mat[i][j];
    }
  }
}

//4*4行列の掛け算。out_matとin_mat1,in_mat2は同じでも大丈夫
void multiply44by44(double out_mat[4][4], const double in_mat1[4][4], const double in_mat2[4][4]){
  double temp_mat1[4][4];
  copy44(temp_mat1, in_mat1);
  double temp_mat2[4][4];
  copy44(temp_mat2, in_mat2);
  for(int i=0; i<4; i++){
    for(int j=0; j<4; j++){
      out_mat[i][j] = temp_mat1[i][0] * temp_mat2[0][j] +
                      temp_mat1[i][1] * temp_mat2[1][j] +
                      temp_mat1[i][2] * temp_mat2[2][j] +
                      temp_mat1[i][3] * temp_mat2[3][j];
    }
  }
}

//平行移動行列の生成。mat:結果、tx:x方向の移動量、ty:y方向の移動量
void makeTranslationMatrix(double mat[4][4], const double tx, const double ty, const double tz){
  mat[0][0] = 1.0; mat[0][1] = 0.0; mat[0][2] = 0.0; mat[0][3] = tx;
  mat[1][0] = 0.0; mat[1][1] = 1.0; mat[1][2] = 0.0; mat[1][3] = ty;
  mat[2][0] = 0.0; mat[2][1] = 0.0; mat[2][2] = 1.0; mat[2][3] = tz;
  mat[3][0] = 0.0; mat[3][1] = 0.0; mat[3][2] = 0.0; mat[3][3] = 1.0;
}

void setTranslation(const double tx, const double ty, const double tz){
  double translation_mat[4][4];
  makeTranslationMatrix(translation_mat, tx, ty, tz);
  multiply44by44(transformation_mat, translation_mat, transformation_mat);
}

//X軸周りの回転行列の生成。mat:結果、r:回転角
void makeRotationXMatrix(double mat[4][4], const double r){
  mat[0][0] = 1; mat[0][1] = 0;      mat[0][2] = 0;          mat[0][3] = 0;
  mat[1][0] = 0; mat[1][1] = cos(r); mat[1][2] = -sin(r);    mat[1][3] = 0;
  mat[2][0] = 0; mat[2][1] = sin(r); mat[2][2] = cos(r);     mat[2][3] = 0;
  mat[3][0] = 0; mat[3][1] = 0;      mat[3][2] = 0;          mat[3][3] = 1;
}
void setRotationX(const double r){
  double rotation_mat[4][4];
  makeRotationXMatrix(rotation_mat, r);
  multiply44by44(transformation_mat, rotation_mat, transformation_mat);
}

//Y軸周りの回転行列の生成。mat:結果、r:回転角
void makeRotationYMatrix(double mat[4][4], const double r){
  mat[0][0] = cos(r);  mat[0][1] = 0;  mat[0][2] = sin(r);     mat[0][3] = 0;
  mat[1][0] = 0;       mat[1][1] = 1;  mat[1][2] = 0;          mat[1][3] = 0;
  mat[2][0] = -sin(r); mat[2][1] = 0;  mat[2][2] = cos(r);     mat[2][3] = 0;
  mat[3][0] = 0;       mat[3][1] = 0;  mat[3][2] = 0;          mat[3][3] = 1;
}
void setRotationY(const double r){
  double rotation_mat[4][4];
  makeRotationYMatrix(rotation_mat, r);
  multiply44by44(transformation_mat, rotation_mat, transformation_mat);
}

//4*4行列Aと4(実際は3)*1行列vの掛け算Avの計算。vertex:v(破壊されて結果が入る)、mat:A
void transform(double vertex[],  double mat[4][4]){
  double temp_x = vertex[0];
  double temp_y = vertex[1];
  double temp_z = vertex[2];
  for(int i=0; i<3; i++){
    vertex[i] = temp_x * mat[i][0] + temp_y * mat[i][1] +
                temp_z * mat[i][2] + 1.0    * mat[i][3];
  }
}

/* 重心深度算出 ※ 結果は比較に使用するだけなのでsqrtしない */
double face_depth(const double eye[3], const double vertices[][3]) {
  double c[3] = {0.0, 0.0, 0.0}; /* 重心 */
  double d = 0.0;
  for (int i = 0; i < object_nv; i++) {
    for (int j = 0; j < 3; j++) {
      c[j] += vertices[i][j];
    }
  }
  for (int j = 0; j < 3; j++) {
    c[j] /= object_nv;
    double t = eye[j] - c[j];
    d += t * t;
  }
  return d; /* return sqrt(d); としないでよい */
}

/* 面の重心深度比較 */
int compare_faces_depth(const void *lhs, const void *rhs) {
  Face *l = (Face*)(lhs), *r = (Face*)(rhs);
  return l->depth > r->depth ? -1 : (l->depth < r->depth ? 1 : 0);
}

/* 面表示 */
void display_faces(Face faces[], double vertices[][object_nv][3], double color[][3],
                   int nf) {
  glBegin(object_nv == 4 ? GL_QUADS : object_nv == 3 ? GL_TRIANGLES : GL_LINE_STRIP); {
    double s = 1.0;
    for(int i = 0; i < nf; i++) {
      int idx = faces[i].index;
      glColor3f(color[idx][0], color[idx][1], color[idx][2]);
      for(int j = 0; j < object_nv; j++) {
        double t = projection_mode == 0 ?
                   s / (eye_pos[2] - vertices[idx][j][2]) : 1.0;
        glVertex2d(t * vertices[idx][j][0], t * vertices[idx][j][1]);
      }
    }
  } glEnd();
}

/* 物体描画 */
void display_object(double vertices[][object_nv][3], double color[][3], int nf){
  // 座標変換
  for(int i = 0; i < nf; i++) {
    for(int j = 0; j < object_nv; j++) {
      transform(vertices[i][j], transformation_mat);
    }
  }

  /* 面 */
  for(int i = 0; i < nf; i++) {
    faces[i].depth = face_depth(eye_pos, vertices[i]);
    faces[i].index = i;
  }
  qsort(&faces, nf, sizeof(Face), compare_faces_depth); /* 深度ソート */

  // 表示
  display_faces(faces, vertices, color, nf);
}

/* 描画 */
void display(void){
  glClear(GL_COLOR_BUFFER_BIT);

  //座標軸の表示
  glBegin(GL_LINES); {
    glColor3f(1.0, 1.0, 1.0);
    glVertex2d(-1.0, 0.0);
    glVertex2d(1.0, 0.0);
    glVertex2d(0.0, -1.0);
    glVertex2d(0.0, 1.0);
  } glEnd();

  /* 物体描画 */
  double vertices[object_nf][object_nv][3];
  copy_object(vertices, object_vertices, object_nf);
  display_object(vertices, object_color, object_nf);

  glFlush();
}

/* インプット */
void key(unsigned char key, int x, int y) {
  switch (key) {
    case 'r':   setIdentity44(transformation_mat);              break;
    case 'm':   projection_mode ^= 1;                           break;
    case 'w':   setTranslation( 0.0, +0.1,  0.0);               break;
    case 'a':   setTranslation(-0.1,  0.0,  0.0);               break;
    case 's':   setTranslation( 0.0, -0.1,  0.0);               break;
    case 'd':   setTranslation(+0.1,  0.0,  0.0);               break;
    case 'q':   setTranslation( 0.0,  0.0, -0.1);               break;
    case 'e':   setTranslation( 0.0,  0.0, +0.1);               break;
    case 'j':   setRotationX( M_PI/8);                          break;
    case 'J':   setRotationX(-M_PI/8);                          break;
    case 'k':   setRotationY( M_PI/8);                          break;
    case 'K':   setRotationY(-M_PI/8);                          break;
    default:                                                    break;
  }
  glutPostRedisplay();
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glutDisplayFunc(display);
  glutKeyboardFunc(key);
  glutMainLoop();
  return 0;
}


Output:
1
2
3
4
Line 20: error: GL/glut.h: No such file or directory
In function 'void display_faces(Face*, double (*)[4][3], double (*)[3], int)':
Line 206: error: 'GL_QUADS' was not declared in this scope
compilation terminated due to -Wfatal-errors.


Create a new paste based on this one


Comments: