/* ex11-4.c --- アニメーション処理: 座標変換関数を利用する方法 * * cc ex11-4.c -g -O2 -Wall -o ex11-4 -I/usr/include/freetype2 -lftgl -lglfw -lGLU -lGL -lX11 -lXrandr -lm */ #include #include #include #include #include #define CROSSING_SIZE 100 /* 交差点数=100 */ #define MAX_NAME_SIZE 50 /* 最大文字数50文字(半角) */ /* 座標変換マクロの定義 */ double ORIGIN_X = 0.0; double ORIGIN_Y = 0.0; double REAL_SIZE_X = 8.0; double REAL_SIZE_Y = 8.0; #ifndef FONT_FILENAME /* 演習サーバに用意されているフォントのファイル名 */ #define FONT_FILENAME "/usr/share/fonts/truetype/fonts-japanese-gothic.ttf" #endif static FTGLfont *font; /* 読み込んだフォントを差すポインタ */ /* データ構造の定義 */ typedef struct { double x, y; /* 位置 x, y */ } Position; /* 位置を表す構造体 */ typedef struct { int id; /* 交差点番号 */ Position pos; /* 位置を表す構造体 */ double wait; /* 平均待ち時間 */ char jname[MAX_NAME_SIZE]; /* 交差点名(日本語) */ char ename[MAX_NAME_SIZE]; /* 交差点名(ローマ字) */ int points; /* 交差道路数 */ int next[5]; /* 隣接する交差点番号 */ } Crossing; /* データを格納する変数の定義 */ static Crossing cross[CROSSING_SIZE]; /* 円を描画 */ static void draw_circle(double x, double y, double r) { int const N = 12; /* 円周を 12分割して線分で描画することにする */ int i; glBegin(GL_LINE_LOOP); for (i = 0; i < N; i++) glVertex2d(x + cos(2 * M_PI * i / N) * r, y + sin(2 * M_PI * i / N) * r); glEnd(); } /* 文字列を描画 */ static void draw_outtextxy(double x, double y, char const *text) { double const scale = 0.01; glPushMatrix(); glTranslated(x, y, 0.0); glScaled(scale, scale, scale); ftglRenderFont(font, text, FTGL_RENDER_ALL); glPopMatrix(); } /* ファイルの読み込み */ static int map_read(char *filename) { FILE *fp; int i, j; int crossing_number; /* 交差点数 */ fp = fopen(filename, "r"); if (fp == NULL) { perror(filename); return -1; } /* はじめに交差点数を読み込む */ fscanf(fp, "%d", &crossing_number); for (i = 0; i < crossing_number; i++) { /* 関数fprintfを使って、構造体のデータを ファイルへ書き出すプログラムを記入しなさい */ fscanf(fp, "%d,%lf,%lf,%lf,%[^,],%[^,],%d", &(cross[i].id), &(cross[i].pos.x), &(cross[i].pos.y), &(cross[i].wait), cross[i].jname, cross[i].ename, &(cross[i].points)); for (j = 0; j < cross[i].points; j++) { fscanf(fp, ",%d", &(cross[i].next[j])); } } fclose(fp); /* ファイルから読み込んだ交差点数を返す */ return crossing_number; } /* 道路網の表示 (新しく作成する部分) */ static void map_show(int crossing_number) { int i, j; for (i = 0; i < crossing_number; i++) { /* 交差点毎のループ */ double x0 = cross[i].pos.x; double y0 = cross[i].pos.y; /* 交差点を表す円を描く */ glColor3d(1.0, 0.5, 0.5); draw_circle(x0, y0, 0.1); /* 交差点の名前を描く */ glColor3d(1.0, 1.0, 0.0); draw_outtextxy(x0, y0, cross[i].jname); /* 交差点から伸びる道路を描く */ glColor3d(1.0, 1.0, 1.0); glBegin(GL_LINES); for (j = 0; j < cross[i].points; j++) { double x1 = cross[ cross[i].next[j] ].pos.x; double y1 = cross[ cross[i].next[j] ].pos.y; glVertex2d(x0, y0); glVertex2d(x1, y1); } glEnd(); } } int main(void) { int crossing_number; /* 交差点数 */ double x_deg = 0.0; /* グラフィック環境を初期化して、ウィンドウを開く */ glfwInit(); glfwOpenWindow(640, 640, 0, 0, 0, 0, 0, 0, GLFW_WINDOW); /* 文字列描画のためのフォントの読み込みと設定 */ font = ftglCreateExtrudeFont(FONT_FILENAME); if (font == NULL) { perror(FONT_FILENAME); fprintf(stderr, "could not load font\n"); exit(1); } ftglSetFontFaceSize(font, 24, 24); ftglSetFontDepth(font, 0.01); ftglSetFontOutset(font, 0, 0.1); ftglSetFontCharMap(font, ft_encoding_unicode); /* マップファイルの読み込み */ crossing_number = map_read("map2.dat"); if (crossing_number < 0) { fprintf(stderr, "couldn't read map file\n"); exit(1); } while (1) { int width, height; /* (ORIGIN_X, ORIGIN_Y) を中心に、REAL_SIZE_X * REAL_SIZE_Y の範囲の 空間をビューポートに投影する */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(ORIGIN_X + REAL_SIZE_X * -0.5, ORIGIN_X + REAL_SIZE_X * 0.5, ORIGIN_Y + REAL_SIZE_Y * -0.5, ORIGIN_Y + REAL_SIZE_Y * 0.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(x_deg, 1.0, 0.0, 0.0); /* X軸まわりにx_deg回転 */ x_deg += 3.0; /* x_degを逐次増加 */ /* Esc が押されるかウィンドウが閉じられたらおしまい */ /* glfwWaitEvents(); */ if (glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)) break; glfwGetWindowSize(&width, &height); /* 現在のウィンドウサイズを取得する */ glViewport(0, 0, width, height); /* ウィンドウ全面をビューポートにする */ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); /* バックバッファを黒で塗り潰す */ map_show(crossing_number); /* 道路網の表示 */ glfwSwapBuffers(); /* フロントバッファとバックバッファを入れ替える */ /* 80ミリ秒くらい時間待ち */ usleep(80 * 1000); } glfwTerminate(); return 0; }