Modified lines:  5, 6, 150, 692, 696
Added line:  59, 60, 61, 62, 63, 107, 108, 652, 653, 654, 707, 708, 709, 710, 711, 712, 713, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759
Removed line:  None
Generated by diff2html.pl
© Yves Bailly, MandrakeSoft S.A. 2001, Ryohei Morita 2007
diff2html.pl is licensed under the GNU GPL.

  ../112-1/112-1-Memory.c     112-2-Replay.c
  777 lines
28582 bytes
Last modified : Mon Nov 21 05:34:46 2011

    820 lines
29999 bytes
Last modified : Mon Nov 21 17:55:25 2011

1 // Keisanki Joron 2 (Introduction to Computing II)   1 // Keisanki Joron 2 (Introduction to Computing II)
2 // Dept. of Engineering Systems, University of Tsukuba   2 // Dept. of Engineering Systems, University of Tsukuba
3 // [UTF-8 / Unix]   3 // [UTF-8 / Unix]
4   4
5 // 2011/11/21 kameda[at]iit.tsukuba.ac.jp   5 // 2011/11/21b kameda[at]iit.tsukuba.ac.jp
6 // 12.1 操作の記録   6 // 12.2 操作の再現
7   7
8 #include <stdio.h>   8 #include <stdio.h>
9 #include <stdlib.h> // exit(), calloc()   9 #include <stdlib.h> // exit(), calloc()
10 #include <math.h> // sqrt()   10 #include <math.h> // sqrt()
11 #include <GL/glut.h>   11 #include <GL/glut.h>
12   12
13 // ***********************************************************************    13 // *********************************************************************** 
14 // structures ************************************************************   14 // structures ************************************************************
15   15
16 // +----------------------------------------------------   16 // +----------------------------------------------------
17 // 1つの点のための構造体   17 // 1つの点のための構造体
18 // +----------------------------------------------------   18 // +----------------------------------------------------
19 struct ic2POINT {   19 struct ic2POINT {
20   float x;   20   float x;
21   float y;   21   float y;
22   float z;   22   float z;
23 };   23 };
24   24
25 // +----------------------------------------------------   25 // +----------------------------------------------------
26 // 1つの色のための構造体   26 // 1つの色のための構造体
27 // +----------------------------------------------------   27 // +----------------------------------------------------
28 struct ic2COLOR {   28 struct ic2COLOR {
29   float r;   29   float r;
30   float g;   30   float g;
31   float b;   31   float b;
32 };   32 };
33   33
34 // +----------------------------------------------------   34 // +----------------------------------------------------
35 // 1つの三角形パッチのための構造体   35 // 1つの三角形パッチのための構造体
36 // 次の三角形パッチへのポインタを持つ。   36 // 次の三角形パッチへのポインタを持つ。
37 // v(st) × v(su) [外積]がこの面の法線ベクトルを成す(右ネジ式)   37 // v(st) × v(su) [外積]がこの面の法線ベクトルを成す(右ネジ式)
38 // +----------------------------------------------------   38 // +----------------------------------------------------
39 struct ic2PATCH {   39 struct ic2PATCH {
40   struct ic2POINT s;     // 頂点s   40   struct ic2POINT s;     // 頂点s
41   struct ic2POINT t;     // 頂点t   41   struct ic2POINT t;     // 頂点t
42   struct ic2POINT u;     // 頂点u   42   struct ic2POINT u;     // 頂点u
43   struct ic2POINT n;     // 法線ベクトル(正規化された方向ベクトル)   43   struct ic2POINT n;     // 法線ベクトル(正規化された方向ベクトル)
44   struct ic2POINT b;     // パッチの重心   44   struct ic2POINT b;     // パッチの重心
45   float l; // 法線ベクトル表示時の長さ補正 (l * n)   45   float l; // 法線ベクトル表示時の長さ補正 (l * n)
46   struct ic2COLOR c;     // 色の強度 (通常は0.0 - 1.0)   46   struct ic2COLOR c;     // 色の強度 (通常は0.0 - 1.0)
47   struct ic2PATCH *next; // 次の三角形パッチへのポインタ   47   struct ic2PATCH *next; // 次の三角形パッチへのポインタ
48 };   48 };
49   49
50 // +----------------------------------------------------   50 // +----------------------------------------------------
51 // 1つのキー入力のための構造体   51 // 1つのキー入力のための構造体
52 // +----------------------------------------------------   52 // +----------------------------------------------------
53 struct ic2KEYINPUT {   53 struct ic2KEYINPUT {
54   unsigned char key;   54   unsigned char key;
55   struct ic2KEYINPUT *next;   55   struct ic2KEYINPUT *next;
56 };   56 };
57   57
58 // ***********************************************************************    58 // *********************************************************************** 
      59 // function prototypes ***************************************************
      60
      61 void ic2_timerhandler(int keynumber);
      62
      63 // *********************************************************************** 
59 // global variables ******************************************************   64 // global variables ******************************************************
60   65
61 // +----------------------------------------------------   66 // +----------------------------------------------------
62 // Global Variables   67 // Global Variables
63 // +----------------------------------------------------   68 // +----------------------------------------------------
64   69
65 // Windowサイズ   70 // Windowサイズ
66 int window_w = 400;   71 int window_w = 400;
67 int window_h = 400;   72 int window_h = 400;
68   73
69 // 直交投影時のスケールファクタ [pixel / unit_of_imager]   74 // 直交投影時のスケールファクタ [pixel / unit_of_imager]
70 // ここでは正規化カメラの撮像面での 1.0 単位を 200画素に相当させる   75 // ここでは正規化カメラの撮像面での 1.0 単位を 200画素に相当させる
71 float ortho_unit = 200.0;    76 float ortho_unit = 200.0; 
72   77
73 // 透視投影に用いる焦点距離 [pixel]   78 // 透視投影に用いる焦点距離 [pixel]
74 // y方向に fovy度 開いて画像の縦が400画素のときの焦点距離で単位は画素。   79 // y方向に fovy度 開いて画像の縦が400画素のときの焦点距離で単位は画素。
75 // ウィンドウサイズ変更時の扱い:   80 // ウィンドウサイズ変更時の扱い:
76 // ・本プログラムではウィンドウサイズが途中で変わるときに見た目の大きさを保つ。   81 // ・本プログラムではウィンドウサイズが途中で変わるときに見た目の大きさを保つ。
77 // ・ここでは、概念的にはウィンドウサイズ変更は撮像面の大きさ変化を意味する。   82 // ・ここでは、概念的にはウィンドウサイズ変更は撮像面の大きさ変化を意味する。
78 // ・焦点距離が同一のまま撮像面の大きさのみ変化したとして投影を表現する。   83 // ・焦点距離が同一のまま撮像面の大きさのみ変化したとして投影を表現する。
79 //   84 //
80 // 撮像面の横幅400画素に対して水平画角35.0°となる焦点距離を初期値設定:   85 // 撮像面の横幅400画素に対して水平画角35.0°となる焦点距離を初期値設定:
81 // tan(35.0[deg]/2) = (400[pixel]/2) / f [pixel]   86 // tan(35.0[deg]/2) = (400[pixel]/2) / f [pixel]
82 // → f = 634.319 [pixel]   87 // → f = 634.319 [pixel]
83 double camera_f = 634.319;    88 double camera_f = 634.319; 
84   89
85 // WindowのID(描画管理用)   90 // WindowのID(描画管理用)
86 int window_id = -1;   91 int window_id = -1;
87   92
88 // トグルスイッチ (1 ... On, -1 ... Off)   93 // トグルスイッチ (1 ... On, -1 ... Off)
89 int tgl_showpredefined = -1; // プログラム内定義物体の表示   94 int tgl_showpredefined = -1; // プログラム内定義物体の表示
90 int tgl_shownormal = -1;     // 法線表示   95 int tgl_shownormal = -1;     // 法線表示
91 int tgl_movelightonly = -1;  // 一時的な光源操作 (必ず-1で初期化)   96 int tgl_movelightonly = -1;  // 一時的な光源操作 (必ず-1で初期化)
92 GLfloat mvmlocked[16]; // 光源操作時にロックされたMODELVIEW行列の内容   97 GLfloat mvmlocked[16]; // 光源操作時にロックされたMODELVIEW行列の内容
93 int tgl_perspective = -1;    // -1...直交投影, 1...透視投影   98 int tgl_perspective = -1;    // -1...直交投影, 1...透視投影
94   99
95 // オブジェクトモデル   100 // オブジェクトモデル
96 struct ic2PATCH *firstpatchptr = NULL;   101 struct ic2PATCH *firstpatchptr = NULL;
97   102
98 // キー操作記録   103 // キー操作記録
99 struct ic2KEYINPUT *firstkeyinputptr = NULL;  // リンクトリストの先頭   104 struct ic2KEYINPUT *firstkeyinputptr = NULL;  // リンクトリストの先頭
100 struct ic2KEYINPUT *latestkeyinputptr = NULL; // リンクトリストの最後尾   105 struct ic2KEYINPUT *latestkeyinputptr = NULL; // リンクトリストの最後尾
101 int tgl_keyinput = -1; // -1 ... 非記録, 1 ... 記録中   106 int tgl_keyinput = -1; // -1 ... 非記録, 1 ... 記録中
      107 int tgl_playing = -1; // -1 ... 非再生中, 1 ... 再生中
      108 int playinterval = 100; // 再生間隔 [ms]
102   109
103 // ***********************************************************************    110 // *********************************************************************** 
104 // key memory ************************************************************   111 // key memory ************************************************************
105   112
106 // +++--------------------------------------------------   113 // +++--------------------------------------------------
107 // 新しいキー入力構造体(ic2KEYINPUT)のメモリ確保と初期化   114 // 新しいキー入力構造体(ic2KEYINPUT)のメモリ確保と初期化
108 // +++--------------------------------------------------   115 // +++--------------------------------------------------
109 static struct ic2KEYINPUT *ic2_NewKEYINPUT (void) {   116 static struct ic2KEYINPUT *ic2_NewKEYINPUT (void) {
110   struct ic2KEYINPUT *newkeyinput = NULL;   117   struct ic2KEYINPUT *newkeyinput = NULL;
111   118
112   newkeyinput = (struct ic2KEYINPUT *)calloc(1, sizeof(struct ic2KEYINPUT));   119   newkeyinput = (struct ic2KEYINPUT *)calloc(1, sizeof(struct ic2KEYINPUT));
113   return (newkeyinput);   120   return (newkeyinput);
114 }   121 }
115   122
116 // -----------------------------------------------------   123 // -----------------------------------------------------
117 // キー1つ分の記録   124 // キー1つ分の記録
118 // -----------------------------------------------------   125 // -----------------------------------------------------
119 int ic2_LogKey(unsigned char key) {   126 int ic2_LogKey(unsigned char key) {
120   struct ic2KEYINPUT *newkeyinput = NULL; // キー入力構造体ヘのポインタ   127   struct ic2KEYINPUT *newkeyinput = NULL; // キー入力構造体ヘのポインタ
121   128
122   // (1) Logの可否   129   // (1) Logの可否
123   if (tgl_keyinput != 1)   130   if (tgl_keyinput != 1)
124     return 1;   131     return 1;
125   132
126   // (2) メモリ確保/下請け   133   // (2) メモリ確保/下請け
127   if ((newkeyinput = ic2_NewKEYINPUT()) == NULL) {   134   if ((newkeyinput = ic2_NewKEYINPUT()) == NULL) {
128     printf("ic2_LogKey: Memory allocation failed.\n");   135     printf("ic2_LogKey: Memory allocation failed.\n");
129     return 1;   136     return 1;
130   }   137   }
131   138
132   // (3) 値の保存   139   // (3) 値の保存
133   newkeyinput->key = key;   140   newkeyinput->key = key;
134   141
135   // (4) ic2KEYINPUTリスト構造への組み込み   142   // (4) ic2KEYINPUTリスト構造への組み込み
136   // *newkeyinput を キー入力集合の最後尾に挿入   143   // *newkeyinput を キー入力集合の最後尾に挿入
137   if (firstkeyinputptr == NULL) {   144   if (firstkeyinputptr == NULL) {
138     firstkeyinputptr = newkeyinput;   145     firstkeyinputptr = newkeyinput;
139     latestkeyinputptr = newkeyinput;   146     latestkeyinputptr = newkeyinput;
140   } else {   147   } else {
141     latestkeyinputptr->next = newkeyinput;   148     latestkeyinputptr->next = newkeyinput;
142     latestkeyinputptr = newkeyinput;   149     latestkeyinputptr = newkeyinput;
143   }   150   }
144   return 0;   151   return 0;
145 }   152 }
146   153
147 // -----------------------------------------------------   154 // -----------------------------------------------------
148 // キーインプット構造体(ic2KEYINPUT)リストの表示   155 // キーインプット構造体(ic2KEYINPUT)リストの表示
149 // -----------------------------------------------------   156 // -----------------------------------------------------
150 int ic2_PrintKEYINPUTList (struct ic2KEYINPUT *firstkeyinputptr) {   157 int ic2_PrintKEYINPUTList (void) {
151   struct ic2KEYINPUT *p;   158   struct ic2KEYINPUT *p;
152   int np = 0;   159   int np = 0;
153   160
154   printf("KEYINPUT: \n");   161   printf("KEYINPUT: \n");
155   for (p = firstkeyinputptr; p != NULL; p = p->next) {   162   for (p = firstkeyinputptr; p != NULL; p = p->next) {
156     np++;   163     np++;
157     printf("%c", p->key);   164     printf("%c", p->key);
158   }   165   }
159   printf("\n");   166   printf("\n");
160   printf("KEYINPUT: %d keys.\n", np);   167   printf("KEYINPUT: %d keys.\n", np);
161   168
162   return np;   169   return np;
163 }   170 }
164   171
165 // -----------------------------------------------------   172 // -----------------------------------------------------
166 // キーインプット構造体(ic2KEYINPUT)リストの解放   173 // キーインプット構造体(ic2KEYINPUT)リストの解放
167 // -----------------------------------------------------   174 // -----------------------------------------------------
168 int ic2_FreeKEYINPUTList (struct ic2KEYINPUT *keyinputptr) {   175 int ic2_FreeKEYINPUTList (struct ic2KEYINPUT *keyinputptr) {
169   struct ic2KEYINPUT *nextptr;   176   struct ic2KEYINPUT *nextptr;
170   int n = 0;   177   int n = 0;
171      178   
172   while (keyinputptr != NULL) {   179   while (keyinputptr != NULL) {
173     nextptr = keyinputptr->next;   180     nextptr = keyinputptr->next;
174     free(keyinputptr);   181     free(keyinputptr);
175     keyinputptr = nextptr;   182     keyinputptr = nextptr;
176   }   183   }
177   184
178   return n;   185   return n;
179 }   186 }
180   187
181 // ***********************************************************************    188 // *********************************************************************** 
182 // read model ************************************************************   189 // read model ************************************************************
183   190
184 // +++--------------------------------------------------   191 // +++--------------------------------------------------
185 // 法線方向ベクトルの計算   192 // 法線方向ベクトルの計算
186 // +++--------------------------------------------------   193 // +++--------------------------------------------------
187 // glEnable(GL_NORMALIZE) で法線ベクトルは常に正規化して解釈させるのでここでは正規化不要   194 // glEnable(GL_NORMALIZE) で法線ベクトルは常に正規化して解釈させるのでここでは正規化不要
188 // 3頂点 s-t-u , 2ベクトル st and su, 法線ベクトル  n   195 // 3頂点 s-t-u , 2ベクトル st and su, 法線ベクトル  n
189 static void ic2_SetPatchNormal (struct ic2PATCH *p) {   196 static void ic2_SetPatchNormal (struct ic2PATCH *p) {
190   struct ic2POINT oa, ob;   197   struct ic2POINT oa, ob;
191   oa.x = p->t.x - p->s.x;   198   oa.x = p->t.x - p->s.x;
192   oa.y = p->t.y - p->s.y;   199   oa.y = p->t.y - p->s.y;
193   oa.z = p->t.z - p->s.z;   200   oa.z = p->t.z - p->s.z;
194   ob.x = p->u.x - p->s.x;   201   ob.x = p->u.x - p->s.x;
195   ob.y = p->u.y - p->s.y;   202   ob.y = p->u.y - p->s.y;
196   ob.z = p->u.z - p->s.z;   203   ob.z = p->u.z - p->s.z;
197   p->n.x = oa.y * ob.z - oa.z * ob.y;   204   p->n.x = oa.y * ob.z - oa.z * ob.y;
198   p->n.y = oa.z * ob.x - oa.x * ob.z;   205   p->n.y = oa.z * ob.x - oa.x * ob.z;
199   p->n.z = oa.x * ob.y - oa.y * ob.x;   206   p->n.z = oa.x * ob.y - oa.y * ob.x;
200 }   207 }
201   208
202 // +++--------------------------------------------------   209 // +++--------------------------------------------------
203 // パッチに関する追加属性の計算(重心と表示用長さ補正項)   210 // パッチに関する追加属性の計算(重心と表示用長さ補正項)
204 // +++--------------------------------------------------   211 // +++--------------------------------------------------
205 static void ic2_SetPatchMoreAttributes (struct ic2PATCH *p) {   212 static void ic2_SetPatchMoreAttributes (struct ic2PATCH *p) {
206   213
207   // パッチ重心の計算   214   // パッチ重心の計算
208   p->b.x = (p->s.x + p->t.x + p->u.x) / 3;   215   p->b.x = (p->s.x + p->t.x + p->u.x) / 3;
209   p->b.y = (p->s.y + p->t.y + p->u.y) / 3;   216   p->b.y = (p->s.y + p->t.y + p->u.y) / 3;
210   p->b.z = (p->s.z + p->t.z + p->u.z) / 3;   217   p->b.z = (p->s.z + p->t.z + p->u.z) / 3;
211   218
212   // 法線ベクトル表示時の長さ補正項の計算   219   // 法線ベクトル表示時の長さ補正項の計算
213   p->l = sqrt(p->n.x * p->n.x + p->n.y * p->n.y + p->n.z * p->n.z);   220   p->l = sqrt(p->n.x * p->n.x + p->n.y * p->n.y + p->n.z * p->n.z);
214   if (p->l != 0.0) {   221   if (p->l != 0.0) {
215     p->l = sqrt(p->l) / p->l;   222     p->l = sqrt(p->l) / p->l;
216   }   223   }
217 }   224 }
218   225
219 // +++--------------------------------------------------   226 // +++--------------------------------------------------
220 // 新しい三角形パッチ構造体(ic2PATCH)のメモリ確保と初期化   227 // 新しい三角形パッチ構造体(ic2PATCH)のメモリ確保と初期化
221 // +++--------------------------------------------------   228 // +++--------------------------------------------------
222 static struct ic2PATCH *ic2_NewPATCH (void) {   229 static struct ic2PATCH *ic2_NewPATCH (void) {
223   struct ic2PATCH *newpatch = NULL;   230   struct ic2PATCH *newpatch = NULL;
224   231
225   newpatch = (struct ic2PATCH *)calloc(1, sizeof(struct ic2PATCH));   232   newpatch = (struct ic2PATCH *)calloc(1, sizeof(struct ic2PATCH));
226   return (newpatch);   233   return (newpatch);
227 }   234 }
228   235
229 // +++--------------------------------------------------   236 // +++--------------------------------------------------
230 // 三角形パッチ構造体(ic2PATCH)1つ分の読み込み   237 // 三角形パッチ構造体(ic2PATCH)1つ分の読み込み
231 // +++--------------------------------------------------   238 // +++--------------------------------------------------
232 static int ic2_InsertPATCH (struct ic2PATCH **firstpatchptr, char *onelinedata) {   239 static int ic2_InsertPATCH (struct ic2PATCH **firstpatchptr, char *onelinedata) {
233   // (1) 文字列へのポインタは存在するか   240   // (1) 文字列へのポインタは存在するか
234   // (2) メモリ確保/下請け   241   // (2) メモリ確保/下請け
235   // (3) 値の読み込み   242   // (3) 値の読み込み
236   // (4) ic2PATCHリスト構造への組み込み   243   // (4) ic2PATCHリスト構造への組み込み
237   struct ic2PATCH *newpatch = NULL; // 三角形パッチ構造体ヘのポインタ   244   struct ic2PATCH *newpatch = NULL; // 三角形パッチ構造体ヘのポインタ
238   int number_of_element = 0;        // 読み込めた項目数   245   int number_of_element = 0;        // 読み込めた項目数
239   246
240   // (1) 文字列へのポインタは存在するか   247   // (1) 文字列へのポインタは存在するか
241   if (onelinedata == NULL) return 1;   248   if (onelinedata == NULL) return 1;
242   249
243   // (2) メモリ確保/下請け   250   // (2) メモリ確保/下請け
244   if ((newpatch = ic2_NewPATCH()) == NULL) {   251   if ((newpatch = ic2_NewPATCH()) == NULL) {
245     printf("ic2_InsertPATCH: Memory allocation failed.\n");   252     printf("ic2_InsertPATCH: Memory allocation failed.\n");
246     return 2;   253     return 2;
247   }   254   }
248   255
249   // (3) 値の読み込み   256   // (3) 値の読み込み
250   number_of_element =    257   number_of_element = 
251     sscanf(onelinedata, "%f %f %f  %f %f %f  %f %f %f  %f %f %f",    258     sscanf(onelinedata, "%f %f %f  %f %f %f  %f %f %f  %f %f %f", 
252    &newpatch->s.x, &newpatch->s.y, &newpatch->s.z,   259    &newpatch->s.x, &newpatch->s.y, &newpatch->s.z,
253    &newpatch->t.x, &newpatch->t.y, &newpatch->t.z,   260    &newpatch->t.x, &newpatch->t.y, &newpatch->t.z,
254    &newpatch->u.x, &newpatch->u.y, &newpatch->u.z,   261    &newpatch->u.x, &newpatch->u.y, &newpatch->u.z,
255    &newpatch->c.r, &newpatch->c.g, &newpatch->c.b);   262    &newpatch->c.r, &newpatch->c.g, &newpatch->c.b);
256   if (number_of_element != 12) {   263   if (number_of_element != 12) {
257     printf("ic2_InsertPATCH: format error (%d elements found)\n", number_of_element);   264     printf("ic2_InsertPATCH: format error (%d elements found)\n", number_of_element);
258     printf("ic2_InsertPATCH: \"%s\"\n", onelinedata);   265     printf("ic2_InsertPATCH: \"%s\"\n", onelinedata);
259     free(newpatch);   266     free(newpatch);
260     return 3;   267     return 3;
261   }   268   }
262   269
263   // (3.5) 法線ベクトルの計算   270   // (3.5) 法線ベクトルの計算
264   ic2_SetPatchNormal(newpatch);   271   ic2_SetPatchNormal(newpatch);
265   272
266   // (3.6) パッチに関する追加属性の計算(重心と表示用長さ補正項)   273   // (3.6) パッチに関する追加属性の計算(重心と表示用長さ補正項)
267   ic2_SetPatchMoreAttributes(newpatch);   274   ic2_SetPatchMoreAttributes(newpatch);
268   275
269   // (4) ic2PATCHリスト構造への組み込み   276   // (4) ic2PATCHリスト構造への組み込み
270   // *newpatch を 三角形パッチ集合の先頭に挿入   277   // *newpatch を 三角形パッチ集合の先頭に挿入
271   newpatch->next = *firstpatchptr;   278   newpatch->next = *firstpatchptr;
272   *firstpatchptr = newpatch;   279   *firstpatchptr = newpatch;
273   return 0;   280   return 0;
274 }   281 }
275   282
276 // +----------------------------------------------------   283 // +----------------------------------------------------
277 // モデルのファイルからの読込   284 // モデルのファイルからの読込
278 // +----------------------------------------------------   285 // +----------------------------------------------------
279 // 返値:負 ... エラー   286 // 返値:負 ... エラー
280 // 返値:0ないし正値 ... 読み込みに成功したパッチ数   287 // 返値:0ないし正値 ... 読み込みに成功したパッチ数
281 int ic2_ReadModel(char *filename, struct ic2PATCH **firstpatchptr) {   288 int ic2_ReadModel(char *filename, struct ic2PATCH **firstpatchptr) {
282   FILE *filetoopen = NULL; // A pointer to FILE structure   289   FILE *filetoopen = NULL; // A pointer to FILE structure
283   char oneline[256]; // 1行分のバッファ,固定長にしておくとsizeof()が利用可能   290   char oneline[256]; // 1行分のバッファ,固定長にしておくとsizeof()が利用可能
284   char firstword[256]; // コメント行かどうかの判定用   291   char firstword[256]; // コメント行かどうかの判定用
285   int  linenumber = 0; // ファイル中の行番号   292   int  linenumber = 0; // ファイル中の行番号
286   int  patchnumber = 0; // パッチ数   293   int  patchnumber = 0; // パッチ数
287   294
288   // We need at least one option to indicate a file to open   295   // We need at least one option to indicate a file to open
289   if (filename == NULL) {    296   if (filename == NULL) { 
290     printf("Error: You need to specify a one file to open.\n");   297     printf("Error: You need to specify a one file to open.\n");
291     return -1;   298     return -1;
292   }   299   }
293   300
294   // Try to open it   301   // Try to open it
295   filetoopen = fopen(filename, "r");   302   filetoopen = fopen(filename, "r");
296   if (filetoopen == NULL) {   303   if (filetoopen == NULL) {
297     printf("Error: Failed to open/read \"%s\".\n", filename);   304     printf("Error: Failed to open/read \"%s\".\n", filename);
298     return -2;   305     return -2;
299   }   306   }
300   printf("Reading model from \"%s\"\n", filename);   307   printf("Reading model from \"%s\"\n", filename);
301   308
302   // 1行ずつ読込   309   // 1行ずつ読込
303   while (fgets(oneline, sizeof(oneline), filetoopen) != NULL) {   310   while (fgets(oneline, sizeof(oneline), filetoopen) != NULL) {
304     linenumber++;   311     linenumber++;
305   312
306     // もし行内に1文字もなければ(1単語もなければ)次行へ   313     // もし行内に1文字もなければ(1単語もなければ)次行へ
307     if (sscanf(oneline, "%256s", firstword) < 1)   314     if (sscanf(oneline, "%256s", firstword) < 1)
308       continue;   315       continue;
309     // もし先頭が#で始まっていれば次行へ   316     // もし先頭が#で始まっていれば次行へ
310     if (firstword[0] == '#')    317     if (firstword[0] == '#') 
311       continue;   318       continue;
312     // 他のエラートラップ   319     // 他のエラートラップ
313     if (0) {   320     if (0) {
314       printf("Skip(line=%d): %s\n", linenumber, oneline);   321       printf("Skip(line=%d): %s\n", linenumber, oneline);
315       continue;   322       continue;
316     }   323     }
317   324
318     if (ic2_InsertPATCH(firstpatchptr, oneline)) {   325     if (ic2_InsertPATCH(firstpatchptr, oneline)) {
319       printf("Model reading is interrupted.\n");   326       printf("Model reading is interrupted.\n");
320       break;   327       break;
321     }   328     }
322     patchnumber++;   329     patchnumber++;
323   }   330   }
324   331
325   // And close it   332   // And close it
326   if (fclose(filetoopen) != 0) {   333   if (fclose(filetoopen) != 0) {
327     printf("Error: Failed to close \"%s\".\n", filename);   334     printf("Error: Failed to close \"%s\".\n", filename);
328     // error, but we get data anyway...   335     // error, but we get data anyway...
329   }   336   }
330   337
331   printf("Finish reading the model (%d patches).\n", patchnumber);   338   printf("Finish reading the model (%d patches).\n", patchnumber);
332   return patchnumber;   339   return patchnumber;
333 }   340 }
334   341
335 // -----------------------------------------------------   342 // -----------------------------------------------------
336 // 三角形パッチ構造体(ic2PATCH)リストの表示   343 // 三角形パッチ構造体(ic2PATCH)リストの表示
337 // -----------------------------------------------------   344 // -----------------------------------------------------
338 int ic2_PrintPATCHList (struct ic2PATCH *firstpatchptr) {   345 int ic2_PrintPATCHList (struct ic2PATCH *firstpatchptr) {
339   struct ic2PATCH *p;   346   struct ic2PATCH *p;
340   int np = 0;   347   int np = 0;
341   348
342   for (p = firstpatchptr; p != NULL; p = p->next) {   349   for (p = firstpatchptr; p != NULL; p = p->next) {
343     np++;   350     np++;
344     printf("PATCH: (%g, %g, %g), (%g, %g, %g), (%g, %g, %g), rgb=[%g, %g, %g] ",   351     printf("PATCH: (%g, %g, %g), (%g, %g, %g), (%g, %g, %g), rgb=[%g, %g, %g] ",
345    p->s.x, p->s.y, p->s.z,   352    p->s.x, p->s.y, p->s.z,
346    p->t.x, p->t.y, p->t.z,   353    p->t.x, p->t.y, p->t.z,
347    p->u.x, p->u.y, p->u.z,   354    p->u.x, p->u.y, p->u.z,
348    p->c.r, p->c.g, p->c.b);   355    p->c.r, p->c.g, p->c.b);
349     printf("n=(%g, %g, %g), b=(%g, %g, %g), l=%g\n",   356     printf("n=(%g, %g, %g), b=(%g, %g, %g), l=%g\n",
350    p->n.x, p->n.y, p->n.z,   357    p->n.x, p->n.y, p->n.z,
351    p->b.x, p->b.y, p->b.z,   358    p->b.x, p->b.y, p->b.z,
352    p->l);   359    p->l);
353   }   360   }
354   361
355   return np;   362   return np;
356 }   363 }
357   364
358 // ***********************************************************************    365 // *********************************************************************** 
359 // gl utilitiess *********************************************************   366 // gl utilitiess *********************************************************
360   367
361 // +----------------------------------------------------   368 // +----------------------------------------------------
362 // MODELVIEW Matrix と PROJECTION を表示する   369 // MODELVIEW Matrix と PROJECTION を表示する
363 // +----------------------------------------------------   370 // +----------------------------------------------------
364 void ic2_ShowMATRIX (char *str) {   371 void ic2_ShowMATRIX (char *str) {
365   GLfloat m[16]; // GL_MODELVIEW matrix   372   GLfloat m[16]; // GL_MODELVIEW matrix
366   GLfloat p[16]; // GL_PROJECTION matrix   373   GLfloat p[16]; // GL_PROJECTION matrix
367   374
368   glGetFloatv(GL_MODELVIEW_MATRIX , m);  // MODELVIEWのスタックトップmatrixをmにコピー   375   glGetFloatv(GL_MODELVIEW_MATRIX , m);  // MODELVIEWのスタックトップmatrixをmにコピー
369   glGetFloatv(GL_PROJECTION_MATRIX, p); // PROJECTIONのスタックトップmatrixをpにコピー   376   glGetFloatv(GL_PROJECTION_MATRIX, p); // PROJECTIONのスタックトップmatrixをpにコピー
370   if (str != NULL) printf("<< %s >>\n", str);   377   if (str != NULL) printf("<< %s >>\n", str);
371   printf("MODELVIEW Matrix                        PROJECTION Matrix\n");   378   printf("MODELVIEW Matrix                        PROJECTION Matrix\n");
372   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n",   379   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n",
373           m[ 0], m[ 4], m[ 8], m[12],     p[ 0], p[ 4], p[ 8], p[12]);   380           m[ 0], m[ 4], m[ 8], m[12],     p[ 0], p[ 4], p[ 8], p[12]);
374   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n",    381   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n", 
375           m[ 1], m[ 5], m[ 9], m[13],     p[ 1], p[ 5], p[ 9], p[13]);   382           m[ 1], m[ 5], m[ 9], m[13],     p[ 1], p[ 5], p[ 9], p[13]);
376   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n",    383   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n", 
377           m[ 2], m[ 6], m[10], m[14],     p[ 2], p[ 6], p[10], p[14]);   384           m[ 2], m[ 6], m[10], m[14],     p[ 2], p[ 6], p[10], p[14]);
378   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n",    385   printf("%7.3f  %7.3f  %7.3f  %7.3f      %7.3f  %7.3f  %7.3f  %7.3f\n", 
379           m[ 3], m[ 7], m[11], m[15],     p[ 3], p[ 7], p[11], p[15]);   386           m[ 3], m[ 7], m[11], m[15],     p[ 3], p[ 7], p[11], p[15]);
380 }   387 }
381   388
382 // ***********************************************************************    389 // *********************************************************************** 
383 // objects_embeded *******************************************************   390 // objects_embeded *******************************************************
384   391
385 // +----------------------------------------------------   392 // +----------------------------------------------------
386 // 正方形を描く   393 // 正方形を描く
387 // +----------------------------------------------------   394 // +----------------------------------------------------
388 void ic2_FigSquare (float s) {   395 void ic2_FigSquare (float s) {
389   glDisable(GL_LIGHTING);   // 光源によるシェーディングを一旦切る   396   glDisable(GL_LIGHTING);   // 光源によるシェーディングを一旦切る
390   397
391   // 正方形(Z=0の平面内、+/- 0.9)   398   // 正方形(Z=0の平面内、+/- 0.9)
392   glBegin(GL_LINE_LOOP); {   399   glBegin(GL_LINE_LOOP); {
393     glColor3f(1.0, 1.0, 1.0);   400     glColor3f(1.0, 1.0, 1.0);
394     glVertex3f(s * -1, s * -1, 0.0);   401     glVertex3f(s * -1, s * -1, 0.0);
395     glVertex3f(s * +1, s * -1, 0.0);   402     glVertex3f(s * +1, s * -1, 0.0);
396     glVertex3f(s * +1, s * +1, 0.0);   403     glVertex3f(s * +1, s * +1, 0.0);
397     glVertex3f(s * -1, s * +1, 0.0);   404     glVertex3f(s * -1, s * +1, 0.0);
398   } glEnd();   405   } glEnd();
399   406
400   // 3軸   407   // 3軸
401   glBegin(GL_LINES); {   408   glBegin(GL_LINES); {
402     glColor3f(1.0, 0.5, 0.5); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.85, 0.0,  0.0); // X (red)   409     glColor3f(1.0, 0.5, 0.5); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.85, 0.0,  0.0); // X (red)
403     glColor3f(0.5, 1.0, 0.5); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0,  0.70, 0.0); // Y (green)   410     glColor3f(0.5, 1.0, 0.5); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0,  0.70, 0.0); // Y (green)
404     glColor3f(0.5, 0.5, 1.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0,  0.0,  1.0); // Z (blue)   411     glColor3f(0.5, 0.5, 1.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0,  0.0,  1.0); // Z (blue)
405   } glEnd();   412   } glEnd();
406   413
407   glEnable(GL_LIGHTING);   // 光源によるシェーディングを開始する   414   glEnable(GL_LIGHTING);   // 光源によるシェーディングを開始する
408 }   415 }
409   416
410 // +----------------------------------------------------   417 // +----------------------------------------------------
411 // ティーポットを描く (glutの作り付け関数の1つ)   418 // ティーポットを描く (glutの作り付け関数の1つ)
412 // +----------------------------------------------------   419 // +----------------------------------------------------
413 void ic2_FigSolidTeapot (float s) {   420 void ic2_FigSolidTeapot (float s) {
414   GLfloat obj_ref[] = {1.0, 1.0, 0.3, 1.0}; // teapotの色情報 (DIFFUSE用)   421   GLfloat obj_ref[] = {1.0, 1.0, 0.3, 1.0}; // teapotの色情報 (DIFFUSE用)
415   GLfloat obj_shn[] = {10.0};               // teapotの色情報 (SHININESS用)   422   GLfloat obj_shn[] = {10.0};               // teapotの色情報 (SHININESS用)
416   423
417   // 色の設定   424   // 色の設定
418   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, obj_ref);   425   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, obj_ref);
419   glMaterialfv(GL_FRONT, GL_SHININESS, obj_shn);   426   glMaterialfv(GL_FRONT, GL_SHININESS, obj_shn);
420   427
421   glutSolidTeapot(s);   428   glutSolidTeapot(s);
422 }   429 }
423   430
424 // ***********************************************************************    431 // *********************************************************************** 
425 // objects_model *********************************************************   432 // objects_model *********************************************************
426   433
427 // +----------------------------------------------------   434 // +----------------------------------------------------
428 // ファイルからの物体を表示   435 // ファイルからの物体を表示
429 // +----------------------------------------------------   436 // +----------------------------------------------------
430 int ic2_DrawModel (struct ic2PATCH *firstpatchptr) {   437 int ic2_DrawModel (struct ic2PATCH *firstpatchptr) {
431   struct ic2PATCH  *p; // パッチ構造体へのポインタ   438   struct ic2PATCH  *p; // パッチ構造体へのポインタ
432   439
433   for (p = firstpatchptr; p != NULL; p = p->next) {   440   for (p = firstpatchptr; p != NULL; p = p->next) {
434     GLfloat v[4];   441     GLfloat v[4];
435   442
436     // 面の色要素(反射特性)をDiffuseとSpecularについて指示   443     // 面の色要素(反射特性)をDiffuseとSpecularについて指示
437     v[0] = p->c.r; v[1] = p->c.g; v[2] = p->c.b; v[3] = 1.0;   444     v[0] = p->c.r; v[1] = p->c.g; v[2] = p->c.b; v[3] = 1.0;
438     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, v);   445     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, v);
439     v[0] = 10.0;   446     v[0] = 10.0;
440     glMaterialfv(GL_FRONT, GL_SHININESS, v);   447     glMaterialfv(GL_FRONT, GL_SHININESS, v);
441   448
442     // 面の法線を指示   449     // 面の法線を指示
443     glNormal3f(p->n.x, p->n.y, p->n.z);   450     glNormal3f(p->n.x, p->n.y, p->n.z);
444   451
445     // 面を構成する3頂点を指示   452     // 面を構成する3頂点を指示
446     glBegin(GL_TRIANGLES); {   453     glBegin(GL_TRIANGLES); {
447       glVertex3f(p->s.x, p->s.y, p->s.z);   454       glVertex3f(p->s.x, p->s.y, p->s.z);
448       glVertex3f(p->t.x, p->t.y, p->t.z);   455       glVertex3f(p->t.x, p->t.y, p->t.z);
449       glVertex3f(p->u.x, p->u.y, p->u.z);   456       glVertex3f(p->u.x, p->u.y, p->u.z);
450     } glEnd();   457     } glEnd();
451   458
452     // 法線の表示   459     // 法線の表示
453     if (tgl_shownormal == 1) {   460     if (tgl_shownormal == 1) {
454       glDisable(GL_LIGHTING);   461       glDisable(GL_LIGHTING);
455       glColor3f(0.3, 1.0, 0.4);   462       glColor3f(0.3, 1.0, 0.4);
456       glBegin(GL_LINES); {   463       glBegin(GL_LINES); {
457         glVertex3f(p->b.x, p->b.y, p->b.z);   464         glVertex3f(p->b.x, p->b.y, p->b.z);
458         glVertex3f(p->b.x + p->l * p->n.x, p->b.y + p->l * p->n.y, p->b.z + p->l * p->n.z);   465         glVertex3f(p->b.x + p->l * p->n.x, p->b.y + p->l * p->n.y, p->b.z + p->l * p->n.z);
459       } glEnd();   466       } glEnd();
460       glEnable(GL_LIGHTING);   467       glEnable(GL_LIGHTING);
461     }   468     }
462        469     
463   }   470   }
464   return 0;   471   return 0;
465 }   472 }
466   473
467 // ***********************************************************************    474 // *********************************************************************** 
468 // lighting **************************************************************    475 // lighting ************************************************************** 
469   476
470 // +----------------------------------------------------   477 // +----------------------------------------------------
471 // 光源を用意   478 // 光源を用意
472 // +----------------------------------------------------   479 // +----------------------------------------------------
473 //  X     Y     Z     Diff(R,G,B)   Spec(R,G,B)   480 //  X     Y     Z     Diff(R,G,B)   Spec(R,G,B)
474 //  1.0   2.0   3.0   0.2 0.2 0.2   0.4 0.4 0.4   481 //  1.0   2.0   3.0   0.2 0.2 0.2   0.4 0.4 0.4
475 // -1.0   2.0   3.0   0.4 0.4 0.4   0.4 0.4 0.4   482 // -1.0   2.0   3.0   0.4 0.4 0.4   0.4 0.4 0.4
476 //  0.0   4.0   0.0   1.0 1.0 1.0   1.0 1.0 1.0   483 //  0.0   4.0   0.0   1.0 1.0 1.0   1.0 1.0 1.0
477 void ic2_LightSetA (void) {   484 void ic2_LightSetA (void) {
478   static int initflag = 0;   485   static int initflag = 0;
479   486
480   if (initflag == 0) {   487   if (initflag == 0) {
481     glEnable(GL_DEPTH_TEST); // デプスバッファによる描画を行う   488     glEnable(GL_DEPTH_TEST); // デプスバッファによる描画を行う
482     glEnable(GL_NORMALIZE);  // 法線ベクトルを常に正規化して解釈させる   489     glEnable(GL_NORMALIZE);  // 法線ベクトルを常に正規化して解釈させる
483     glEnable(GL_LIGHTING);   // 光源によるシェーディングを開始する   490     glEnable(GL_LIGHTING);   // 光源によるシェーディングを開始する
484     glEnable(GL_LIGHT0);     // LIGHT0 を利用   491     glEnable(GL_LIGHT0);     // LIGHT0 を利用
485     glEnable(GL_LIGHT1);     // LIGHT1 を利用   492     glEnable(GL_LIGHT1);     // LIGHT1 を利用
486     glEnable(GL_LIGHT2);     // LIGHT2 を利用   493     glEnable(GL_LIGHT2);     // LIGHT2 を利用
487     initflag = 1;   494     initflag = 1;
488   }   495   }
489      496   
490   GLfloat val[4];   497   GLfloat val[4];
491   498
492   val[0] =  1.0; val[1] =  2.0; val[2] =  3.0; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_POSITION, val);   499   val[0] =  1.0; val[1] =  2.0; val[2] =  3.0; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_POSITION, val);
493   val[0] =  0.2; val[1] =  0.2; val[2] =  0.2; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_DIFFUSE,  val);   500   val[0] =  0.2; val[1] =  0.2; val[2] =  0.2; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_DIFFUSE,  val);
494   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_SPECULAR, val);   501   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT0, GL_SPECULAR, val);
495   502
496   val[0] = -1.0; val[1] =  2.0; val[2] =  3.0; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_POSITION, val);   503   val[0] = -1.0; val[1] =  2.0; val[2] =  3.0; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_POSITION, val);
497   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_DIFFUSE,  val);   504   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_DIFFUSE,  val);
498   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_SPECULAR, val);   505   val[0] =  0.4; val[1] =  0.4; val[2] =  0.4; val[3] = 1.0; glLightfv(GL_LIGHT1, GL_SPECULAR, val);
499   506
500   val[0] =  0.0; val[1] =  4.0; val[2] =  0.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_POSITION, val);   507   val[0] =  0.0; val[1] =  4.0; val[2] =  0.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_POSITION, val);
501   val[0] =  1.0; val[1] =  1.0; val[2] =  1.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_DIFFUSE,  val);   508   val[0] =  1.0; val[1] =  1.0; val[2] =  1.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_DIFFUSE,  val);
502   val[0] =  1.0; val[1] =  1.0; val[2] =  1.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_SPECULAR, val);   509   val[0] =  1.0; val[1] =  1.0; val[2] =  1.0; val[3] = 1.0; glLightfv(GL_LIGHT2, GL_SPECULAR, val);
503 }   510 }
504   511
505 // ***********************************************************************    512 // *********************************************************************** 
506 // camera work ***********************************************************   513 // camera work ***********************************************************
507   514
508 // +----------------------------------------------------   515 // +----------------------------------------------------
509 // カメラの投影行列を設定   516 // カメラの投影行列を設定
510 // +----------------------------------------------------   517 // +----------------------------------------------------
511 // 利用する大域変数: window_w, window_h   518 // 利用する大域変数: window_w, window_h
512 // window_w/window_hの変化に対して、物体の見かけの大きさが変わらないように描画   519 // window_w/window_hの変化に対して、物体の見かけの大きさが変わらないように描画
513 // → ortho_unit が重要!   520 // → ortho_unit が重要!
514 //   521 //
515 void ic2_SetUpCamera_Ortho (void) {   522 void ic2_SetUpCamera_Ortho (void) {
516   float wlimit, hlimit;   523   float wlimit, hlimit;
517   wlimit = (window_w/2) / ortho_unit;    524   wlimit = (window_w/2) / ortho_unit; 
518   hlimit = (window_h/2) / ortho_unit;    525   hlimit = (window_h/2) / ortho_unit; 
519   526
520   // glOrtho(左端, 右端, 下端, 上端, 近接側クリッピング面,  遠方側クリッピング面)   527   // glOrtho(左端, 右端, 下端, 上端, 近接側クリッピング面,  遠方側クリッピング面)
521   glMatrixMode(GL_PROJECTION);   528   glMatrixMode(GL_PROJECTION);
522   glLoadIdentity(); // 毎フレーム再設定するのでPROJECTION行列スタックトップの初期化必要   529   glLoadIdentity(); // 毎フレーム再設定するのでPROJECTION行列スタックトップの初期化必要
523   glOrtho(-wlimit, wlimit, -hlimit, hlimit, -1.0, 1.0);   530   glOrtho(-wlimit, wlimit, -hlimit, hlimit, -1.0, 1.0);
524   531
525   // 通常はMODELVIEWを操作するので念のため元に戻しておく.   532   // 通常はMODELVIEWを操作するので念のため元に戻しておく.
526   glMatrixMode(GL_MODELVIEW);   533   glMatrixMode(GL_MODELVIEW);
527 }   534 }
528   535
529 // +----------------------------------------------------   536 // +----------------------------------------------------
530 // カメラの投影行列を設定   537 // カメラの投影行列を設定
531 // +----------------------------------------------------   538 // +----------------------------------------------------
532 // 利用する大域変数: window_w, window_h, camera_f   539 // 利用する大域変数: window_w, window_h, camera_f
533 // window_w/window_hの変化に対して、物体の見かけの大きさが変わらないように描画   540 // window_w/window_hの変化に対して、物体の見かけの大きさが変わらないように描画
534 // → 焦点距離 camera_f が重要!   541 // → 焦点距離 camera_f が重要!
535 // 注: glViewport()の設定により本演習では撮像面=ウィンドウの大きさ   542 // 注: glViewport()の設定により本演習では撮像面=ウィンドウの大きさ
536 //   543 //
537 void ic2_SetUpCamera_Perspective (void) {   544 void ic2_SetUpCamera_Perspective (void) {
538   float fovy; // 垂直画角    545   float fovy; // 垂直画角 
539   float aspect; // 撮像面のアスペクト比   546   float aspect; // 撮像面のアスペクト比
540   float depth_near_end =   0.1; // 近距離限界   547   float depth_near_end =   0.1; // 近距離限界
541   float depth_far_end  = 100.0; // 遠距離限界   548   float depth_far_end  = 100.0; // 遠距離限界
542   549
543   // 透視投影を規定するためのパラメータ   550   // 透視投影を規定するためのパラメータ
544   fovy = atan((window_h/2.0)/camera_f)*2.0*(180.0/M_PI);   551   fovy = atan((window_h/2.0)/camera_f)*2.0*(180.0/M_PI);
545   aspect = (float)window_w/window_h;   552   aspect = (float)window_w/window_h;
546   depth_near_end = 0.1;   553   depth_near_end = 0.1;
547   depth_far_end  = 100.0;   554   depth_far_end  = 100.0;
548   555
549   // 透視投影行列   556   // 透視投影行列
550   glMatrixMode(GL_PROJECTION);   557   glMatrixMode(GL_PROJECTION);
551   glLoadIdentity(); // 毎フレーム再設定するのでPROJECTION行列スタックトップの初期化必要   558   glLoadIdentity(); // 毎フレーム再設定するのでPROJECTION行列スタックトップの初期化必要
552   gluPerspective(fovy, aspect, depth_near_end, depth_far_end);   559   gluPerspective(fovy, aspect, depth_near_end, depth_far_end);
553      560   
554   // 通常はMODELVIEWを操作するので念のため元に戻しておく.   561   // 通常はMODELVIEWを操作するので念のため元に戻しておく.
555   glMatrixMode(GL_MODELVIEW);   562   glMatrixMode(GL_MODELVIEW);
556 }   563 }
557   564
558 // ***********************************************************************    565 // *********************************************************************** 
559 // rendering *************************************************************   566 // rendering *************************************************************
560   567
561 // +----------------------------------------------------   568 // +----------------------------------------------------
562 // スクリーンに描画する   569 // スクリーンに描画する
563 // +----------------------------------------------------   570 // +----------------------------------------------------
564 void ic2_DrawFrame (void) {   571 void ic2_DrawFrame (void) {
565   572
566   // (前処理) 以前にglClearColor()で指定した色で塗り潰す   573   // (前処理) 以前にglClearColor()で指定した色で塗り潰す
567   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    574   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
568   // (前処理) 今回CGを描画する範囲   575   // (前処理) 今回CGを描画する範囲
569   glViewport(0, 0, window_w, window_h);   576   glViewport(0, 0, window_w, window_h);
570   577
571   // (1) カメラの設置   578   // (1) カメラの設置
572   if (tgl_perspective == 1) {   579   if (tgl_perspective == 1) {
573     ic2_SetUpCamera_Perspective();   580     ic2_SetUpCamera_Perspective();
574   } else {   581   } else {
575     ic2_SetUpCamera_Ortho();   582     ic2_SetUpCamera_Ortho();
576   }   583   }
577   584
578   // (2) 光源の設置   585   // (2) 光源の設置
579   ic2_LightSetA();   586   ic2_LightSetA();
580   587
581   // (3) 物体の設置   588   // (3) 物体の設置
582   // 一時的な光源環境の操作時にはロックした行列を上乗せ   589   // 一時的な光源環境の操作時にはロックした行列を上乗せ
583   if (tgl_movelightonly == 1) {   590   if (tgl_movelightonly == 1) {
584     glMatrixMode(GL_MODELVIEW);   591     glMatrixMode(GL_MODELVIEW);
585     glPushMatrix();   592     glPushMatrix();
586     glLoadMatrixf(mvmlocked);   593     glLoadMatrixf(mvmlocked);
587   }       594   }    
588   if (tgl_showpredefined == 1) {   595   if (tgl_showpredefined == 1) {
589     // 物体描画:正方形   596     // 物体描画:正方形
590     ic2_FigSquare(0.9);   597     ic2_FigSquare(0.9);
591     // 物体描画:ティーポット   598     // 物体描画:ティーポット
592     ic2_FigSolidTeapot(0.5);   599     ic2_FigSolidTeapot(0.5);
593   }   600   }
594   ic2_DrawModel(firstpatchptr);   601   ic2_DrawModel(firstpatchptr);
595   // 一時的な光源環境の操作時には上乗せした行列を廃棄   602   // 一時的な光源環境の操作時には上乗せした行列を廃棄
596   if (tgl_movelightonly == 1) {   603   if (tgl_movelightonly == 1) {
597     glPopMatrix();   604     glPopMatrix();
598   }   605   }
599   606
600   // (後処理) スクリーンの切り替え   607   // (後処理) スクリーンの切り替え
601   glutSwapBuffers();   608   glutSwapBuffers();
602   609
603 }   610 }
604   611
605 // ***********************************************************************    612 // *********************************************************************** 
606 // callbacks *************************************************************    613 // callbacks ************************************************************* 
607   614
608 // +----------------------------------------------------   615 // +----------------------------------------------------
609 // キーが何か押されたときの対策用関数    616 // キーが何か押されたときの対策用関数 
610 // +----------------------------------------------------   617 // +----------------------------------------------------
611 // glutKeyboardFunc()にて登録予定   618 // glutKeyboardFunc()にて登録予定
612 // 引数 : key ... 入力文字    619 // 引数 : key ... 入力文字 
613 // 引数 : x   ... 文字が押されたときのマウスカーソルのX位置    620 // 引数 : x   ... 文字が押されたときのマウスカーソルのX位置 
614 // 引数 : y   ... 文字が押されたときのマウスカーソルのY位置    621 // 引数 : y   ... 文字が押されたときのマウスカーソルのY位置 
615 void ic2_NormalKeyInput (unsigned char key, int x, int y) {   622 void ic2_NormalKeyInput (unsigned char key, int x, int y) {
616   float delta_t = 0.1; // [unit]   623   float delta_t = 0.1; // [unit]
617   float delta_r = 1.0; // [degree]   624   float delta_r = 1.0; // [degree]
618   625
619   switch (key) {   626   switch (key) {
620   case 'q' :   627   case 'q' :
621   case 'Q' :   628   case 'Q' :
622   case 27 : // ESCキーのこと   629   case 27 : // ESCキーのこと
623     exit (0);   630     exit (0);
624     break;   631     break;
625   632
626   // Translation -_+ : [X]h_l [Y]n_u [Z]j_k   633   // Translation -_+ : [X]h_l [Y]n_u [Z]j_k
627   case 'h': glTranslatef(delta_t * -1, 0, 0); ic2_LogKey(key); break;   634   case 'h': glTranslatef(delta_t * -1, 0, 0); ic2_LogKey(key); break;
628   case 'l': glTranslatef(delta_t * +1, 0, 0); ic2_LogKey(key); break;   635   case 'l': glTranslatef(delta_t * +1, 0, 0); ic2_LogKey(key); break;
629   case 'n': glTranslatef(0, delta_t * -1, 0); ic2_LogKey(key); break;   636   case 'n': glTranslatef(0, delta_t * -1, 0); ic2_LogKey(key); break;
630   case 'u': glTranslatef(0, delta_t * +1, 0); ic2_LogKey(key); break;   637   case 'u': glTranslatef(0, delta_t * +1, 0); ic2_LogKey(key); break;
631   case 'j': glTranslatef(0, 0, delta_t * -1); ic2_LogKey(key); break;   638   case 'j': glTranslatef(0, 0, delta_t * -1); ic2_LogKey(key); break;
632   case 'k': glTranslatef(0, 0, delta_t * +1); ic2_LogKey(key); break;   639   case 'k': glTranslatef(0, 0, delta_t * +1); ic2_LogKey(key); break;
633   640
634   // Rotation -_+ : [Y]a_f [Z]s_d [X]x_w   641   // Rotation -_+ : [Y]a_f [Z]s_d [X]x_w
635   case 'x': glRotatef(delta_r * -1, 1, 0, 0); ic2_LogKey(key);  break;   642   case 'x': glRotatef(delta_r * -1, 1, 0, 0); ic2_LogKey(key);  break;
636   case 'w': glRotatef(delta_r * +1, 1, 0, 0); ic2_LogKey(key);  break;   643   case 'w': glRotatef(delta_r * +1, 1, 0, 0); ic2_LogKey(key);  break;
637   case 'a': glRotatef(delta_r * -1, 0, 1, 0); ic2_LogKey(key);  break;   644   case 'a': glRotatef(delta_r * -1, 0, 1, 0); ic2_LogKey(key);  break;
638   case 'f': glRotatef(delta_r * +1, 0, 1, 0); ic2_LogKey(key);  break;   645   case 'f': glRotatef(delta_r * +1, 0, 1, 0); ic2_LogKey(key);  break;
639   case 's': glRotatef(delta_r * -1, 0, 0, 1); ic2_LogKey(key);  break;   646   case 's': glRotatef(delta_r * -1, 0, 0, 1); ic2_LogKey(key);  break;
640   case 'd': glRotatef(delta_r * +1, 0, 0, 1); ic2_LogKey(key);  break;   647   case 'd': glRotatef(delta_r * +1, 0, 0, 1); ic2_LogKey(key);  break;
641   648
642   // [Scale] v_b   649   // [Scale] v_b
643   case 'v': glScalef(0.95, 0.95, 0.95); ic2_LogKey(key);  break;   650   case 'v': glScalef(0.95, 0.95, 0.95); ic2_LogKey(key);  break;
644   case 'b': glScalef(1.05, 1.05, 1.05); ic2_LogKey(key);  break;   651   case 'b': glScalef(1.05, 1.05, 1.05); ic2_LogKey(key);  break;
      652  
      653   // [No Operation] z
      654   case 'z': ic2_LogKey(key);  break;
645   655
646   // [Reset]    656   // [Reset] 
647   case 'R':    657   case 'R': 
648     glMatrixMode(GL_MODELVIEW);   658     glMatrixMode(GL_MODELVIEW);
649     glPopMatrix(); // 保護されてた第1階層に降りる   659     glPopMatrix(); // 保護されてた第1階層に降りる
650     glPushMatrix(); // 保護されてた第1階層からコピーしてスタックトップを1つ上げる   660     glPushMatrix(); // 保護されてた第1階層からコピーしてスタックトップを1つ上げる
651     ic2_LogKey(key);   661     ic2_LogKey(key);
652     break;   662     break;
653   663
654   // [Show Stacktop MODELVIEW Matrix]   664   // [Show Stacktop MODELVIEW Matrix]
655   case 'p':   665   case 'p':
656     ic2_ShowMATRIX("Current status");   666     ic2_ShowMATRIX("Current status");
657     break;   667     break;
658   668
659   // [Toggle Objects] T   669   // [Toggle Objects] T
660   case 'T': tgl_showpredefined *= -1; break;   670   case 'T': tgl_showpredefined *= -1; break;
661   // [Toggle Normals] N   671   // [Toggle Normals] N
662   case 'N': tgl_shownormal *= -1; break;   672   case 'N': tgl_shownormal *= -1; break;
663   // [Move only lights temporarily] L   673   // [Move only lights temporarily] L
664   case 'L':    674   case 'L': 
665     tgl_movelightonly *= -1;    675     tgl_movelightonly *= -1; 
666     if (tgl_movelightonly == 1) {   676     if (tgl_movelightonly == 1) {
667       // この時点のMODELVIEW行列を保存してロック状態にする   677       // この時点のMODELVIEW行列を保存してロック状態にする
668       glMatrixMode(GL_MODELVIEW);   678       glMatrixMode(GL_MODELVIEW);
669       glGetFloatv(GL_MODELVIEW_MATRIX , mvmlocked);   679       glGetFloatv(GL_MODELVIEW_MATRIX , mvmlocked);
670     } else {   680     } else {
671       // ロック状態を開始したときの状況に復帰   681       // ロック状態を開始したときの状況に復帰
672       glMatrixMode(GL_MODELVIEW);   682       glMatrixMode(GL_MODELVIEW);
673       glLoadMatrixf(mvmlocked);   683       glLoadMatrixf(mvmlocked);
674     }   684     }
675     break;   685     break;
676   // [Toggle Projection Method] O, P   686   // [Toggle Projection Method] O, P
677   case 'O': tgl_perspective = -1; ic2_LogKey(key); break;   687   case 'O': tgl_perspective = -1; ic2_LogKey(key); break;
678   case 'P': tgl_perspective = +1; ic2_LogKey(key); break;   688   case 'P': tgl_perspective = +1; ic2_LogKey(key); break;
679   689
680   // [Key Memory - Animation]   690   // [Key Memory - Animation]
681   case 'S':    691   case 'S': 
682     // リンクトリストの初期化   692     // リンクトリストの初期化
683     ic2_FreeKEYINPUTList(firstkeyinputptr);    693     ic2_FreeKEYINPUTList(firstkeyinputptr); 
684     firstkeyinputptr = NULL;   694     firstkeyinputptr = NULL;
685     latestkeyinputptr = NULL;   695     latestkeyinputptr = NULL;
686     tgl_keyinput = 1; // 記録開始   696     tgl_keyinput = 1; // 記録開始
687     ic2_NormalKeyInput('O', 0, 0); // 投影の初期化(直交投影)   697     ic2_NormalKeyInput('O', 0, 0); // 投影の初期化(直交投影)
688     ic2_NormalKeyInput('R', 0, 0); // MODELVIEW行列の初期化   698     ic2_NormalKeyInput('R', 0, 0); // MODELVIEW行列の初期化
689     printf("Start recording\n");    699     printf("Start recording\n"); 
690     break;   700     break;
691   case 'E':    701   case 'E': 
692     tgl_keyinput = -1;    702     tgl_keyinput = -1; // 記録終了
693     printf("End recording\n");    703     printf("End recording\n"); 
694     break;   704     break;
695   case 'A':    705   case 'A': 
696     ic2_PrintKEYINPUTList(firstkeyinputptr);    706     ic2_PrintKEYINPUTList(); 
      707     break;
      708   case 'G':
      709     tgl_keyinput = -1; // No recording while playing
      710     tgl_playing = 1; // Now playing!
      711     printf("Start playing (interval = %d[ms]\n", playinterval); 
      712     // 最初のアニメーション描画
      713     glutTimerFunc(playinterval, ic2_timerhandler, 0);
697     break;   714     break;
698   }   715   }
699   716
700   // 次のメインループ(glutMainLoop)での繰り返し時に描画を要求   717   // 次のメインループ(glutMainLoop)での繰り返し時に描画を要求
701   glutPostWindowRedisplay(window_id);   718   glutPostWindowRedisplay(window_id);
702 }   719 }
703   720
704 // +----------------------------------------------------   721 // +----------------------------------------------------
705 // ウィンドウサイズの変更が生じたときの対策用関数   722 // ウィンドウサイズの変更が生じたときの対策用関数
706 // +----------------------------------------------------   723 // +----------------------------------------------------
707 // glutReshapeFunc()にて登録   724 // glutReshapeFunc()にて登録
708 void ic2_ReshapeWindow (int w, int h) {   725 void ic2_ReshapeWindow (int w, int h) {
709   726
710   // 新しいウィンドウサイズを大域変数にセット   727   // 新しいウィンドウサイズを大域変数にセット
711   window_w = w; window_h = h;   728   window_w = w; window_h = h;
712   729
713   // 次のメインループ(glutMainLoop)での繰り返し時に描画を要求   730   // 次のメインループ(glutMainLoop)での繰り返し時に描画を要求
714   glutPostWindowRedisplay(window_id);   731   glutPostWindowRedisplay(window_id);
715 }   732 }
716   733
      734 // -----------------------------------------------------
      735 // キーインプット構造体(ic2KEYINPUT)リストの再生
      736 // -----------------------------------------------------
      737 void ic2_timerhandler(int keynumber){
      738   struct ic2KEYINPUT *p;
      739   int i = 0;
      740   
      741   printf("ic2_timerhandelr: ID = %4d ", keynumber);
      742   for (p = firstkeyinputptr; p != NULL; p = p->next) {
      743     if (i == keynumber) {
      744       printf(", key = '%c'\n", p->key);
      745       ic2_NormalKeyInput(p->key, 0, 0); // 指定番号のキーの再生
      746       if (p->next != NULL) {
      747         // 次の再生への準備(タイマーのセット)
      748         glutTimerFunc(playinterval, ic2_timerhandler, keynumber + 1);
      749       } else {
      750         // 再生終了
      751         printf("End playing\n"); 
      752         tgl_playing = -1;
      753       }
      754       return ;
      755     }
      756     i++;
      757   }
      758 }
      759
717 // +----------------------------------------------------   760 // +----------------------------------------------------
718 // OpenGLとしてのWindowの初期化   761 // OpenGLとしてのWindowの初期化
719 // +----------------------------------------------------   762 // +----------------------------------------------------
720 void ic2_BootWindow (char winname[]) {   763 void ic2_BootWindow (char winname[]) {
721   764
722   // ダブルバッファ,RGB表色モード,デプスバッファ を利用   765   // ダブルバッファ,RGB表色モード,デプスバッファ を利用
723   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);    766   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
724   767
725   // ウィンドウの大きさ   768   // ウィンドウの大きさ
726   glutInitWindowSize(window_w, window_h);   769   glutInitWindowSize(window_w, window_h);
727   770
728   // ウィンドウを開く   771   // ウィンドウを開く
729   window_id = glutCreateWindow(winname);   772   window_id = glutCreateWindow(winname);
730   773
731   // レンダリングにはSmooth Shadingを採用   774   // レンダリングにはSmooth Shadingを採用
732   glShadeModel(GL_SMOOTH);   775   glShadeModel(GL_SMOOTH);
733   776
734   // ウィンドウ全体を書き直すときの色(ここでは黒)   777   // ウィンドウ全体を書き直すときの色(ここでは黒)
735   glClearColor(0.0, 0.0, 0.0, 0.0);   778   glClearColor(0.0, 0.0, 0.0, 0.0);
736   779
737   // 初期MODELVIEW matrixの保護   780   // 初期MODELVIEW matrixの保護
738   glMatrixMode(GL_MODELVIEW);    781   glMatrixMode(GL_MODELVIEW); 
739   glPushMatrix(); // 以後本プログラムでは GL_MODELVIEW スタックの2層目以上で作業   782   glPushMatrix(); // 以後本プログラムでは GL_MODELVIEW スタックの2層目以上で作業
740   783
741   // Callback関数を設定 (イベント処理)   784   // Callback関数を設定 (イベント処理)
742   glutIdleFunc(ic2_DrawFrame); // 暇だったらフレームを描く(よい実装ではない)   785   glutIdleFunc(ic2_DrawFrame); // 暇だったらフレームを描く(よい実装ではない)
743   glutKeyboardFunc(ic2_NormalKeyInput); // キーが押されたときの対策   786   glutKeyboardFunc(ic2_NormalKeyInput); // キーが押されたときの対策
744   glutReshapeFunc(ic2_ReshapeWindow); // ウィンドウサイズ変更が検知されたときの対策   787   glutReshapeFunc(ic2_ReshapeWindow); // ウィンドウサイズ変更が検知されたときの対策
745 }   788 }
746   789
747 // ***********************************************************************    790 // *********************************************************************** 
748 // main  *****************************************************************   791 // main  *****************************************************************
749 // +----------------------------------------------------   792 // +----------------------------------------------------
750 // Main Function   793 // Main Function
751 // +----------------------------------------------------   794 // +----------------------------------------------------
752 int main (int argc, char *argv[]) {   795 int main (int argc, char *argv[]) {
753   int numberpatches = 0;   796   int numberpatches = 0;
754   797
755   // model ファイルの読み込み   798   // model ファイルの読み込み
756   if (argc <= 1) {   799   if (argc <= 1) {
757     printf("Error: no model file is specified.\n");   800     printf("Error: no model file is specified.\n");
758     return 1;   801     return 1;
759   }   802   }
760   numberpatches = ic2_ReadModel(argv[1], &firstpatchptr);   803   numberpatches = ic2_ReadModel(argv[1], &firstpatchptr);
761   if (numberpatches < 0) {   804   if (numberpatches < 0) {
762     printf("Error: invalid model \"%s\", reading failed.\n", argv[1]);   805     printf("Error: invalid model \"%s\", reading failed.\n", argv[1]);
763     return 1;   806     return 1;
764   }   807   }
765   printf("Number of Patches in the model = %d \n", numberpatches);   808   printf("Number of Patches in the model = %d \n", numberpatches);
766   809
767   // glutライブラリによる引数の解釈   810   // glutライブラリによる引数の解釈
768   glutInit(&argc, argv);   811   glutInit(&argc, argv);
769   812
770   // OpenGL Window の初期化   813   // OpenGL Window の初期化
771   ic2_BootWindow(argv[0]);   814   ic2_BootWindow(argv[0]);
772   815
773   // 無限ループの開始   816   // 無限ループの開始
774   glutMainLoop();   817   glutMainLoop();
775      818   
776   return 0;   819   return 0;
777 }   820 }

Generated by kameda[at]iit.tsukuba.ac.jp