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

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

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

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

C++

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

Q&A

解決済

1回答

3859閲覧

OpenGLで行列モード変換について

hikar

総合スコア13

OpenGL

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

C++

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

0グッド

0クリップ

投稿2020/02/09 01:15

編集2020/02/09 05:38

いつも暖かいご返答ありがとうございます。<(_ _)>
また、質問させていただきます。
Yutuberゲーム道館さんの「OpenGL道場 第4回「2D変換」」を参考にさせていただいています。
OpenGLの行列変換で、いくら調べても納得がいかない点があったので、質問させていただきます。

glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D( 0, // GLdouble left windowWidth, // GLdouble right windowHeight, // GLdouble bottom 0); // GLdouble top glMatrixMode(GL_MODELVIEW); glLoadIdentity();

まずこちらのソースコードですが、

「glMatrixMode(GL_PROJECTION)」で行列を射影行列に設定する。
上の関数は正射影、投視射影を計算できるよう専用の行列をモデル(glutWireTeapot()使用)の行列に設定しているのでしょうか?

そして「glLoadIdentity()」で設定した行列を単位行列に設定する。
そして「gluOrtho2D()」で座標系を左上が(0,0)、左下が(0,1)、右上が(1,0)のように設定。

なぜglLoadIdent()を使用し単位行列を設定しなければいけないのでしょうか?
(コメントにした場合、モデルが消えてしまいました。)

gluOrtho2D()で座標系を設定するだけならgluOrtho2D()を書かなくてもよくない?と考え、コメントにしてみたらモデルが消えました!
なぜモデルが消えてしまったのでしょうか?
gluOrtho2D()は座標系設定以外にも他に何か意味があるのでしょうか?
ちなみに、こちらの手抜きOpenGLを拝見させていたでき、こちらで扱っている座標系とは、X,Y,Z 軸のことだと勝手に解釈させていただきました。<(_ )>
そして最後に「glMatrixMode(GL_MODELVIEW)」関数を使いわざわざモデルビュー行列に設定しているのでしょうか?
どなたかわかる方、どうか教えてください。<(
_)>

全体のソースコードです。

OpenGL

1#include "glut.h" 2#include <stdio.h> 3 4int windowWidth = 800; 5int windowHeight = 800; 6 7 8void display(void) { 9 glClear(GL_COLOR_BUFFER_BIT);//GLbitfield mask:画面の色情報をクリア 10 11 glMatrixMode(GL_PROJECTION); 12 glLoadIdentity(); 13 gluOrtho2D( 14 0, // GLdouble left 15 windowWidth, // GLdouble right 16 windowHeight, // GLdouble bottom 17 0); // GLdouble top 18 19 glMatrixMode(GL_MODELVIEW); 20 glLoadIdentity(); 21 22 glTranslatef(windowWidth/2,windowHeight/2,0); 23 24 static float angle; 25 angle += 1; 26 glRotatef( 27 angle, // GLfloat angle:回転度 28 0,0,1); // GLfloat x, y, z:回転軸 29 30 glScalef(256, 256, 1); 31 glutWireTeapot(1); 32 glFlush(); 33 //glutSwapBuffers(); 34} 35 36void timer(int value) { 37 glutPostRedisplay();//この関数を呼び出せばOpenGLに再描画が必要であると訴えれる 38 39 glutTimerFunc( // 一定時間が経過するとコールバック関数を呼び出す 40 1000/60, // unsigned int millis 41 timer, // void (GLUTCALLBACK *func)(int value) 42 0); // int value 43} 44 45void Reshape(int width, int height) { 46 printf("reshape: width:%d heigh:%d\n", width, height); 47 48 glViewport( 49 0, 0,//GLint x, y 50 width, height);//width, height 51 52 windowHeight = height; 53 windowWidth = width; 54} 55 56int main(int argc, char* argv[]) { 57 glutInit(//ウィンドウを表示させるため、GLUTを初期化 58 &argc, 59 argv); 60 //glutInitDisplayMode(GL_DOUBLE);//unsigned int mode 61 glutInitWindowPosition(0,0); 62 glutInitWindowSize(windowWidth, windowHeight); 63 glutCreateWindow("Title"); 64 glutDisplayFunc(display);//void (GLUTCALLBACK *func)(void) 65 glutTimerFunc( // 一定時間が経過するとコールバック関数を呼び出す 66 1000/60, // unsigned int millis 67 timer, // void (GLUTCALLBACK *func)(int value) 68 0); // int value 69 glutReshapeFunc(Reshape);// ウィンドウのサイズが変わった際に呼び出される 70 glutMainLoop(); 71}

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

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

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

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

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

guest

回答1

0

ベストアンサー

マトリクスモードについては「GL_MODELVIEW GL_PROJECTION」あたりでググってください.
ざっくり言うと,ある3次元座標をどこか(視点)から見た景色を最終的に画像に投影する処理を
画像上座標 = 変換行列*3次元座標
とするとき,OpenGLではこの変換行列を,利便性のために2つのマトリクスの積として扱っている感じです.
画像上座標 = (行列A*行列B)*3次元座標みたいな.
で,どっち側の行列をいじくりまわしたいのか?を指定するのがglMatrixModeです.

なぜglLoadIdent()を使用し単位行列を設定しなければいけないのでしょうか?

gluOrtho2Dのような関数が,「マトリクスの現内容に,計算結果を乗じる」という処理をおこなうからです.
マトリクスの内容を,gluOrtho2Dで計算される「乗じる」内容そのものに更新するために,先に「マトリクスの現内容」をglLoadIdentityで単位行列にしているわけです.

投稿2020/02/10 01:21

fana

総合スコア11656

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

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

hikar

2020/02/10 03:49

ご返答ありがとうございます。(>_<) なんとなく内容をつかめた気がします。 独学で行列を勉強してみましたが、ざっくりとしか内容はつかめていませんが、 gluOrth2Dを使う際にglLoadIdentity()関数を使用しなければマトリックスの現内容にgluOrth2Dで計算した行列?を掛けてしまうため、表示される内容が、思っていたものと異なってしまうということでしょうか? そこで、glLoadIdentity()を使用し現内容を単位行列(単位行列に何を掛けても計算結果はかけたものになる AE=A、E=単位行列 ,A=gluOrth2Dの計算結果)に設定すれば、マトリクスの内容が上のソースコードでいう、座標系が記述した通りに変更されるということでしょうか? 質問攻めになってしまいますが、どうかよろしくお願いします。<(_ _)>
fana

2020/02/10 04:15

関数display()は何度も実行されるでしょうから,glLoadIdentity()を無くしてしまうと毎度行われるgluOrtho2D()によってマトリクスは謎の内容になってしまうでしょう. > AE=A OpenGLだとおそらく EA=A の側かな(Aを右から掛ける),と思いますが,まぁそういう話です. 例えば,このコードのGL_MODELVIEW側の行列を見ると,コードは glLoadIdentity()→glTranslatef()→glRotatef()→glScalef()の順で書かれていますので, まず行列は E になり,そこに平行移動の行列Tが右から掛けられ(この時点で行列はTになる),さらに回転の行列Rが右から掛けられ(TR),さらに拡大の行列Sが右から掛けられるので,行列は TRS になるわけです. (この行列による変換は「変換結果=T*R*S*変換前」という形になります(最後に書いたやつほど変換としては先に作用する))
hikar

2020/02/10 15:07

ご返答ありがとうございます。(>_<) とてもわかりやすく、完全に理解できました。 またわからないことがあったら質問させていただきます。 よろしくお願いします。<(_ _)>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問