マルチスクリーンアプリケーション

[ Last updated : 2011-03-24 ]

MPI を利用して OpenGL で作成した 3D CG アプリケーションを複数の PC で分 割表示させた際の覚え書きです。 この仕組みを利用して、立体視装置やマルチスクリーンでの星空回転アプリケー ションなどを作成しました。

int myid, numprocs;

int main(int argc, char** argv)

{

    int namelen;

    char processor_name[MPI_MAX_PROCESSOR_NAME];

    char winname[256];

    

    MPI_Init(&argc, &argv);

    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    MPI_Comm_rank(MPI_COMM_WORLD, &myid);

    MPI_Get_processor_name(processor_name, &namelen);

    sprintf(winname,"%s [%d of %d on %s]\n", argv[0], myid, numprocs, processor_name);

 

    glutInit(&argc, argv);

    ...

    MPI_Finalize();

    return 0;

}

Δ θ = 360/(全プロセス数)

θi = i ⋅ Δ θ

int myid, numprocs;

void reshape(int w, int h) /* Window サイズ変更に伴う書き直しと、その際の描画設定 */

{

     GLdouble ratio, fovy;

     double theta, edist;

     GLdouble eye[]={0.0, 0.0, 0.0}, cent[]={0.0, 0.0, 0.0};

     fovy = 360.0 / (double) numprocs;       /* 横方向の視野角 */

     theta = 2.0 * M_PI * (double) myid/(double) numprocs; /* 視線の角度 */

     edist = (PERS_FAR - PERS_NEAR) * 0.5;    /* 視線方向の点への距離 */

     cent[0] = edist * cos(theta);            /* 視線方向の点の座標 */

     cent[2] = edist * sin(theta);

     ratio = (GLdouble)w/(GLdouble)h;         /* 画面の縦横比         */

     fovy = ytheta0 /ratio;                  /* y 方向の視野角の設定 */

     if (fovy > 180.0) fovy = 180.0;

     glViewport(0, 0, (GLsizei) w, (GLsizei) h);

     glMatrixMode(GL_PROJECTION);

     glLoadIdentity();

     gluPerspective(fovy, ratio, PERS_NEAR, PERS_FAR); /* 射影変換の設定 */

     glMatrixMode(GL_MODELVIEW);

     glLoadIdentity();

     gluLookAt(eye[0], eye[1], eye[2], cent[0], cent[1], cent[2], 0.0, 1.0, 0.0);

                                  /* 視点と視線方向の点の設定 (y 軸を上方)*/

}

MPI による同期

void mpiDisplay(void)

{

    if(myid == MASTER)

    {

        /* 新しい座票 x[3] の計算 */

    }

    MPI_Bcast(&x, 3, MPI_DOUBLE, 0, MPI_COMM_WORLD);  /* MASTER -> others */

    MPI_Barrier(MPI_COMM_WORLD);                      /* マシン間で同期 */

    glutPostRedisplay();                              /* 画面描画 */

}

プログラム全体は次のようになる

#include "mpi.h"

#include <stdio.h>

#include <math.h>

#include <GL/gl.h>

#include <GL/glu.h>

#include <GL/glut.h>

#define MASTER   0

...

int myid, numprocs;

...

void display(void){ /* 画面の描画 */ }

void mpiDisplay(void){ /* 新しい座標の計算、データの送受信、マシン間の同期 */ }

void init(void){ /* 描画の初期設定 (質感、ライト等) */ }

void reshape(int w, int h){ /* 視点、視野角の設定 */ }

void mouse(int button, int state, int x, int y){ /* マウスイベント処理 */ }

int main(int argc, char** argv)

{

    /* MPI 初期化 */

    ...

    /* glut 初期化 */

    ...

    init ();

    glutDisplayFunc(display);

    glutReshapeFunc(reshape);

    if(myid == MASTER) glutMouseFunc(mouse);      /* マウスは MASTER のみ使用 */

    glutIdleFunc(mpiDisplay); 

    glutMainLoop();

    MPI_Finalize();

    return 0;

}

サンプルプログラム

$ mpiexec -n 5 -f mpd.hosts ./MPI-planet