codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
/* * 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; }
Private
[
?
]
Run code
Submit