opengl学習
[,left]
改行で区切られた3次元座標のテキストファイルを受け取り、それぞれの点に球を描いて、さらにそれぞれを線で繋ぐプログラム。
カメラの位置と視点はキーボードからの入力で移動させられる。
いずれは球同士を円柱で繋ぎたい。
// spheres.cpp /* * [フォーマット] * x座標 y座標 z座標 * (以下繰り返し) */ #include<iostream> #include<vector> #include<GL/glut.h> using namespace std; float cx, cy, cz; // カメラの位置 float sx, sy, sz; // 視点の位置 char *inFileName; typedef struct point_t { point_t(float a, float b, float c): x(a), y(b), z(c){} float x, y, z; } pt; vector<pt> pts; double perspective() { return (double)glutGet(GLUT_WINDOW_WIDTH) / glutGet(GLUT_WINDOW_HEIGHT); } void sphere(pt p) { glPushMatrix(); { glTranslatef(p.x, p.y, p.z); float red[] = {1, 0, 0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, red); glutSolidSphere(1.5, 20, 20); } glPopMatrix(); } void line(pt p, pt q) { glBegin(GL_LINES); glVertex3f(p.x, p.y, p.z); glVertex3f(q.x, q.y, q.z); glEnd(); } void display() { // カメラの設定 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, perspective(), 1, 1000); gluLookAt(cx, cy, cz, sx, sy, sz, 0, 1, 0); // 描画 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1, 0, 0); glLineWidth(2); for (int i = 0; i < pts.size(); i++){ sphere(pts[i]); for (int j = i+1; j < pts.size(); j++) line(pts[i], pts[j]); } glutSwapBuffers(); } void reshape(int width, int height) { glViewport(0, 0, width, height); } void keyboard(unsigned char k, int x, int y) { if (k == 'q') exit(0); #define match(keyCode) else if (k == keyCode) match('u') cx += 1; match('j') cx -= 1; match('i') cy += 1; match('k') cy -= 1; match('o') cz += 1; match('l') cz -= 1; match('p') sx += 1; match(';') sx -= 1; match('@') sy += 1; match(':') sy -= 1; match('[') sz += 1; match(']') sz -= 1; #define F "%.1f" match('p') printf(F F F F F F "\n", cx, cy, cz, sx, sy, sz); glutPostRedisplay(); } void loadPoints() { FILE *inFile = fopen(inFileName, "r"); char inBuf[256]; float x, y, z; if (!inFile){ perror(inFileName); exit(0); } while (fgets(inBuf, 256, inFile)){ sscanf(inBuf, "%f %f %f", &x, &y, &z); printf("read %f %f %f\n", x, y, z); // DEBUG pt p(x, y, z); pts.push_back(p); } } void init() { cx = cy = cz = sx = sy = sz = 0; loadPoints(); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); // 照明 float pos0[] = {100, 200, 250, 0}; glLightfv(GL_LIGHT0, GL_POSITION, pos0); glClearColor(1, 1, 1, 0); } int main(int argc, char** argv) { if (argc < 2){ fprintf(stderr, "usage: %s file\n", argv[0]); exit(0); } inFileName = argv[1]; // glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("shperes"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); init(); glutMainLoop(); return 0; }
上の画像での入力ファイルは以下。
+0 +0 +0 -10 -10 -10 -10 -10 +10 -10 +10 -10 -10 +10 +10 +10 -10 -10 +10 -10 +10 +10 +10 -10 +10 +10 +10