回答編集履歴

2

点のサイズを変化させたパターンを追記

2019/05/31 15:21

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -331,3 +331,95 @@
331
331
 
332
332
 
333
333
  ![結果2](19dd9988b6e699871961e625f6e9294e.gif)
334
+
335
+
336
+
337
+ **おまけ**
338
+
339
+ 点のサイズを奥行きに反比例して変化させても面白いように思います。点の遠さを把握しやすくなるんじゃないでしょうか?
340
+
341
+ ```C++
342
+
343
+ int drawMarker(ssgEntity *entity, int traversal_mask) {
344
+
345
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
346
+
347
+
348
+
349
+ // デプステストを無効化しないでおくと
350
+
351
+ // 点より手前のオブジェクトによって点が隠れるようになる
352
+
353
+ glDisable(GL_CULL_FACE);
354
+
355
+ glDisable(GL_TEXTURE_2D);
356
+
357
+ glDisable(GL_LIGHTING);
358
+
359
+
360
+
361
+ // 現在のモデルビュー行列を取得
362
+
363
+ GLfloat mvMat[16];
364
+
365
+ glGetFloatv(GL_MODELVIEW_MATRIX, mvMat);
366
+
367
+
368
+
369
+ // 描画先の座標を...
370
+
371
+ double worldX = 602.849609;
372
+
373
+ double worldY = 1167.055908;
374
+
375
+ double worldZ = 3.845393;
376
+
377
+
378
+
379
+ // Z成分だけでいいので、ビュー座標に変換する
380
+
381
+ // ついでに正負反転し、遠いほど大きい値になるようにする
382
+
383
+ double viewZ = -(mvMat[2] * worldX + mvMat[6] * worldY + mvMat[10] * worldZ + mvMat[14]);
384
+
385
+
386
+
387
+ // 奥行き10でサイズ50ピクセルになるものとすると...
388
+
389
+ double refPointSize = 50;
390
+
391
+ double refViewZ = 10;
392
+
393
+
394
+
395
+ // 距離の最小値を0.1としたら、点のサイズはこうなる
396
+
397
+ // ただし1ピクセル未満にはならないようにした
398
+
399
+ double pointSize = max((refPointSize * refViewZ) / max(viewZ, 0.1), 1);
400
+
401
+
402
+
403
+ glColor3d(1.0, 0.0, 0.0);
404
+
405
+ glPointSize((int)pointSize);
406
+
407
+ glBegin(GL_POINTS);
408
+
409
+ glVertex3d(worldX, worldY, worldZ);
410
+
411
+ glEnd();
412
+
413
+
414
+
415
+ glPopAttrib();
416
+
417
+
418
+
419
+ return TRUE;
420
+
421
+ }
422
+
423
+ ```
424
+
425
+ ![結果3](ee65fa7a6e955994edc47f51ae6af1e2.gif)

1

改造案を追記

2019/05/31 15:21

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -63,3 +63,271 @@
63
63
  下図のようになるでしょうか?
64
64
 
65
65
  ![結果](3ae18ac5991dcea4d89c83093bd7fe0c.png)
66
+
67
+
68
+
69
+ **追記**
70
+
71
+ TORCSのall-in-oneをダウンロード、まずはサイトのWindows向けガイドに従ってビルドし(Windows 10 バージョン1803、Visual Studio Community 2019 バージョン16.0.3を使用したため、ソリューションを私の環境に合わせてアップグレード、ビルドを通すためいくつか泥縄的改修を加えました...過去のご投稿を拝見しますと、ご質問者さんもいろいろ工夫されたご様子ですね)、ひとまずそのままでちゃんと動くか確認したのち改造案を検討してみました。
72
+
73
+
74
+
75
+ `glClear`で全面を塗りつぶしてみると背景だけが塗られたり、点を描こうとすると前景に隠れてしまったり...といった現象があるとのことですが、見た感じ`grDrawCar`のタイミングでは車の描画は行われておらず、[PLIBのSSGとかいう機能](http://plib.sourceforge.net/ssg/index.html)(これも初めて知りましたもので知識がなく、突っ込んだご質問は勘弁願います...)を使って構築された階層構造内の情報を更新しているだけのようです。
76
+
77
+ 前景部分...つまりサーキットや車など諸々の3Dオブジェクト実際の描画は`grscreen.cpp`の`cGrScreen::camDraw`末尾にある`grDrawScene();`が起点となっているようで、その内部では`ssgCullAndDraw(TheScene);`(`TheScene`は`ssgRoot`オブジェクトで、これがシーン上の3Dオブジェクトが所属するヒエラルキーの頂点にいるっぽいですね)によってシーン全体が描画されるように思われました。
78
+
79
+
80
+
81
+ SSGにはヒエラルキー上のエンティティが描画される前とか後のタイミングでコールバックを実行する機能があるようでしたので、それを使って`grDrawCar`内ではなく`TheScene`描画後のタイミングで追加描画を行った方がいいんじゃないか...と思い、下記のようにしてみました(`TheScene`描画後にはさらに反射?やダッシュボードのようなUI類の描画が入るようですが、ダッシュボードよりは奥に描画された方がよさそうということと、反射の後に追加描画を仕込むのは面倒そうという理由から、手軽にアクセスできる`TheScene`を選びました)。
82
+
83
+
84
+
85
+ **grcar.cpp**
86
+
87
+ ```C++
88
+
89
+ /***************************************************************************
90
+
91
+
92
+
93
+ file : grcar.cpp
94
+
95
+ created : Mon Aug 21 18:24:02 CEST 2000
96
+
97
+ copyright : (C) 2000 by Eric Espie
98
+
99
+ email : torcs@free.fr
100
+
101
+ version : $Id: grcar.cpp,v 1.42.2.9 2012/06/06 13:56:39 berniw Exp $
102
+
103
+
104
+
105
+ ***************************************************************************/
106
+
107
+
108
+
109
+ /***************************************************************************
110
+
111
+ * *
112
+
113
+ * This program is free software; you can redistribute it and/or modify *
114
+
115
+ * it under the terms of the GNU General Public License as published by *
116
+
117
+ * the Free Software Foundation; either version 2 of the License, or *
118
+
119
+ * (at your option) any later version. *
120
+
121
+ * *
122
+
123
+ ***************************************************************************/
124
+
125
+
126
+
127
+ // 省略
128
+
129
+
130
+
131
+ // 後述のコールバックとして使用する関数を適当な位置に用意する
132
+
133
+ int drawMarker(ssgEntity *entity, int traversal_mask) {
134
+
135
+ // まずアトリビュートを保存
136
+
137
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
138
+
139
+
140
+
141
+ // 各種設定を適宜無効化(または使用したい機能があれば有効化)
142
+
143
+ glDisable(GL_CULL_FACE);
144
+
145
+ glDisable(GL_TEXTURE_2D);
146
+
147
+ glDisable(GL_LIGHTING);
148
+
149
+ glDisable(GL_DEPTH_TEST);
150
+
151
+
152
+
153
+ // 点を描画
154
+
155
+ // パースペクティブ行列はこの時点ですでに適正に設定されているでしょうから操作せず、
156
+
157
+ // モデルビュー行列もワールド空間をメインカメラでとらえるような形になっていると思いますので
158
+
159
+ // gluLookAtなどを駆使して調整してやる必要はなさそうです
160
+
161
+ glColor3d(1.0, 0.0, 0.0);
162
+
163
+ glPointSize(60);
164
+
165
+ glBegin(GL_POINTS);
166
+
167
+ glVertex3d(602.849609, 1167.055908, 3.845393); // Forzaサーキットのスタート地点の座標はこの辺?
168
+
169
+ glEnd();
170
+
171
+
172
+
173
+ // アトリビュートを復元
174
+
175
+ glPopAttrib();
176
+
177
+
178
+
179
+ return TRUE;
180
+
181
+ }
182
+
183
+
184
+
185
+ void grDrawCar(tCarElt * car, tCarElt * curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera* curCam)
186
+
187
+ {
188
+
189
+ sgCoord wheelpos;
190
+
191
+ int index, i, j;
192
+
193
+ static float maxVel[3] = { 20.0, 40.0, 70.0 };
194
+
195
+ float lod;
196
+
197
+
198
+
199
+ TRACE_GL("cggrDrawCar: start");
200
+
201
+
202
+
203
+ // 省略
204
+
205
+
206
+
207
+ /* push the car at the end of the display order */
208
+
209
+ CarsAnchorTmp->addKid(grCarInfo[index].carTransform);
210
+
211
+ CarsAnchor->removeKid(grCarInfo[index].carTransform);
212
+
213
+ CarsAnchor->addKid(grCarInfo[index].carTransform);
214
+
215
+ CarsAnchorTmp->removeKid(grCarInfo[index].carTransform);
216
+
217
+
218
+
219
+ // もしTheScene描画後のタイミングにまだコールバックが仕込まれていなければ...
220
+
221
+ if (!(TheScene->getTravCallback(SSG_CALLBACK_POSTTRAV))) {
222
+
223
+ // コールバックとしてdrawMarkerを仕込む
224
+
225
+ TheScene->setTravCallback(SSG_CALLBACK_POSTTRAV, drawMarker);
226
+
227
+ }
228
+
229
+
230
+
231
+ TRACE_GL("cggrDrawCar: end");
232
+
233
+ }
234
+
235
+ ```
236
+
237
+
238
+
239
+ 上記のようにしたところ、下図のように路上の地点を示す赤四角が現れました。すみませんが、上で申し上げたように手抜きして描画タイミングに`TheScene`描画後を選んだため、車の窓ガラス・テールランプなどの映り込みが四角の上に重ね描きされてしまいました。
240
+
241
+
242
+
243
+ ![結果1](7f5579649117390c2a697d2939431d2f.gif)
244
+
245
+
246
+
247
+ せっかくですので、点以外も描いてみようと思って`drawMarker`を下記のようにしたところ...
248
+
249
+
250
+
251
+ ```C++
252
+
253
+ int drawMarker(ssgEntity *entity, int traversal_mask) {
254
+
255
+ // まずアトリビュートを保存
256
+
257
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
258
+
259
+
260
+
261
+ // 表面材質その他を設定
262
+
263
+ static const GLfloat diffuse[] = {1.0, 0.0, 0.0, 1.0};
264
+
265
+ static const GLfloat specular[] = {1.0, 1.0, 1.0, 1.0};
266
+
267
+ glCullFace(GL_FRONT);
268
+
269
+ glDisable(GL_TEXTURE_2D);
270
+
271
+ glDisable(GL_COLOR_MATERIAL);
272
+
273
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, diffuse);
274
+
275
+ glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
276
+
277
+
278
+
279
+ // 点を打つだけなら行列操作の必要はないでしょうが、
280
+
281
+ // 現在のモデルビュー行列にさらに変換を重ねる場合は
282
+
283
+ // 操作前の行列を保存しておくべきでしょう
284
+
285
+ glMatrixMode(GL_MODELVIEW);
286
+
287
+ glPushMatrix();
288
+
289
+
290
+
291
+ // モデル原点をスタート地点付近に向きを合わせて据えて...
292
+
293
+ glTranslated(602.849609, 1167.055908, 3.845393);
294
+
295
+ glRotated(90, 1, 0, 0);
296
+
297
+ glRotated(90, 0, 1, 0);
298
+
299
+ glTranslated(0, 2, 0);
300
+
301
+
302
+
303
+ // ティーポットを描く
304
+
305
+ glutSolidTeapot(3);
306
+
307
+
308
+
309
+ // モデルビュー行列を復元
310
+
311
+ glPopMatrix();
312
+
313
+
314
+
315
+ // アトリビュートを復元
316
+
317
+ glPopAttrib();
318
+
319
+
320
+
321
+ return TRUE;
322
+
323
+ }
324
+
325
+ ```
326
+
327
+
328
+
329
+ 下図のように路上にティーポットが現れました。もちろん物理的形状は持っていませんので、車は貫通してしまいますが...
330
+
331
+
332
+
333
+ ![結果2](19dd9988b6e699871961e625f6e9294e.gif)