MITOUJTAG 3Dのプログラム解析
昔いたアルバイトさんが作ったプログラムを解析しています。
まず、この部分。
MJ3D_Initという関数は、3Dビューのウィンドウが開くたびに呼び出される関数なのですが、
renderer_ptr ptr = new Renderer(w);
ということをしています。
Rendererというクラスがあるのは良いのですが、なぜ、わざわざtypedefでポインタ型のクラスを作るのか?うーん。わからない。
Rederer * ptr = new Renderer(w);
C#とかJavascriptとかでは基本的にクラスオブジェクトの実体ではなくポインタで扱うから、そのような感覚でプログラミングがしたかったのかもしれません。
このmap<int, renderer_ptr>というのは、idに対してRendererのポインタを返す連想配列を作っています。MITOUJTAGではたくさんの3Dビューが開くので、そのウィンドウごとにidという数字が割り当てられるのですが、その数字に対応したRendererのポインタを得たいのでしょう。
このプログラムを解析して知りたいことは、たくさんの3Dビューが開くプログラムをOpenGLでどうやって作るか。また、glutやglfwとの関係はどうなっているのかということです。
では、Rendererクラスの中を見ていきましょう。
あああ・・・😢
ヘッダファイルの中にメソッドを書きまくっています。
最近のコーディングスタイルなんでしょうかねぇ。ヘッダは宣言だけにしてCPPに本体を書くというやり方は古いのかもしれません。
さて、Rendererの引数に与えられたwというのは、表示したいウィンドウのハンドルです。MITOUJTAGはBorland C++で作られていて、それぞれのMDI子ウィンドウはTFrameというクラスの仕組みを使って描画しています。このwにはTFrameのHandleを渡しています。
hDC = GetDC(w);
auto pfdID = ChoosePixelFormat(hDC, &pfd);
で、TFrameのハンドルからGetDCをしてピクセルフォーマットを得ています。これが何をしているかはこのページに解説がありました。ふむふむ。おまじないのようなものですね。
ここではautoが使われていますが、中身はintです。
次に
hGLRC = wglCreateContext(hDC);
if (hGLRC == NULL) { exit(1); }
wglMakeCurrent(hDC, hGLRC);
詳しいことはわかりませんが、TFrameのHandleから作ったhDCを元にhGLRCを作っています。その後でライトの設定とかテクスチャの読み込みとか(テクスチャのファイルが開発者のPCのフォルダ構成に依存していた😞)を行っていました。
つまり、3Dのビューが開くたびにOpenGLのコンテキストを作っていて共有するとかはしていないようです。
で、RendererクラスにはRenderというメソッドがあって、呼び出されると、
glClearした後で
devices[i]->DrawDevice();
をしています。このDrawDeviceの中身は
です。 このobjという中にデバイスを描画するための座標やら色のデータが入っていて、それをここで描き出しています。
全貌が見えてきました。
JTAGデバイスが追加されると、objというオブジェクトの中にポリゴンの座標データが大量にぶちこまれ、それがRender関数の呼び出し時に描画されるという仕組みのようです。
3Dのグラフィックで言ういわゆる「シーン」というのはobjというクラスの中に全部入っていて、Render関数が呼び出されたときにfor文で全部をなめるようにして描いているようです。
| 固定リンク
コメント