第7回 objviewの使用法
けを参照できます。

座標が負）ほど細くなるように、次に生成する物体ばかりを例にしてきましたが、今回は、ウChildクラスのインスタンスに渡す大きさの値ネウネとした動物的な動きをする物体を作成し■インスタンスの再帰的生成（RX）を小さくしています。また、再帰的に生J3W 付属のタコ（taco.j3c）の足の部分は、ジスタ変数が「0」の場合には、 Top クラスをこれまでは、幾何学的な形状の「硬そうな」てみましょう。次に、物体の形を個別に確認するためのツールである objview.j3c の使い方成する数（RY）を 1 つ減らしています。RY レインスタンスを再帰的に生成しています。階層生成して再帰から抜けます。こうしてChildク構造の上位（親）の頂点を使って面（スキン）ラスは、自分自身を再帰的に呼び出して、階層■スキンを次々と登録していき、階層構造の下位に自分構造を形成しながら多くのインスタンスを生成自身を生成しています。リスト 1 に示すしています。

「腕を曲げる」動作を考えると、肘の皮膚はskin.j3c の Common クラス自身は実体化せず枝を分岐させて再帰的に生成し、先端部に葉伸び縮みしていることが分かります。動物の体にTop、Child、Baseクラスに継承され、スキが付くようなオブジェクトも同じように作成では骨とそれを取り巻く筋肉、そして皮膚でできンで構成された三角柱を生成する機能を提供しきると思います。ています。関節の角度が変化しても、表面の皮ています。

を解説します。

動きの設定は、Childクラスで単にピッチ回膚が伸縮することによって関節の部分で分離す

Common クラスは、三角形を1つ登録した後、転を繰り返すだけですが、ねじれを加えているることはありません。J3Wでは多角形の頂点を親の頂点を使って面を登録して三角柱を生成しため動物的なちょっと無気味な動きをします。

登録する場合に、親の頂点を含めることができています（図 2）。三角柱の側面に三角形を張ます。子物体と親物体の距離が変わると多角形ることで、上下の三角形が「ねじれる」ことがが伸縮します（図 1）。

できるようになっています。最初の頂点（頂点■オブジェクトビューア

階層構造の物体は、頂点を持つ親オブジェク

番号が 0）は子インスタンスから参照できない

形状を確認しながら物体を定義できると、ストが存在する場合、多角形の頂点番号に負の数ため、原点に置いていますが、使用しません。

トレスなくプログラミングを進めることができを使用して親オブジェクトの頂点を指定するこBase クラスが階層構造の基部になるクラスると思います。目的としている本来のプログラとができます。独立して運動する物体間には、で、正三角形になるように頂点を登録してChildムとは独立して、作成中の物体の形状を確認す多角形（スキン）を張ることができます。このクラスを生成しています。Childクラスを生成るために、objview.j3c というツールが用意

とき親オブジェクトの頂点は負の数を使用してするとき、RXレジスタ変数に三角形の大きさ、されています。

指定するため、親の0番頂点は指定できないこ

RY レジスタ変数に再帰的に生成する数、 RZ レとに注意してください。親1つに複数の子を持ジスタ変数に色を設定します。

たせる場合も同様に、それぞれの子が親の頂点Childクラスは、生成時のレジスタ変数の値を指定できます。なお、子は直接の親の頂点だに従って三角柱を生成しますが、先端に行く（X

リスト 1の skin.j3c は物体を作成するクラスだけですが、プログラムとして完成させるためには、いろいろな初期設定をしたり、視点を持つ物体を作成する必要があります。
J3C で 3D アプリケーションを作成する場合【図 1】腕を曲げる動作を多角形で表した様子【図 2】リスト 1（skin.j3c）の Common クラスによる三角柱の生成の基本的な手順は次のようになります。まず最初に、個々の物体の形状と動作を独立して作成します。次に、部品として用意された物体を空間に追加していくことで世界を組み立てます。
各部品のクラスを objview.j3c に組み込むと、部品の形状や動きを確認して完成することができます。objview.j3c には、インポートした model.j3c で定義済みの model クラスを継承して、キー入力に従って移動や回転する

MyModel クラスがあります。この model.j3c
中で、任意のクラスを継承するようにmodelク58

J3W for Linux 入門講座

ラスを定義することで、部品としての物体の形状を確認するプログラムができます。

model.j3c で定義される物体は、ワールド【図3】ワールド座標系にあるmodel.j3c で定義された物体囲は変化します。
物体の移動速度は、objview.j3cのMyModel
クラスの EVENT メソッドで決められており、1座標系の原点（変更可能）にあり、視点は X 座

回のキー入力で 100 の距離を 0.1 秒間で移動し標が -1000 の位置（南に 1000 離れた位置）にあます。視点は、距離50を0.1秒間で移動します。

ります（図 3）。初期状態で画面に表示される

どちらも回転速度は3度/0.1秒となっています。

範囲は、左右（Y 座標）に 2000、上下（Z 座標）

小さい物体を近くで見る場合には、見失わないに 1500 になります。ズームした場合は、それように移動速度を小さくする必要があるかもし

ぞれ 1000 と 750 の範囲が見えることになりまれません。

す。視点や物体を移動させた場合には、表示範

model.j3c の model クラスは、物体のクラ【リスト 1】skin.j3c→// 共通の基底クラス
class Common {volatile int radius, color, count;// 正三角形の頂点を登録
int Def_Tri(int radius, int x) {volatile int P, Q, R;
PushRegisters();
R = radius;
P = sqrt(radius * radius * 3) / 2;
Q = radius / 2;
RX = x;RZ = -R; RY = 0; Point();// #0;
RZ = Q; RY = P; Point();// #1
RZ = Q; RY = -P; Point();// #2
PopRegisters();}// 親物体の頂点との間に面（スキン）を張る
int def_shape(int r, int color) {DefPoint(0, 0, 0);// 0 頂点はダミー
Def_Tri(r, -200);
DefPlane(color, 3, 2, 3, -3); //DefPlane(color, 3, 2, -3, -2); //-2
DefPlane(color, 3, 1, 2, -2); //2
DefPlane(color, 3, 1, -2, -1); //1
3
DefPlane(color, 3, 3, 1, -1); // -1-3
DefPlane(color, 3, 3, -1, -3); //}int INIT() {}int RUN () {Wait();}int EVENT () {}// 先端部：階層構造の最下位
class Top extends Common {int INIT() {color = 4;
radius = RX;
def_shape(radius, color);
DefPlane(color, 3, 3, 2, 1);
ClearRegisters();
RX = -100;
SetPosition();// 初期位置と角度}}

int RUN () {RotPitch(3000, -120);
RotPitch(2000, 120);}// 動きを定義// 3 秒間で回転}// 階層の根元
class Base extends Common {int initialize() {ClearRegisters();
RP = -720;
SetPosition();// 初期位置と角度
DefPoint(0, 0, 0);// ダミー頂点
Def_Tri(radius, 0);
DefPlane(color, 3, 1, 2, 3);}
int INIT() {radius = 300;// 基部の太さ
color = 2;
initialize();
RX = radius;
RY = 20;qi// 中間部の長さは 10 個
RZ = color;child(Child, 50, 4, 6);// 子オブジェクト}}→}// 中間部：オブジェクトを再帰的生成
class Child extends Common {int initialize() {color = RZ;
radius = RX;count = RY;
def_shape(radius, color);
ClearRegisters();
RX = -100;
SetPosition();// 初期位置と角度}
int INIT () {initialize();
RX = radius - 5;
RY = count - 1;
RZ = color;
if (count > 0) child(Child, 50, 4, 6)
else child (Top, 50, 4, 7);// Top の生成
RotBank(3000, 80);
RotPitch(2000, 60);// 2 秒間で回転}

2002.3

Linux Japan59スを継承するか、または物体のクラスを子オブの物体）として Base クラスのインスタンスをジェクトとして生成します。modelクラスを継生成します。

リスト 3 は model クラスが Base クラスを継承する MyModel は、model クラスの RUN とskin.j3cで定義されている物体が大きいた承しています。リスト2とは異なり、model ク

EVENTメソッドを書き換えることで、作成されめ、初期値であるワールド座標系の原点位置よラス自体が形を持つ物体となります。この方法

る物体をキー入力で操作できるようになります

り遠ざかった位置で、さらに下に移動した位置

では、 Base クラス自身を継承によって書き換（表 1）。に配置しています。背景の色も黒に変更してみえるため、より柔軟な設定を試すことができま

実際に model クラスを作成して objview の使ました。こうしてskin.j3cをobjview.j3cにすが、継承元のクラス（この場合は Base クラい方を見ていきましょう。作業環境は、今月号組み込んでできたプログラムは、「目に見えなス）の内容を理解して、必要な変更を加える必の本誌付録 CD-ROM の sample.tar.gz を展開

いテーブルの上に物体を置いて、テーブルを動してできる s k i n . j 3 c 、 m _ s k i n . j 3 c 、かすことによって形状を色々な角度から確認す

m_skin2.j3cをj3w-643/j3c_script/objviewる」形式になります。

ディレクトリにコピーしているものとします。

m_skin.j3c を model.j3c にコピーした後、リスト 2 に示す m_skin.j3c では、リスト 1

objview.j3cをコンパイルします。model.j3cで作成したskin.j3cをインポートしています。

を変更してobjview.j3cをコンパイルしても、skin.j3c 中の Base クラスは、物体の階層構

いつも objview.j3d という実行ファイルがで造の根元を作るクラスになっています。model

きてしまいます。objview.j3d の名前を変更

クラスより下位の階層に物体を生成するため、しておくと、別の model.j3c を設定してコンmodelクラス自身は形を持つ必要がありません。

パイルしても上書きされません。実行例1のよ単にインスタンスの位置をワールド座標系の原うにして objskin.j3d を実行すると、画面 1点に置いて、子オブジェクト（階層構造の下位のようになります。ちょっと不気味な動きをす【実行例 1】リスト 2 のコンパイルと実行【リスト 2】m_skin.j3c$ cp m_skin.j3c model.j3c$ j3cc objview.j3c$ mv objview.j3d objskin.j3d$ j3w objskin.j3d【表 1】objview のキー操作
操作対象

キー

物体の操作

←

左回転

→

右回転

↑

下向き回転

↓

上向き回転

L

バンク反時計回り

カメラの操作表示60

ると思いませんか？

動作

K、R

バンク時計回り

F

前進

B

後退

W

上移動

X

下移動

S

左移動

D

右移動

I

元の位置（原点）に戻る

Z

拡大

Q

縮小

U

上向き回転

N

下向き回転

H

左回転

J

右回転

O

前進

P

後退

T

ワイヤーフレーム表示

Y

通常の表示

ESC

終了

J3W for Linux 入門講座

【画面 1】objskin.j3d の実行画面

import "skin.j3c";class model {int INIT() {BackgroundColor(0x000);
NewObject(0,0);
ClearRegisters();
RX = 1000;
RZ = 1000;
SetPosition();child(Base, 50, 4, 1);}
int RUN() {}int EVENT() {}}// 背景は黒// インスタンス自身は形状を持たない// (1000, 0, 1000) に配置// MyModel で上書きされる// MyModel で上書きされる【リスト 3】m_skin2.j3c

import "skin.j3c";class model extends Base {int INIT() {NewObject(4, 1);
radius = 300;// 基部の太さ
color = 2;// 色
initialize();
RX = radius;
RY = 20;// 中間部の長さは 20 個
RZ = color;child(Child, 50, 4, 6); // 子オブジェクト
ClearRegisters();
RX = 1000;
RZ = 1000;
RP = -720;
SetPosition();// (1000, 0, 1000) に配置}}

要があります。
コンパイルの際には、実行例 2 のようになく、自立して運動している物体もobjview.j3c に組み込んで表示することがで

m_skin2.j3c を model.j3c にコピーした後、きます。いろいろな形や動きを簡単に試すことobjview.j3cをコンパイルして、objview.j3dができると思います。

【表 3】objview.j3c のクラスの動作
クラス

動作

MyModelmodel を継承して物体を生成する
RUN と EVENT メソッドをオーバーライドして model の動作を変更する

をobjskin2.j3dにリネームしておきます。実
行してみると、objskin.j3d とはキー操作が異なることに気が付かれると思います。

RUN メソッドでインスタンス番号を設定して、メッセージを待つ■終わりに

EVENT メソッドでキー入力によるコマンドを実行する

objskin.j3dではMy_modelというテーブルのJ3C言語を使った三次元アニメーションの作上に立てた物体を操作しているのに対して、成法を一通り解説してきました。次回は最終回

objskin2.j3dではテーブル自身が物体となっとして、J3Wのネイティブな言語であるアセン視点用に物体を生成するて 90 度向きを変えて立ち上がっています。

ブリでのプログラミングを紹介する予定です。

(-1000, 0, 0)に位置を設定する

Cameraインスタンス番号を設定する

j3w-643/j3c_script/objview ディレクト
リには、他にも表2に示すように、いろいろな物体用の model.j3c が m_XXX.j3c というファSee を実行して視点を取得する【表 2】objview ディレクトリ
ファイル

メッセージを受信したら対応した動作をする

内容

falcon02.j3c

F-16 クラス

m̲falcon.j3c

falcon02.j3c 用の model.j3c

objview.j3c の構造を簡単に表 3 にまとめま

taco.j3c

タコの形状クラスした。objview.j3c をカスタマイズするとき

weed.j3c

海草クラスの参考にしてください。静止した物体だけではm̲taco.j3ctaco.j3c と weed.j3c 用の model.j3clhand.j3c

左手クラスm̲hand.j3clhand.j3c 用の model.j3c

body.j3c

POSE の人体クラス

m̲body.j3cbody.j3c 用の model.j3c

tubo.j3c

回転体で作成した壷クラス

INIT を再定義して位置を変更する

m̲tubo.j3ctubo.j3c 用の model.j3c

RUN、EVENT は MyModel で再定義される

イル名で収録されていますので、objview.j3cと組み合わせて試してみてください。また、【実行例 2】リスト 3 のコンパイルと実行$ cp m_skin2.j3c model.j3c$ j3cc objview.j3c$ mv objview.j3d objskin2.j3d$ j3w objskin.j3d

main

背景色の設定する
フレームレート表示用のクラスを起動する
MyModel を起動して物体を表示する
視点用にカメラを生成する
グラフックウィンドウを開く
使用法を表示する
キー入力からカメラや物体にメッセージを送信する

model

別に定義したクラスを継承する

J3W の内部構造の解説
前回（2002年2月号）のコラムで、「シンボル管理類別に設定しています。

■コンパイラの組み込み関数処理に苦労した」と書きましたが、j3cコンパイラのソーcSymTableは、単一のクラスまたはライブラリ用のシンスのうちで、動作が分かりにくい部分を簡単に説明

ボル管理テーブルで、シンボル名、種類、値を保持します。

J3C言語の組み込み関数は、Cでいうところの「ラします。

シンボルには、ライブラリ名、クラス名、メソッド名、引イブラリ」
としてリンクされるのではなく、1つのj3w数名、定数名、局所変数名の6種類があります。値は、変（仮想CPU）の命令に翻訳されます。現在、115個の数の場合は変数のアドレス、定数の場合は、定数値をその組み込み関数が用意されていますが、引数の数や引シンボル管理に関連する（C++ の）クラスには、まま登録しています。局所変数名の場合はブロックのネス数の種類（レジスタまたは定数）、関数の結果を式でcClassTable、cSymTable、cHSymTable、cSymRoot

トの数を登録します。cSymTableは、cHSymTableに継承使うか、といった組み込み関数ごとの情報を j3w のの 4 つがあります（図 A）。紛らわしいので、これ以されて、クラス名とスーパークラス（継承元）へのポイン命令に翻訳するために、組み込み関数の書式をコン降の「クラス」という記述は、すべて「J3C言語におタを追加した形で使われます。

パイラが知っている必要があります。この組み込み■コンパイラのシンボル管理けるクラス」として説明していきます。

J3Cの複数のクラスやライブラリのシンボルを扱うため、関数の書式処理は cParamFormat（j3c_func.h）がcClassTableが最も簡単で、宣言されたクラス名、cSymRootがcHSymTableへのポインタを配列として持つよライブラリ名、インポートファイル名を構文解析時うになっています。cSymRoot は、構文解析中のクラスの115種類の関数の書式は、関数ごとに32ビット整に登録しています。登録時に、インポートファイルシンボルを管理している c H S y m T a b l e へのポインタ数で表現しています（ParamFormatTable）。これら

名なら0、クラス名なら1、ライブラリ名なら2を種（Current）を持っていて、実際のシンボルの登録、検索は、は上位30ビットを2ビットずつ使って引数の種類をcSymRoot経由でのみ行われます。

持っています。1は式、2は文字列、3は定数式を表構文解析時に、新たなクラスに出し、最大15個の引数を指定しています。従って、引会うと c S y m R o o t 経由で数の数に制限のない多角形の登録などの命令でも、最cHSymTableを生成して、そのポ大引数は15に制限されるようになっています。最下

インタを配列に登録し、さらに位のビットは、引数を使わずレジスタ変数を入出力

cClassTableに名前とクラスかラに使う命令を表していますが、実際には使っていま【図A】シンボル管理に関連する（C++ の）クラス担当しています。

イブラリの種別を登録します。ク

せん。下位の 2 ビット目は算術関数や InKey などのラスの定数、変数、メソッドのス

返り値のある関数の第1引数（レジスタ）を隠す目的

コ ー プ（ 名 前 の 有 効 範 囲 ）はで使用しています。

cSymRootによって適切に管理さソースコードを単語単位で読み込むscan->getsym()

れるため、構文解析側ではクラスに注意して、記事末の構文図式を参考に cParse::の継承関係によるスコープを気にparse から追っていくと、j3cの仕組みが理解できるすることなくシンボルにアクセスと思います。

（水谷純）できるようにしています。

2002.3

Linux Japan61

J3C は、3D アニメーションキット J3W のコンパイラです。
J3C は、Java風の文法を持つオブジェクト指向言語として設計されています。J3Cの構文リファレンスを掲載します。

■構文規則（syntactic rule）■構文図式の基本形

コンピュータ言語の文法は、構文規則によって決定されます。
構文は、左から右へ、上から下へ矢印をたどって読んでいきます。

a は b である

b は「B」である

構文図式の基本形は次のようになっています。
「連続」
、「選択」
、「繰り返し」を組み合わせて文法を記述します。

連続選択

a の後に b が続く

a か b のどちらかを選択する

繰り返し

繰り返し

a の 0 回以上の繰り返し

a の 1 回以上の繰り返し。b は区切りの役割を持つ

構文規則の左側にある名前のことを、「非終端記号（nonterminalsymbol）」と呼びます。また、class や for などの予約語、＝や＋などの記号で表される単語そのもののことを「終端記号（terminalsymbol）」と呼びます。終端記号と非終端記号は、構文図では次のように表します。

終端記号

非終端記号

（terminal symbol）（nonterminal symbol）

囲みの中には予約語または記号が入ります

囲みの中には、他で定義しているものが入ります

任意a か何もなし

構文規則を順次適用していくと、 すべての非終端記号は終端記号に行き着きます。

代入文

文
文としては、次の14種類が使用可能です。IF文以外は、C言語など他

代入文は、左辺に用意した局所変数、データメンバおよびそれらの配列、またはレジスタ変数に、右辺の式の値を代入します。代入文は値を返しません。の言語に共通する文法となっています。

メソッド呼び出し
メソッドを文として呼び出した場合、返り値は無視されますが、代入文の右辺や式中で使用された場合には、メソッド中で最後に評価された式の値が返り値になります。

空文
ASM 文

文が必要な位置にセミコロンを置くと、何もしない空文とすることができます。

62

J3W for Linux 入門講座

ASM文で指定された文字列は、そのままj3cの出力としてアセンブラソースに埋め込まれます。j3dasm の入力として有効な文字列を指定する必要があります。

組み込み関数呼び出し
組み込み関数呼び出しは、仮想マシン J3W の機能を使用するためにJ3C内に組み込まれている関数です。引
数は、通常のメソッドやライブラリの呼び出しとは異なり、形式は組み込み関数ごとに違います。

BREAK 文B R E A K 文は、最も内側のループ（FOR、DO、WHILE、SWITCH）からライブラリ呼び出し抜けます。BREAK文は、SWITCH文中でCASEの区切りとして使用します。

library 宣言されているライブラリが持つメソッドを呼び出します。ライブラリ呼び出しは、ライブラリが宣言済みである限り、どのクラスまたはライブラリから参照することもできます（グローバルスコープを持つ）。実引数リストは、メソッ

CONTINUE 文

ド呼び出し、ライブラリ呼び出しのときの引数です。引数の数は 0 以上、任意の個数が指定可能です。

CONTINUE 文は、ループ（FOR、DO、WHILE）内で、CONTINUE文の後の処理を飛ばして次のループの先頭から開始します。

SWITCH 文SWITCH文は、C、C++、JAVAと同じように、式の値で分岐する場合に使用します。BREAK文を使用しない場合、分岐したラベル以降を上から下へ順に実行します。BREAK文が存在する

RETURN 文と SWITCH 文の実行は終了します。case ラベルに一致する値がなく、「default:」が存在する場
すべてのメソッドは、最後に評価し合にはその部分が実行されます。

た式の値が返ります。RETURN文は式を評価する目的で使用します。式の伴
なわない RETURN 文は何もしません。
処理の流れを制御する目的では使用できません。メソッドの最後で返す値を明示するために使用します。メソッド定義の途中で RETURN 文を使用してもメソッドは終了しません。

FOR 文
FOR文は、決まった回数を繰り返します。FOR文に使用する変数（制御変数）

DO 文

は、事前に宣言しておく必要があります。また、加算は「i++」ではなく「i=i+1」という形式にする必要があります。

DO文は、C、C++、JAVAと同じように、繰り返し処理に使用します。式の値が真（非 0）の間、繰り返し文が実行されます。WHILE文と異なり、文は少なくとも 1 度は実行されます。

IF 文
IF文だけが、C、C++、JAVAの文法とわずかに異なり、ELSE節の前にセミコロンを置くことができません。

WHILE 文WHILE 文は、C、C++、JAVA と同じように、繰り返し処理に使用します。式の値が真（非 0）の間、繰り返し文が実行されます。

2002.3

Linux Japan63