subtitle
さて、先月までの2ヶ月間は五十子さんにCGアーティストとIndyの初々しい恋愛について御講釈願いました。今月からはいよいよプログラマとIndyの背徳の関係について語ることにしましょう。背徳というのはナンセンスですが、ここにきて、Indyをめぐるプログラミングの状況は、インターネットという怪物の出現によって、ただ単なるUNIXの一変種のマシンの問題では治まらなくなってきました。
OpenGLやVRMLは今やプログラマのみならず、多くのインターネットユーザの関心を集める技術の1つです。これらの技術がSGIの技術をベースにしたものであることは、再三再四お話してきました。すなわちIndyで使われているプログラム技術が、現在のコンピューティング技術の牽引役を果たしているのです。ですから、これからもますますインターネット指向を強めているIndyの新技術をウォッチングしていくことが、これからのネットワーク時代を先取りする最善策の1つといえるかもしれません(ちょっと言い過ぎか)。
そして、プログラマであれば1度は、あのSGIのマシンのプログラムをやってみたい、3次元のオブジェクトをグリグリしたり、美女がライオンにモーフィングするようなプログラムを描いてみたいと思ったことがあるでしょう。これからプログラムでも覚えようかという奇特な、いや無知で命知らずな若者も、多くがSGIマシーンに見せられているはずです。
Indyでプログラムするといっても、もちろん誰でもがプログラムしなければならない訳ではありません。プログラムする必要もないし、全く興味がないという人が大多数かもしれません。しかし、インターネットのユーザならかなりの割合で3次元グラフィックスのプログラミングに興味を持ってくれるのではないでしょうか。HTMLを自分で書いてWWWのホームページを作った人がごまんと(50万人かもしれない)いる昨今です。HTMLはプログラムではないといわれるかもしれませんが、私は、意味のある整合性のとれたスクリプトを書くという点では、似たようなものでないかと思っています。だから、職業プログラマではないけれど、VRMLのような3次元仮想空間を作ってスゴイことをしたいと考えている元気のいいナイスガイがいても不思議ではないでしょう。
それで今月は、Indyのプログラミング環境というのはどんなものか、どんなツールがそろっているのか、といったことを説明したいと思います。今はC++でプログラムするのがIndyの標準的なプログラムですが、3ヶ月も経てば、JavaするのがIndyのプログラマの主流になっているかも知れません。プログラムの実践は来々月ぐらいから始めようかと考えていますが、もしそうなっていたら、迷わずJavaしましょう。
subtitle
GL(Graphics Libraryとは、なんて安直で傲慢な名前でしょうか)は、SGIのワークステーション(IRISシリーズ)で昔からサポートされているプロパーなグラフィックスライブラリです。OpenGLが出た今でも、昔からのオリジナルライブラリの資産があるために、なかなかGLから離れられないプログラマや会社も多いようです。
それでは、GLのプログラムとはどんなものでしょうか。百聞は一見にしかず、ということでサンプルプログラムを見てみましょう。もちろんC言語の知識は必要となりますが、C言語を知らなくても何等かのプログラム言語を知っている人ならなんとなく理解できるかもしれません。
これが最もシンプルなGLのプログラムだ!!
#includeshort v1[3] = {100, 100, 0}; /* 左下の頂点 */ long v2[2] = {100, 200}; /* 左上の頂点 */ float v3[2] = {200.0, 200.0}; /* 右上の頂点 */ double v4[3] = {200.0, 100.0, 0.0}; /* 右下の頂点 */ main() { /* 初期設定 */ prefsize(500, 500); winopen("Square"); ortho2(0.5, 500.5, 0.5, 500.5); /* 画面をクリア */ color(WHITE); clear(); /* 正方形を描画 */ color(RED); bgnline(); /* ラインの描画開始 */ v2s(v1); /* 左下の頂点を設定 shortデータ */ v2i(v2); /* 左上の頂点を設定 longデータ */ v2f(v3); /* 右上の頂点を設定 floatデータ */ v3d(v4); /* 右下の頂点を設定 doubleデータ */ v3s(v1); endline(); /* ラインの描画の終了 */ sleep(10); /* 10秒間表示 */ gexit(); }
prefsize()でウインドウのサイズを設定してwinopen()でウインドウを開きます。orhto2()はウインドウの(左、右、下、上)の座標値をマッピングします。どういうことかといいますと、ウインドウの左下の座標が、(0.5, 0.5)で、右上の座標が(500.5, 500.5)になるということです。何で(0, 0)ではなくて(0.5, 0.5)かという点については、皆さんの宿題としておきましょう。このプログラムが、赤い正方形を描くプログラムではないかなというのは想像できると思います。
しかし、ちょっと不可解なのは、頂点のデータが、2次元の座標あり、3次元の座標あり、また、shortありlongありfloat、doubleありで、ほんまにこれでええんかいな、という感じです。いいのです。GLの幾何学図形は内部的には全て3次元で処理しており、また実数値で処理しているので、こんな芸当ができるのです。
subtitle
まあ、消えゆく運命にあるGLについてこれ以上説明しても紙面の無駄でしょうから、今をときめくOpenGLについて、ちょっとだけ見てみます。ちょっとだけというのは、本誌でもOpenGLの連載を始めようかという動きがあるようです。OpenGLについてより深く知りたい輩はそっちを参考にしてください。Indyといっしょ -プログラマ編ではOpenGLは捨てて、その上のOpen InventorやRapidAppなどの高度なツールキットに焦点を当てて行きたいと思っています。
マイクロソフトがOpenGLを採用して以来、OpenGLのプログラミングの話題が非常にホットになってきました。それは出版される書籍にも見て取れ、OpenGL関係の書籍が何冊も出版されています。
ところで、私は、OpenGLのことを「3Dグラフィックスのアセンブラ」だと捉えています。3Dのツールやアプリケーションを作るのにOpenGLが最適かというと、そうともいえないと思います。 まあ、立方体を表示させてマウスで回転させるぐらいのプログラムなら、慣れていれば数十分、慣れていなければ数日かかるかもしれません。しかし、ウォークスルーのプログラムといったら、OpenGLで開発するのは、プロトタイプでさえ数ヶ月はかかる結構きつい作業になるでしょう。それは、OpenGLがサポートする関数が、アプリケーションレベルから見るとかなり下層レベルの機能しかサポートしていないためです。
OpenGLは、何をやるにも多くのコードを書かなければなりません。OpenGLができることは、ポリゴンを描画したり、光源の設定をしたりといった、あくまでも描画レベルのインターフェイスです。これに対してOpen Inventorの方は、描画からアプリケーションレベルのオペレーションまでを含んだ高度なグラフィックスのインターフェイスです。具体的には、一般的な3次元グラフィックスアプリケーションが必要とする3次元オブジェクトのデータ構造や、そのデータ操作の方法などのインターフェイスまでも提供しています。 しまった、OpenGLのことを語るところなのでOpenGLに話しを戻しましょう。
OpenGLは、GLからIRISに依存する部分を削除して、マルチベンダに対応できるようにしたAPIです。SunのマシンやもちろんWindows NT/95でもOpenGLはサポートされています。確かOS/2版も存在します。Machintosh版やPC UNIX向けには、OpenGLもどきがあるようです。特にPC UNIXが流行っている昨今では、OpenGL互換ライブラリのMesaはLinixユーザなどから注目を集めているようです。Solaris 2.4 for x86を私も使用していますが、Sloaris 2.5からMotif環境が標準で付いてくるので、このMesaを試してみようかと思っています。
それではOpenGLがどんな機能を持っているか簡単にまとめましょう
これはグラデーションの四角形を表示するOpenGLプログラムだ!!
#include#include "aux.h" /* 頂点情報 */ float vertex[4][3] = { {0.0, 0.0, 0.0}, {1.0, 0.0, 0,0}, {1.0, 1.0, 0,0}, {0.0, 1.0, 0,0} }; /* 画面クリア、シェーディングモード設定 */ void ClearScreen() { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glShadeModel(GL_SMOOTH); } /* グラデーション四角形を表示 */ void DrawObject() { glBegin(GL_QUADS); /* 四角形の描画開始 */ glColor3f(0.0, 0.0, 0.0); glVertex3fv(vertex[0]); /* 左下の頂点を設定 */ glColor3f(1.0, 0.0, 0.0); glVertex3fv(vertex[1]); /* 左上の頂点を設定 */ glColor3f(0.0, 1.0, 0.0); glVertex3fv(vertex[2]); /* 右上の頂点を設定 */ glColor3f(0.0, 0.0, 1.0); glVertex3fv(vertex[3]); /* 右下の頂点を設定 */ glEnd(); /* 四角形の描画終了 */ } /* メイン関数 */ void main(int argc, char **argv) { /* ウインドウの初期化 */ auxInitDisplayMode(AUX_SINGLE | AUX_RGB); auxInitPosition(0, 0, 500, 500); auxInitWindow(argv[0]); /* 見え方の設定 */ glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0); /* 画面クリア */ ClearScreen(); /* オブジェクト描画 */ DrawObject(); sleep(10); }
一見して分かることは、OpenGLの関数にはglという接頭辞が付く関数が多いということですね。いや、多いのではなくコアの100強の関数にはすべてglが付きます。いやaux付きもあるぞといわれそうですが、これは補助的な関数群で、gluの付くGLユーティリティライブラリ、glXが付くGLXユーティリティライブラリ、auxが付くAUXライブラリなどがあります。さらにauxの発展型のglutライブラリなどがあり玄人受けしているようです。
これらのaux関数は、本格的なウインドウシステムに対応したプログラムを書かなくても、とりあえず何かオブジェクトを表示したいというユーザ向けの補助関数です。例えば、IndyはMotifベースのGUIになっていますが、Modif上でウインドウを表示してその中で3次元オブジェクトを表示したり、操作したりしようとするなら、当然OpenGL以外にMotifのことまで知る必要があります。これでは大変なので、簡易ウインドウを表示する目的でauxが開発されたわけです。マルチプラットホームなOpenGL、と言われていますが、実際アプリケーションを開発しようと思ったら、UNIXではMotifのことを、Windows NTならWindows APIやMFCクラスライブラリのことを学ばなければならないのです。これらがいかに大変なことか、だれでも知っています。OpenGLのプログラムを学ぶ前に、ぐったり疲れてしまったのでは元も子もないので、このようなライブラリが用意されているのです。
GLでは、ラインの描画は
bgnline(); : : endline();という感じでしたが、OpenGLでは四角形を描くのに
glBegin(GL_QUADS); : : glEnd();という具合です。また、頂点の設定も
v3f(v);から
glVertex3fv(v);に変更されています。一般的にいってOpenGLの関数は、GLの関数を整理整頓して、今風の名前を付けたものだといえるかもしれません。したがって、GLでプログラムしてきた人には、割と移行は容易ではないでしょうか。100%と完璧ということではないのですが、自動的にGLプログラムをOpenGLにコンバートするツールも用意されていて、結構使えるようです。ただ、先に述べたようにウインドウシステムなどのGUIの部分は、昔のGLプログラムと現在のものとではずいぶん異なりますので、規模の大きいアプリケーションなどはコンバートできないでしょう。 新規にOpenGLを学ぶ方には、GLだろうがOpenGLだろうが大した差はないと思います。OpenGLはステートマシン(それが変更されるまで現在の状態が保持される、例えば赤を設定したら、ほかの色を設定するまで、何を描いても赤のオブジェクトが描かれる)といわれますが、このような、普通のプログラムとはちょっと趣を異にするGL(OpenGL)の癖に慣れるまでに少し苦労するかもしれません。
それから、四角形を表示するために
glBegin(GL_QUADS); ..... glEnd();
というスコープの中で頂点を定義しました。エッいちいちこんなことしなきゃいけないの?と驚くかもしれません。複雑な図形は最終的に頂点座標に頼るしかないのはあたりまえですが、立方体や球などの簡単なプリミティブは、aux関数がサポートしていることを、OpenGL派の名誉のために断っておきます。
auxSolidSphare() 球 auxSolidCube() 立方体 auxSolidBox() 直方体 auxSolidTorus() ドーナツ auxSolidCylinder() 円柱 auxSolidCone() 円錐 auxSolidTetrahedron() 正四面体 .......... 正XX面体 auxSolidTeapot() ティーポット
たとえば上のプログラムのDrawObject()で球を表示したければ
void DrawObject() { auxSolidSphere(1.0); /* 球の描画 */ }
とやります。これでちょっとだけ手が抜けそうです。
subtitle
次は、Open Inventorです。Open InventorはVRMLの普及によって、3Dアプリケーション開発ツールとして、注目を集めるようになりました。 SGIのVRMLブラウザであるWebSpaceも初期のころはOpenGLで開発されたようですが、今はOpen Inventorが主力ツールのようです。しかし、パフォーマンスという点では「3Dのアセンブラ」ですからOpenGLの方に分があります。従って、Open Inventorでアプリケーションを開発して、パーフォーマンスのチューニングはOpenGLを使うというやり方が主流のようです。
いきなりプログラムです。これを実行するとウィンドウに青い円柱が現れて、あ~ら不思議円柱をマニュピレータを使って回転できるではないですか。たったこれだけのプログラムでです。(図3)
(プログラムの内容については、ソースのコメントを参考にして下さい。 またC++のソースは、可読性が高いので、何をやっているかは大体わかります。)
トラックボール付きの立方体の表示プログラム
#include// たくさんインクルードする #include #include #include #include #include #include #include void main(int argc, char** argv) { // InventorとXtの初期化 Widget window = SoXt::init(argv[0]); if (!window) exit(0); // シーンのルート作成 SoSeparator *root = new SoSeparator; root->ref(); // カメラ(視点)を作成してルートに追加 SoPerspectiveCamera *camera = new SoPerspectiveCamera; root->addChild(camera); // ライトとトラックボールマニュピレータを作成、追加 root->addChild(new SoDirectionalLight); root->addChild(new SoTrackballManip); // マテリアルをルートに追加 SoMaterial *material = new SoMaterial; material->diffuseColor.setValue(0.0, 0.0, 1.0); root->addChild(material); // 円柱を作成、追加 root->addChild(new SoCylinder); // 表示領域を作成して、シーンを追加する SoXtRenderArea *renderArea = new SoXtRenderArea(window); camera->viewAll(root, renderArea->getViewportRegion()); renderArea->setSceneGraph(root); renderArea->setTitle("Cylinder with Trackball"); renderArea->show(); // メインウインドウを表示して、イベントハンドリング開始 SoXt::show(window); SoXt::mainLoop(); }
C++の大きな欠点の一つにインクルードファイルが膨大になってしまう、というのがあります。上記のようなたくさんのインクルードファイルを1つのインクルードファイルにまとめて1個だけインクルードすればいいじゃないかと、素人は思うかもしれませんが、読み込んでいるファイルの量に変わりはありません。それに、まとめたインクルードファイルを、全てのソースで使用しようとすると、逆にいらないインクルードファイルまで読み込んでしまうので、非効率的です。
プログラムはたったこれだけなのにおそらく、数千、数万行のインクルードファイルがコンパイル時に読み込まれるはずです。 インクルードのことはおいといて、ざっとプログラムを眺めてみてください。一見して分かることは初めからかなり高度なオブジェクトのクラスが用意されているということです。このシンプルトンプログラムでも最低インクルードの数だけ、すなわち次のオブジェクトが使われています。
Open InventorがOpenGLと違うところは、 Iventorには、アプリケーション作成に必要な様々なクラスが用意されており、さらにそれを管理するデータベース構造も持っているということです。書籍『The Inventor Mentor』(Addison Wesley)から引用すると、次のような特徴を持っていることになります。
モデルデータを読み込み表示するプログラム
// viewer.c++ // シーングラフをファイルから読みだして、 // シーングラフを構成するプログラム // #include#include #include #include #include main(int argc, char **argv) { if (argc != 2){ fprintf(stderr, "Usage: %s datafile.iv\n", argv[0]); exit(0); } Widget mainWindow = SoXt::init(argv[0]); if (mainWindow == NULL) exit( 1 ); SoSeparator *root; // ファイルからシーングラフを読む SoInput in; if (in.openFile(argv[1])) { root = SoDB::readAll(&in); if (root == NULL) { fprintf(stderr, "Couldn't open file %s", argv[1]); exit(0); } in.closeFile(); } else { fprintf(stderr, "Couldn't open file %s\n", argv[1]); exit(0); } // ビュアーを生成する SoXtExaminerViewer *viewer = new SoXtExaminerViewer; // シーングラフをビュアーに結合する viewer->setSceneGraph(root); // シーン全体がイメージに入るようにカメラを設定する viewer->viewAll(); // レンダリング領域を表示に設定する viewer->show(); // メインウインドウを表示し、イベントハンドリング // 状態にし、イメージを表示する SoXt::show(mainWindow); SoXt::mainLoop(); }
subtitle
GL、OpenGL、Open InventorはIndyの三大グラフィックス開発環境ですが、見落としてはならないのが、その周辺にあるプログラム開発のための統合的な環境です。最近ではPCの開発環境は目覚ましく進歩していて、MSのVC++やBorlandのBC++などを使って開発してきた経験のあるプログラマにとって、UNIXの開発環境はお寒い限りです。まあ、文化が違うといえばそれまでですが、あまりにもいろいろなUNIXがあるために、標準的な商用のツールが少なく、結局フリーソフトなどを自分でコンパイルして使用することになってしまします。そして、逆にこのフリーソフトの文化がまともな商用のアプリケーションが出にくい要因になっているように思います。
たとえば、ソースレベルデバッガ、皆さんはどうしていますか? dbxやxdbxを使用されているのでしょうか。ないよりはましだと思いますが、知人などはprint文の方がましだといっています。最新のソフトウェア技術を駆使したデバッガを使用したいところです。
ことSGIの開発環境に関しては、素晴らしいデバッガが用意されています。このWorkShopはVC++などと比べても遜色ない機能であり、プログラムのパフォーマンスを計測するプロファイラなどは並ぶものはないでしょう。まあ、値段が10倍することを大目に見ての評価ですが。
プログラマならソースレベルデバッガの使い方は知っているでしょう。ただでさえ、しんどいプログラム作業です。少しでも不可を少なくしたいところです。予算が許せばこのデバッガは揃えておきたい一本です。しかし、個人で買うには高すぎます。
GUIエディタについても、UNIXは惨澹たるものです。メインウィンドウやダイアログをインタラクティブに作成しようと思ったら、UIM/XやX-DesignerなどのGUIビルダーを購入しなければなりません。ところがこれが50万円ぐらいするのです。PCなら4、5万で手に入る機能がです。私はNEXTSTEPは使用したことがないので分からないのですが、NEXTSTEPならかなり事情はかなり改善されるのでしょうか。NEXTSTEPの次バージョンOpenStepがUNIXの代表的な開発環境になって、この辺の状況が改善されれば万々歳です。その代わりデベロッパバージョンが50万近くという今の価格を何とかして欲しいと思います。
そして、GUIビルダーに関してもSGIはやってくれました。その名もRapidAppといいます。(図6)
RapidAppは、GUIビルダというよりもさらに上を行くアップリケーションビルダということになっています。PCならMSのVisual BasicやBorlandのDelphiなどといったところでしょうか。RapidAppはIRISシリーズのGUI、Indigo Magicのインターフェイスを備えたアプリケーションを作成することができます
Open InventorやIRIS ViewKit(SGIオリジナルのGUIコンポーネント)、OpenGLなど他のSGIのライブラリに対応しています。まあ、裏をかえせばSGIの環境でしか動作しないアプリケーションになってしまうということです。
図6はRapidAppでダイアログを設計しているところです。図7はRapidAppに付いているチュートリアルの画面です。
subtitle
そして、とうとう期待の真打登場となりました。その名もCosmo(この前潰れた銀行と違ってコズモと読むようです)。この連載の第一回で取り上げたWWW構築ツールWebFORCEを更に発展させた強力なツール群です。
まだ私も使用したことはありませんが、冒頭で述べたとおり、これはまったくこれからのネットワーク技術に焦点を当てた野心的な商品構成に仕上がっています。私はOpen Inventorを中心に据えてプログラムの実践編を書こうかと考えていましたが、ん~、Cosmoにしようかという気になってきました。Cosmoはそのうち必ず取り上げることにしましょう。今日はざっとどんなものがあるのか見てみます。
Cosmoは次の4つのパッケージから構成されています。 (www.sig.co.jpのCosmoを参照)
・Cosmo Create(オーサリングソフトウェア)
インタラクティブなWWWページや、マルチメディアタイトルを作るためのオーサ リングツールです。HTMLやVRML、Javaなどをサポートします。
・Cosmo Code
Javaプログラミング言語用の最先端の拡張開発環境です。コンパイラ、ソースデ バッガ、ソースブラウザ、デジタルメディアならびに3Dライブラリを含んでいます。
・Cosmo Player
ブラウザです。他のブラウザのプラグインとしても利用できます。
・Cosmo MediaBase
World Wide Webおよびイントラネットに対し、強力なマルチメディアデータのマ ネージメントと配信サービス機能を提供します。
ということになってますが、今回使用できなかったのが残念です。 最近のSGI社の積極的な行動は何か発散ぎみで、この会社がどこに向かおうとしているのかちょっと理解できないところがあります。任天堂とのUltra64の開発や双方向のマルチメディアネットワークサービスの実験などは、ビジュアルのトップ企業として当然の選択かもしれません。スーパーコンピューターの代名詞、Crayを買収したのは、これからますます重要性を増してくるクライアント/サーバー型ネットワークのためのサーバー事業の強化の一環として捉えることができるかもしれません。
しかし、足元を見てみると、これまでSGIマシンにしかできなかった3次元グラフィックスがWindows NTやPowerPCを載せたMachintoshなどのPCでも可能になってきており、ローエンドのマシンに関してはかなりシビアな競争時代に入っているということもできます。したがって、ハイエンドの市場での生き残りを掛けた選択が今回のCrayの買収劇だったのかもしれません。
まあ、そういったことはどうでもいいことですが、こうやってSGIの開発環境を見てくると、SGIが他の会社より格段に優れている点が浮かび上がってきます。それは、メーカでありながら、どこよりもソフトウェアの開発に力を入れていることです。これは今に始まったことではありません。しかし、OpenGLあたりから業界のスタンダード作りを意識したソフトウェアパッケージの開発を進めているようです。また、聞くところによるとSGIはハード部門とソフトウェア部門を分離するようです。SunのSunSoftのような会社ができるのでしょうか。
ここで紹介したソフトウェア以外にも、多くのパッケージがSGIから販売されています。詳しく知りたい方は
http://www.sgi.co.jp
http://www.sgi.com
にアクセスしてみてください。