第2回 J3C言語の特徴
今回は「物体をプログラムする」という J3Cりません。このインスタンスが3次元空間で実J3C言語のクラスとインスタンスという用語言語の特徴をオブジェクト指向的な側面から解体化して運動することで、3D アニメーションの違いを理解していただけましたか？ クラス説します。

を実現します。

は遺伝子で、インスタンスはその遺伝子から生J3C言語は「物体」を動かすプログラムを作成

例えば、図2に示す空間ではビルもクルマもまれて実際に生きている個々の生物です。同じするための言語です。J3C 言語を習得するため道路も山も3次元空間に存在するものすべてが、遺伝子をもつ生物が 1 匹の場合も 1000 匹の場には身の回りの「物体」に注意して、「何」を「どクラスの定義に従って動作するコンピュータに合もありえます。例えば J3W 付属のサンプルのように動かすプログラムとしようか？」と考コントロールされているインスタンスとなりま

では、 taco.j3d のタコの足は 6 個のクラスをえて実際にプログラミングしてみることです。身す。ビルがたくさん立ち並んでいたとしても、使った120個のインスタンスでできています（画の回りで動くものを見つけて、それがどのよう1つのクラスの複数のインスタンスとして簡単

面 1）。に動いているかを観察することで、オリジナルに実現できます。空間で実体を持たないインスなプログラムのアイデアが見つかると思います。

タンスも使いますが、普通はインスタンスは1●インスタンス●インスタンスの例

つの物体と考えておきましょう。個々のクラス

実際に複数のインスタンスを動作させる簡単は、別のプログラムのように完全に独立して動な例を実行してみましょう。リスト1では、独作します。複雑な3Dアニメーションでも個々立した 2 つのクラスの、それぞれ 1 つのインス前回、1 つのクラスは汎用言語の 1 つのプロのインスタンスを順に追加することで、他のクタンスが同時に動作しますが、全体として意味グラムに相当すると説明しました。複数のクララスに影響することなくシーン（3 次元空間）のある動きをします。

スは同時に動作することが可能で、全体としてを組み立てていくことができます。

1 つの 3 次元空間を構成します。同一のクラス【リスト 1】インスタンスの動作例

で定義される物体が、同時に複数動作することもできます。そこで動作中のクラス1つをイン 【図 2】3 次元空間内に存在するインスタンススタンスと呼んでクラスと区別します。クラスとは、物体の設計図で、インスタンスが物体そのものと考えると理解しやすくありませんか？
図1は独立して動作するクラスの概念図です。
コンピュータは複数存在し、どれか1つのクラスを実行しています。同じクラスを複数のコンピュータに実行させることもできます。また実行を終了したクラス（コンピュータは消滅）や、実行されていないクラスはインスタンスではあ【図 1】クラスとインスタンスの関係【画面 1】

class esc_key {volatile int key;
int INIT() {RQ = 9;}int RUN() {key = InKey();if (key == 0x1B)
Stop();}
int EVENT() {}}class main {volatile int i;
int INIT() {new(esc_key, 50);i = 0;}
int RUN() {Number(i);Char(13);i = i + 1;}
int EVENT() {}}// 変数宣言// キ−コ−ド入力//ESC キーなら// 全インスタンスの終了// イベント処理はない// 変数宣言//esc_key を実行開始// 数値の出力// 改行の出力//i の値を 1 増やす

2001.10

Linux Japan71

【図 3】J3W 仮想 CPU の構造【図 4】インスタンスの関係

クウィンドウかテキス
トウィンドウがアクティブ（フォーカスがあたっている）になっている必要があります。アクティブでなくてもキー入力を有効にするには以下のリスト2を使用してください。
ただし、リスト2のように RawKey 組み込み関数を使うと複数キーの同時入力チェックが可能となるものこの例では、まず main クラスの INIT メソッ

クラスインスタンスと呼びます）は ESC キーの、別のウィンドウで実行されているアプリケードが最初に実行され、その中の new(esc_key,が押されると Stop()に処理が移り、他のすべション（例えば vi）で ESCキーが押されても実50)で esc_key クラスのインスタンスを生成してのインスタンスを終了させるためです。図4

行中のJ3Cのプログラムは終了します。RawKeyています。
「50 個のデータメモリを持つクラスに示すように main クラス（のインスタンス）は組み込み関数はグラフィックウィンドウが開いesc_keyのインスタンスを生成して、INITメソッ

esc_key クラスインスタンスを生成しますが、ている状態（GraphMode 実行後）で使う必要がドから実行しなさい」という意味になります。

その後は独立して動作します。esc_keyクラスあります。

インスタンスを生成するときには、実行に必インスタンスは、ESCキーが押されると、すべ要なデータメモリの大きさを指定する必要があてのインスタンスにプログラム終了のメッセーります。インスタンスを生成すると、図3に示ジを送信してプログラムは終了します（図 4）。

C++におけるコンストラクタの引数に相当す

すJ3Wの仮想CPUが内部的に生成されますが、RUN()メソッドは1回実行すると、他のインる機能がインスタンスの引数です。1つのクラ

このときクラスのデータメンバ（変数）と、ススタンスに実行を渡します（内部的にThrow 組

スから複数の同一のインスタンスを生成しては、タック領域を格納するデータメモリの大きさをみ込み関数を呼び出している）。つまり、各イ同じ物体が同じ位置で同じ動きをすることになっ指定する必要があります。データメモリの量は、ンスタンスのRUNが1度ずつ順に実行されます。て、無意味な場合があります。大きさが異なる配列や再帰を使用しなければ50か100で十分とすべてのインスタンスが RUN を1回実行するたとか、速度が異なるといったインスタンスを同思います。必要ならば大きな値を指定してくだびに画面更新が行われます。

一のクラスから生成するために、インスタンスさい。1000 でも 10000 でも制限はありません。

物体の移動などの時間を指定する組み込み関

ここで2つのクラスのインスタンスの動作を数では、自動的に必要なタイミングで別のインインスタンスが生成されるとき、親インスタ考えます。1 つ目の main クラスのインスタンスタンスに実行が渡されます。時間を指定する

ンスのレジスタ変数（RX,RY,RZ,RH,RP,RB）をスは0 から順に永久に 1 を加えてそれを表示し組み込み関数では長時間の指定でも問題ありま引き継ぎます。アセンブリ言語（j3dasm）レベ続けます。2つ目のインスタンスはESCキーがせん。一方、INIT、RUN中、またはそこから呼ルでは、RL、RH、RP、RB、R1 〜 R6 の計 13 個

押されるまで永久に待ちますが、ESCキーが押ばれるメソッド中で計算など長時間かかるルーのレジスタが実際に渡されますが、J3C言語でされると Stop を実行して、すべてのインスタプを実行すると、別のインスタンスに実行が渡は、RX、RY、RZ、RH、RP、RB の 6 個のレジスンスを終了させます。

を生成するときに引数を渡すことができます。

らず、画面の更新もされません。どうしても必

タ変数を利用できます。これらのレジスタ変数個々に考えるとどちらも無限ループかそれに要な場合は Throw 組み込み関数をループ内にに値を設定してnewを実行することで、同じプ近いものですが、2つのプロセスが同時に実行置いて他のインスタンスに実行するチャンスをログラムを複数のインスタンスで共有して、引されていると「ESCキーが押されるまで0から与えてください。基本的にはループを避けてRUN数により異なった動作をさせることができます。

順に1を加えてそれを表示する」プログラムとが繰り返し実行されるよう利用する方がよいでなります。2つ目のインスタンス（今後esc_keyしょう。

【リスト 2】キー入力を有効にする

class esc_key {volatile int key;
int INIT() {RQ = 9;GraphMode();}int RUN() {key = RawKey(0x1B); // キ−コ−ド入力
if (key) Stop();//ESC キーなら終了}
int EVENT() {}// イベント処理はない}

72●インスタンスの引数

J3W for Linux 入門講座

リスト 3 は、main クラスのインスタンスから生成された3つの WaitAndWrite クラスのイ

esc_keyクラスインスタンスの最初ンスタンスが同時に動作します。WaitAndWriteの文「RQ = 9 」はインスタンスの識

クラスのインスタンスは、newで生成される時別番号を9に設定するための組み込み点の親インスタンスのレジスタ変数を引数とし関数です。他のインスタンスからメッて受け取って、別々の文字を異なるタイミングセージを送る場合などに使用しますが、で出力します。

リスト 1 では使っていません。この

esc_keyクラスのインスタンスを、任●ライブラリ

意の J 3 C のプログラム内でCの関数のように定型的な処理を定義するた

new(esc_key, 50);を実行してインめに、クラスの外で関数や定数を宣言するライスタンス化するだけで、ESCキーで強ブラリという機能があります。ライブラリは、制終了という機能を追加できます。

クラスと異なりインスタンス化することはありInKeyによるキー入力はグラフィッません。スコープはグローバルで複数のクラス

からライブラリに属するメソッドと定数を参照のファイル中に取り込んで再利用できるこすることができます。クラスのようにデータメとです。J3C 言語はクラスの継承という機ンバ（クラスの変数）を持つことはできません

能を持っているため、インポートされるファが、定数を宣言することはできます。例えば、イルには手を加えずに、必要な部分だけを色を異なるクラス中で統一した名前で指定したインポートする側のファイルで変更できまい場合には、リスト4のようにライブラリを使す。いろいろな形状を持つ物体のクラスをいます。どのクラスからでも、Color.Blackと記述したファイルを用意しておくと、それ指定すれば黒に相当する色番号を名前で指定すらのファイルをインポートして、必要ならることができるようになります。

ば色や位置や動作を再定義することで、そリスト5はライブラリで関数を利用する例です。クラスのデータメンバ（変数）を参照することはできないため、関数が必要とする情報は引数として渡します。どのクラスからでも、このライブラリを使うと Error.Message(n) をれらの物体を容易に 3 次元空間に追加できます。
インポートファイルのパスは、

import "../../lib/abc.j3c";

呼び出すことでnの値に対応したエラーメッセーのようにインポートするファイルからの相ジを表示できます。switch文のcaseブロック対パスで指定することもできます。インポーの最後には break;が必要なことに注意してく

トファイル中に、さらにインポートファイださい。breakを忘れると、C言語と同じようルを記述することも可能です。に、その後に続くcaseを実行します。libraryの関数は値を1つしか返せませんが、レジスタ■終わりに変数をグローバル変数として使うことで複数の値を返すこともできます。

今回までの解説でJ3Wに付属している文
書とサンプルプログラムが理解しやすくな●インポートると思います。次回は 3 次元に関する話題

インポートは指定したファイルをその位置に挿入する働きをします。汎用的に使用できるクに移ります。3 次元の形状の作成のコツを中心に解説する予定です。

ラスやライブラリをファイルに記述して、その機能が必要な場合にインポートします。C のヘッダファイルのインクルードと同様な使い方になります。同じファイルが何度もインポートされても、最初に1度だけコンパイルされ、2 度目からは無視されます。同一ファイルかどうかの判定はファイル名のみで行っているため、別ディレクトリに同名のファイルが存在し、両方のファイルをインポートしようとしても同一ファイルと判定されます。
リスト 2のソースをesckey.j3c というファイル名で保存します。リスト6のように別ファイルから import で指定すると、アセンブル時にesckey.j3c が挿入され、リスト 1 と同等なプログラム（RawKey バージョン）となります。このように挿入して使用するファイルをインポートファイルと呼びます。
インポートの利点は、1 度作成したクラスやライブラリを別【リスト 3】インスタンスの引数の使用例

class WaitAndWrite {volatile int c, time;
int INIT () {c = RX;time = RY;}
int RUN () {Pause(time);
Char(c);}int EVENT() {}}class main {volatile int i;
int INIT () {RX = 'A'; RY = 1000;
new(WaitAndWrite, 50);
RX = 'B'; RY = 2000;
new(WaitAndWrite, 50);
RX = 'C'; RY = 1500;
new(WaitAndWrite, 50);i = 0;}
int RUN () {Pause(5000);
Char(13);i = i + 1;
if (i>=10) Stop();}int EVENT() {}}// インスタンス引数// インスタンス引数// 時間待ち// 文字の出力【リスト 4】ライブラリ使用例

library Color {final int Black= 0 ;final int Blue= 1 ;final int Green= 2 ;final int Aqua
= 3 ;final int Red= 4 ;final int Purple= 5 ;final int Yellow= 6 ;final int White= 7 ;final int Gray
= 8 ;final int Navy
= 9 ;final int Teal
= 10 ;
final int LightGreen = 11 ;final int Brown= 12 ;
final int Fkusia= 13 ;
final int Orange= 14 ;
final int Cream= 15 ;// 関数宣言を置いてもよい}【リスト 5】ライブラリで関数を利用する例

library Error {// ここで変数宣言できない// 定数宣言は可
int Message(int i) {// ここで局所変数宣言は可能
switch (i) {case 1 :String("Error 1"); // 文字列表示
Char(13);// 改行出力
break;// 忘れないこと
case 2 :String("Error 2"); // 文字列表示
Char(13);// 改行出力
break;// 忘れないこと// 必要なら case が続く
default :String("Unknown"); // 文字列表示
Char(13);// 改行出力
break;// なくてもいい}}// ここに別の関数定語も可能}【リスト 6】インポートの例//A を 1 秒ごとに出力

import "esckey.j3c";//B を 2 秒ごとに出力

class main {volatile int i;
int INIT() {new(esc_key, 50);i = 0;}
int RUN() {Number(i);Char(13);i = i + 1;}
int EVENT() {}}//C を 1.5 秒ごとに出力// 時間待ち(5 秒)// 改行出力// 終了// esckey.j3c を挿入

2001.10

Linux Japan73

J3W と PS2LinuxKit

J3W の内部構造の解説

J3Wは、PS2LinuxKitでも、ソースを修正す

前号では J3W の 3D エンジンの概要の紹介まででします。また、テーブルが存在する、床のある 1 点ることなくコンパイルと実行を行えます。ただ、したので、今回はもう少し詳しく見ていきましょう。

を基準として雑誌の 8 個の頂点を表したものがワー

PS2のCPUであるEmotion Engineの数値演算

J3Wでは、頂点、面、位置、角度といった物体の情ルド座標系（world）となります。さらに、ワールドコプロセッサでは32ビットの浮動小数点数しか報は複数のクラスに分散して格納しています。まず座標系のある位置の「目」を基準とする視点座標系サポートしていないため、doubleを多用していは、頂点と面( 多角形）について見てみましょう。

（eye）でも同様に8個の頂点の座標を持ちます。
「目」

る J3W では非常に遅くなってしまいます。

TPolygons クラス（図A）は、1 つの物体を構成するも含めて複数の物体がワールド座標系を動き回る状

そこで、double を float に変更して試して複数の頂点と多角形を管理しています。TVertexク

況を考えるとこのように 3 種類の座標系が必要になみました。表の3つのヘッダーファイルの先頭ラスが管理する頂点は物体を構成する上で必要な情ります。

付近に「#define double float」の 1 行を追報ですが、さらに物体の表面の性質を指定する必要加します。さらに、xkey.cpp の先頭付近のがあります。J3W では物体は多くの面（多角形、ポ#include <iostream.h>とある行を削除します。
その後コンパイルして実行すると2〜3倍高速化され、使用に耐えられるようになります。行

J3W では面はすべて多角形で定義します。1 つの情報の管理がTPolygonsクラスの役割となります（図多角形は頂点座標以外にも、色、反射率、環境光のA）。物体を構成する多角形は頂点の情報と面の情報強度、重心のオフセットという情報を持っています。に分かれて、それぞれ TVertex クラスとPolygon3D

1 つの多角形に関する情報は Polygon3D 構造体が持クラスに保持されています。

ち、 P o l y g o n 3 D 構造体へのポインタの配列をTPolygonsクラスが所有することによって複数の多列演算にVPUを使えば、より高速化できるはずです。

（水谷純）●面リゴン）から構成され、1 つの物体の「形」に関する●頂点角形を管理しています。

TVertexクラスは、物体を構成する最も基本的なデー

多角形の頂点は、Polygon3D構造体がVectorSetタである頂点を管理しています。頂点の座標データ内の頂点を頂点番号で参照します。その頂点番号をは、local 、world、 eye という 3 種類の 3 次元座標配列で持つことによって、多角形の実際の頂点デー値（x、y、 z）を1組にした VectorSet 構造体に格納タにアクセスします。このように頂点と多角形を分

source/j3w/hobj3d.hします。TVertexクラスは、そのVectorSet構造体へ離することによって、複数のポリゴンで頂点を共有

source/j3w/tpolygon.hのポインタを配列として持つことによって、複数のすることができます。

【表】「#define double float」を追加するヘッダーファイル
source/j3w/misc3d.h

頂点を管理します。

J3W for Linux のインストール

ポリゴンの反射率とはスペキュラ（ハイライト）のテーブルの上に、1冊の雑誌が存在するとしましょ

強度のことで、値が大きいほど良く光る面となりまう。雑誌のサイズが、高さ30cm、幅20cm、厚さ3cmす。環境光の強度は 0 から 100 までの値をとり、光といえば誰でもどんな大きさか理解できますよね。例があたらない面の明るさを決めます。

えば、この雑誌の表紙の右下の角を原点として雑誌

J3Wでは視点から遠いポリゴンから塗り潰し法でを形作る 8 個の頂点の位置をローカル座標系で指定描画しますが、視点からの距離はポリゴンの重心位置で比較します。小さいポリゴン

J3W の最新ソースコード「j3w643.tar.gz」【図 A】TPolygons クラスの概要

が、地面などを表す大きいポリゴを付録CD-ROMに収録しています。インストー

ンの近くにあると位置関係が狂っルは、流れ図のように行なってください。インてしまうことがあります。重心のストールに関してさらに詳しい情報を得るには、オフセットは、ポリゴンの重心をJ3W添付のREADME.eucファイルを確認してく強制的に変化させて、そのポリゴださい。

ンの表示順序を変えるために使い（編集部）ます。

【図】J3W のインストール手順●移動と回転1

j3w643.tar.gz を展開

3Dアニメーションの基本とな

tar vxzf j3w643.tar.gz

る物体の移動や回転は、物体のローカル座標系の移動や回転とし2

j3w-643 ディレクトリへ移動て扱います。ローカル座標系の原$ cd j3w-643

点の位置をワールド座標系（または親座標系）の座標で指定するこ3

コンパイルを行なうとで物体の位置が決まり、これを$ make && make strip

変化させれば物体は移動します。
ローカル座標系とワールド座標系

4 ルートになりインストールを行なう# make install && make clean
5 一般ユーザーになり、検索パスを確認$ echo $PATH【図 B】TAxis 座標軸（ ま た は 親 座 標 系 ）と の 角 度 はquaternionの形式で格納されます。この角度を変化させれば物体は回転します。このように物体の回転や移動は単にTAxisに値を設

6 検索パスに /usr/local/bin が含まれて定することで実現します。頂点やいない場合は、 ~./bashrc などに以下を面の操作と比べると簡単です（図追加B）。

export PATH=/usr/local/bin:$PATH

74

J3W for Linux 入門講座

（水谷純）