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