質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

1609閲覧

OpenGLを用いて点を描画することでシュミレーション結果を可視化したい

muton

総合スコア31

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/05/28 10:46

編集2019/05/29 09:06

オープンソースコードのカーシュミレーションソフトにおいてある座標位置にOpenGLを用いて、点をシミュレーション画面上に描画したいと考えています。

初めにx座標=74,y座標=171,z座標=0に点を描画するプログラミングを以下の様に組みました。
しかし、ビルドは通るのですが、シミュレーション画面上に点が確認できません。
アドバイスを頂けると嬉しいです。

C++

1void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam) 2{ 3 glClear(GL_COLOR_BUFFER_BIT); 4 glColor3d(1.0, 0.0, 0.0); 5 glPointSize(500); 6 glBegin(GL_POINTS); 7 glVertex3d(74, 171, 0); 8 glEnd(); 9 glFlush(); 10

試したこと

1.チュートリアルを参考に、新しいプロジェクトを立ち上げ、二次元図形を描くことでOpenGLの理解を深めました。

2.シュミレーションゲームの背景の色を変更することはできました。

C++

1void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam) 2{ 3 glClear(GL_COLOR_BUFFER_BIT); 4 glClearColor(0.0, 0.0, 1.0, 1.0); 5

使用環境

GLUTによる「手抜き」OpenGL入門を参考にし、
GLUT を用いた OpenGLを使用しています。

GLUT を用いるためにfreeglut をコンパイルし、
freeglutd.lib, freeglut_staticd.lib,freeglutd.dll
glut.h freeglut.h freeglut_std.h freeglut_ext.h
を用いています。

windows8.1/visual studio2017/C++

解答用の画像

イメージ説明

現状

イメージ説明
イメージ説明
描画させたい箇所:赤い丸(コース上の位置座標:x座標=74,y座標=171,z座標=0)
現在実際に描画されている箇所:黄色い丸(背景??コース上ではない)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

点を描画しようとしている座標(74, 171, 0)というのは、もしかしてピクセル単位のスクリーン座標でしょうか。
描画時の変換行列が正しく設定されているかどうかが気になりますね。仮に描画領域が幅640ピクセル、高さ480ピクセル、原点を左上隅とすると、下記のようにした場合...

C++

1void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam) 2{ 3 glClear(GL_COLOR_BUFFER_BIT); 4 5 // プロジェクション行列は単位行列とする 6 glMatrixMode(GL_PROJECTION); 7 glLoadIdentity(); 8 9 // モデルビュー行列は上下反転、横0〜680・縦0〜480とする 10 glMatrixMode(GL_MODELVIEW); 11 glLoadIdentity(); 12 glScaled(1.0, -1.0, 1.0); 13 glOrtho( 14 0.0, 15 640.0, 16 0.0, 17 480.0, 18 -1.0, 19 1.0); 20 21 glColor3d(1.0, 0.0, 0.0); 22 glPointSize(500); 23 glBegin(GL_POINTS); 24 glVertex3d(74, 171, 0); 25 glEnd(); 26 glFlush(); 27}

下図のようになるでしょうか?
結果

追記
TORCSのall-in-oneをダウンロード、まずはサイトのWindows向けガイドに従ってビルドし(Windows 10 バージョン1803、Visual Studio Community 2019 バージョン16.0.3を使用したため、ソリューションを私の環境に合わせてアップグレード、ビルドを通すためいくつか泥縄的改修を加えました...過去のご投稿を拝見しますと、ご質問者さんもいろいろ工夫されたご様子ですね)、ひとまずそのままでちゃんと動くか確認したのち改造案を検討してみました。

glClearで全面を塗りつぶしてみると背景だけが塗られたり、点を描こうとすると前景に隠れてしまったり...といった現象があるとのことですが、見た感じgrDrawCarのタイミングでは車の描画は行われておらず、PLIBのSSGとかいう機能(これも初めて知りましたもので知識がなく、突っ込んだご質問は勘弁願います...)を使って構築された階層構造内の情報を更新しているだけのようです。
前景部分...つまりサーキットや車など諸々の3Dオブジェクト実際の描画はgrscreen.cppcGrScreen::camDraw末尾にあるgrDrawScene();が起点となっているようで、その内部ではssgCullAndDraw(TheScene);TheScenessgRootオブジェクトで、これがシーン上の3Dオブジェクトが所属するヒエラルキーの頂点にいるっぽいですね)によってシーン全体が描画されるように思われました。

SSGにはヒエラルキー上のエンティティが描画される前とか後のタイミングでコールバックを実行する機能があるようでしたので、それを使ってgrDrawCar内ではなくTheScene描画後のタイミングで追加描画を行った方がいいんじゃないか...と思い、下記のようにしてみました(TheScene描画後にはさらに反射?やダッシュボードのようなUI類の描画が入るようですが、ダッシュボードよりは奥に描画された方がよさそうということと、反射の後に追加描画を仕込むのは面倒そうという理由から、手軽にアクセスできるTheSceneを選びました)。

grcar.cpp

C++

1/*************************************************************************** 2 3 file : grcar.cpp 4 created : Mon Aug 21 18:24:02 CEST 2000 5 copyright : (C) 2000 by Eric Espie 6 email : torcs@free.fr 7 version : $Id: grcar.cpp,v 1.42.2.9 2012/06/06 13:56:39 berniw Exp $ 8 9***************************************************************************/ 10 11/*************************************************************************** 12 * * 13 * This program is free software; you can redistribute it and/or modify * 14 * it under the terms of the GNU General Public License as published by * 15 * the Free Software Foundation; either version 2 of the License, or * 16 * (at your option) any later version. * 17 * * 18 ***************************************************************************/ 19 20// 省略 21 22// 後述のコールバックとして使用する関数を適当な位置に用意する 23int drawMarker(ssgEntity *entity, int traversal_mask) { 24 // まずアトリビュートを保存 25 glPushAttrib(GL_ALL_ATTRIB_BITS); 26 27 // 各種設定を適宜無効化(または使用したい機能があれば有効化) 28 glDisable(GL_CULL_FACE); 29 glDisable(GL_TEXTURE_2D); 30 glDisable(GL_LIGHTING); 31 glDisable(GL_DEPTH_TEST); 32 33 // 点を描画 34 // パースペクティブ行列はこの時点ですでに適正に設定されているでしょうから操作せず、 35 // モデルビュー行列もワールド空間をメインカメラでとらえるような形になっていると思いますので 36 // gluLookAtなどを駆使して調整してやる必要はなさそうです 37 glColor3d(1.0, 0.0, 0.0); 38 glPointSize(60); 39 glBegin(GL_POINTS); 40 glVertex3d(602.849609, 1167.055908, 3.845393); // Forzaサーキットのスタート地点の座標はこの辺? 41 glEnd(); 42 43 // アトリビュートを復元 44 glPopAttrib(); 45 46 return TRUE; 47} 48 49void grDrawCar(tCarElt * car, tCarElt * curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera* curCam) 50{ 51 sgCoord wheelpos; 52 int index, i, j; 53 static float maxVel[3] = { 20.0, 40.0, 70.0 }; 54 float lod; 55 56 TRACE_GL("cggrDrawCar: start"); 57 58 // 省略 59 60 /* push the car at the end of the display order */ 61 CarsAnchorTmp->addKid(grCarInfo[index].carTransform); 62 CarsAnchor->removeKid(grCarInfo[index].carTransform); 63 CarsAnchor->addKid(grCarInfo[index].carTransform); 64 CarsAnchorTmp->removeKid(grCarInfo[index].carTransform); 65 66 // もしTheScene描画後のタイミングにまだコールバックが仕込まれていなければ... 67 if (!(TheScene->getTravCallback(SSG_CALLBACK_POSTTRAV))) { 68 // コールバックとしてdrawMarkerを仕込む 69 TheScene->setTravCallback(SSG_CALLBACK_POSTTRAV, drawMarker); 70 } 71 72 TRACE_GL("cggrDrawCar: end"); 73}

上記のようにしたところ、下図のように路上の地点を示す赤四角が現れました。すみませんが、上で申し上げたように手抜きして描画タイミングにTheScene描画後を選んだため、車の窓ガラス・テールランプなどの映り込みが四角の上に重ね描きされてしまいました。

結果1

せっかくですので、点以外も描いてみようと思ってdrawMarkerを下記のようにしたところ...

C++

1int drawMarker(ssgEntity *entity, int traversal_mask) { 2 // まずアトリビュートを保存 3 glPushAttrib(GL_ALL_ATTRIB_BITS); 4 5 // 表面材質その他を設定 6 static const GLfloat diffuse[] = {1.0, 0.0, 0.0, 1.0}; 7 static const GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; 8 glCullFace(GL_FRONT); 9 glDisable(GL_TEXTURE_2D); 10 glDisable(GL_COLOR_MATERIAL); 11 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, diffuse); 12 glMaterialfv(GL_FRONT, GL_SPECULAR, specular); 13 14 // 点を打つだけなら行列操作の必要はないでしょうが、 15 // 現在のモデルビュー行列にさらに変換を重ねる場合は 16 // 操作前の行列を保存しておくべきでしょう 17 glMatrixMode(GL_MODELVIEW); 18 glPushMatrix(); 19 20 // モデル原点をスタート地点付近に向きを合わせて据えて... 21 glTranslated(602.849609, 1167.055908, 3.845393); 22 glRotated(90, 1, 0, 0); 23 glRotated(90, 0, 1, 0); 24 glTranslated(0, 2, 0); 25 26 // ティーポットを描く 27 glutSolidTeapot(3); 28 29 // モデルビュー行列を復元 30 glPopMatrix(); 31 32 // アトリビュートを復元 33 glPopAttrib(); 34 35 return TRUE; 36}

下図のように路上にティーポットが現れました。もちろん物理的形状は持っていませんので、車は貫通してしまいますが...

結果2

おまけ
点のサイズを奥行きに反比例して変化させても面白いように思います。点の遠さを把握しやすくなるんじゃないでしょうか?

C++

1int drawMarker(ssgEntity *entity, int traversal_mask) { 2 glPushAttrib(GL_ALL_ATTRIB_BITS); 3 4 // デプステストを無効化しないでおくと 5 // 点より手前のオブジェクトによって点が隠れるようになる 6 glDisable(GL_CULL_FACE); 7 glDisable(GL_TEXTURE_2D); 8 glDisable(GL_LIGHTING); 9 10 // 現在のモデルビュー行列を取得 11 GLfloat mvMat[16]; 12 glGetFloatv(GL_MODELVIEW_MATRIX, mvMat); 13 14 // 描画先の座標を... 15 double worldX = 602.849609; 16 double worldY = 1167.055908; 17 double worldZ = 3.845393; 18 19 // Z成分だけでいいので、ビュー座標に変換する 20 // ついでに正負反転し、遠いほど大きい値になるようにする 21 double viewZ = -(mvMat[2] * worldX + mvMat[6] * worldY + mvMat[10] * worldZ + mvMat[14]); 22 23 // 奥行き10でサイズ50ピクセルになるものとすると... 24 double refPointSize = 50; 25 double refViewZ = 10; 26 27 // 距離の最小値を0.1としたら、点のサイズはこうなる 28 // ただし1ピクセル未満にはならないようにした 29 double pointSize = max((refPointSize * refViewZ) / max(viewZ, 0.1), 1); 30 31 glColor3d(1.0, 0.0, 0.0); 32 glPointSize((int)pointSize); 33 glBegin(GL_POINTS); 34 glVertex3d(worldX, worldY, worldZ); 35 glEnd(); 36 37 glPopAttrib(); 38 39 return TRUE; 40}

結果3

投稿2019/05/28 12:43

編集2019/05/31 15:21
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

muton

2019/05/29 04:09

回答ありがとうございます。 説明不足で申し訳ございません。スクリーン座標ではなく、カーレースにおける車の位置座標のことを想定しています。 提示頂いたコードをビルドしてみると、質問欄に追加した画像の様に 背景が黒に(glClear(GL_COLOR_BUFFER_BIT)の影響) 画面左に黒い四角形が描画されました。 宜しくお願い致します。
muton

2019/05/29 06:53

追記 以下のコードを書くことで、点を確認することができました。 しかし、質問欄に追記した通り、その点はコース上ではなく、背景の位置に描画されているようです。コース上に描画するためにはどうすれば良いでしょうか。 if(/*car->myCoordsVector*/true) { glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(curCam->getFovY(), 2, .005, 100000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); t3Dd *pos = curCam->getPos(); t3Dd *center = curCam->getCenter(); t3Dd *upv = curCam->getUp(); gluLookAt(pos->x, pos->y, pos->z, center->x, center->y, center->z, upv->x, upv->y, upv->z); glColor3d(1.0, 0.0, 0.0); glPointSize(60); glBegin(GL_POINTS); glVertex3d(74, 171, 100); glEnd(); glPopMatrix(); glPopAttrib(); }
Bongo

2019/05/29 08:44

ご質問者さんのおっしゃるカーシミュレーションソフトというのはTORCS ( http://torcs.sourceforge.net/index.php )でいいでしょうか? 私はこのソフトを初めて知りまして、具体的なアドバイスを差し上げるには時間がかかるかと思います。ご容赦ください... ご質問者さんの目指していることについておうかがいしますが、ご提示のスクリーンショット右上のミニマップ上に車を表すドットを描画したいということでしょうか。 ですが、今は手元に開発用PCがなくてダウンロードはしておらずサイトの情報をいくらか眺めてみただけなのですが、このソフトにはすでにミニマップ描画機能が備わっており、実際にご質問者さんの現状画面でもちゃんと車の位置に応じてミニマップのコース上を赤い点が動いているように見えます。それではダメだということでしょうか? 理想的にはこのように描画したい...といったことを図で(現状画面の上にペイントソフトで描き込むなど)ご説明いただけますと参考になりそうです。
muton

2019/05/29 09:11

回答ありがとうございます。 説明不足で申し訳ございません。 提示いただいたURLのTORCSで間違いないです。 デフォルトで、ミニマップ上に車を表す描画機能はついています。 追記に示した通り、赤い丸で示す位置(コース上)に点を描画したいということになります。 何度も申し訳ございません。宜しくお願い致します。
Bongo

2019/05/30 09:30

なるほど誤解していました。地平線の向こうで動いている赤黒い四角が描画した点だったんですね... `(74, 171, 0)`というのはサーキット空間(ワールド空間?)内の一点を表していて、そこに描画することでサーキットの路上に赤い点が置いてあるように見せたいというわけですね。 TORCSをダウンロードしていじってみた結果を追記しましたが、ご参考になりそうでしょうか?
muton

2019/06/14 08:00

ご丁寧な回答感謝いたします。 教えていただいたことを基に、試行錯誤を行った結果、やりたいことができました。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問