VRML with JavaScript Tutorial

戻る はじめに / ノードの生成

文字列以外からノード生成

文字列から生成できないプロトタイプのインスタンスの生成方法と、 あるVRMLブラウザー専用の拡張ノードを同じファイルで実行する為のテクニックについて。

プロトタイプのインスタンス

先の作例ではアニメーションに必要なノードとそれらを関連付ける ROUTE をスクリプトで生成しましたが、 これらをプロトタイプ ( PROTO ) として纏めてそのインスタンスを逐一生成するようにすれば、理解しやすく簡潔な記述になります。  またプロトタイプであることを活かして、生成された各々のインスタンスに異なる特徴を付けることができます。

プロトタイプのインスタンスは文字列から生成できない

このファイルはプロトタイプの定義だけでありインスタンスを含んでいませんので、実行しても何も表示されません。
VRML - ソース / X3D - ソース
このプロトタイプは球の形状と浮上アニメーションを纏めたものです。  また、球の座標により色を変える機能も備えています。  ballPosition フィールドに3次元座標がイベントされると、そこに球を位置させて、x 座標に応じて球の色相を z 座標に応じて彩度を変化させます。  startFloat フィールドに時刻がイベントされるとその時点からボールが浮上開始します。


そしてこちらが、そのプロトタイプのインスタンス ColorBallEXTERNPROTO を通じて生成する側のファイルです。
VRML - ソース / X3D - ソース
茶色の板の上のカーソルで触れた場所に、先のプロトタイプのインスタンスを生成するようにしてみました。
しかし、この作例は何れのVRMLブラウザーにおいても意図した動作をいたしません。  Cosmo Cortona の場合、板の上をなぞるとエラーが表示されます。  Contact の場合、板以外は何も表示されません。
DEF Sc Script {
eventIn SFVec3f set_hitPoint
eventOut MFNode addChildren
url "javascript:

function set_hitPoint(vec,et) {

var Ball = new SFNode ( 'ColorBall {}' );
Ball.ballPosition = vec;
Ball.startFloat = et + 1;

addChildren[0] = Ball;

}

"
}
new SFNode ( 'ColorBall {}' );
で文字列からプロトタイプのインスタンスの新規生成を試みてますが、これは上手くいきません。  Browser.createVrmlFromString メソッドを使ってみても同じく生成されることはありません。

生成済のインスタンスを読み込む

では、新しいインスタンスが必要となる度に既に生成されたインスタンスが記述されたファイルを逐一読み込むようにしてみましょう。
VRML - ソース / X3D - ソース
このファイルは先のプロトタイプと定義部分は全く同じです。 最後の1行にこのプロトタイプのインスタンス ColorBall を記述しています。  このファイルを実行しても画面中央に赤い球が1個表示されるだけです。


そしてこちらが、そのファイルを読み込む側のファイルです。  既に生成されたインスタンスを読み込むので EXTERNPROTO はありません。 drawing #2
VRML - ソース / X3D - ソース
茶色い板の上でカーソルを動かすと、小さな球がマウスカーソルの軌跡を残すように追加されます。  追加された球は、少し時間が経つと板の上から離れて徐々に上昇します。  球の色は茶色い板の触れた場所により異なります。
DEF Sc Script {
eventIn SFVec3f set_hitPoint
eventIn MFNode set_children
field SFVec3f pos 0 0 0
field MFString protoUrl "proto_colorball_1.wrl"
field SFNode BallsGp USE Balls-Gp
directOutput TRUE
url "javascript:

function set_hitPoint (vec) {

pos = vec;
Browser.createVrmlFromURL( protoUrl, BallsGp, 'addChildren' );

}

function set_children (nodes,et) {

var last = nodes.length - 1;
nodes[last].ballPosition = pos;
nodes[last].startFloat = et + 1;

}

"
}
茶色の板の上をカーソルが移動する度にインスタンスが記述された外部ファイルを読み込むようにしてみました。

Browser.createVrmlFromURL( url, node, event )
このメソッドは url で示された VRML ファイルを読み込んで、node で示されたノードの event で示されたフィールド ( MFNode ) に出力します。

この作例の場合、インスタンス ColorBallGroup ノードの addChildren フィールドにイベントされるため、その children フィールドの一番最後に追加されます。  set_children 関数は その children フィールドが変化したタイミングで動作し、一番最後の要素に対して位置とアニメーション開始時刻を与えます。


この外部ファイルを逐一読み込む方法は、通信環境にパフォーマンスが影響される場合があるので注意してください。  Cosmo の場合は読込ファイルのキャッシングが行われない為、createVrmlFromURL メソッドが実行される度に外部ファイルがダウンロードされます。

同一ファイルで拡張ノード対応

Cortona VRML Client や blaxxun Contact 3D 、BS Contact VRML など最新のVRMLブラウザーは標準仕様以外に独自の拡張ノードを追加して機能を向上させています。  但し、あるブラウザー用の拡張ノードはそれ以外のブラウザーでは動作しない場合が殆どです。

各VRMLブラウザーの拡張ノードについては以下を参照してください。
Cortona VRML Client - products - developer zone - ParallelGraphics
Node Extensions in blaxxun DeveloperNet

CortonaContact は共に標準仕様ではサポートされていないキーボードからの入力を判断するための拡張ノードがあります。
Cortona の場合

KbdSensor {
exposedField SFBool enabled TRUE
exposedField SFBool isActive FALSE
eventOut SFInt32 keyDown
eventOut SFInt32 keyUp
}
Contact の場合 ( GLView 4.4 は対応していません)

KeySensor {
eventIn SFBool eventsProcessed
exposedField SFBool enabled TRUE
eventOut SFInt32 keyPress
eventOut SFInt32 keyRelease
eventOut SFInt32 actionKeyPress
eventOut SFInt32 actionKeyRelease
eventOut SFBool shiftKey_changed
eventOut SFBool controlKey_changed
eventOut SFBool altKey_changed
eventOut SFBool isActive
}
ご覧の通り、ノード、フィールド名が一致していません。  KbdSensor ノードを Cortona 以外のVRMLブラウザーで使用した場合、 また、KeySensor ノードを Contact 以外で使用した場合はエラーとなります。  ただ、KbdSensor ノードの keyDown フィールドと KeySensor ノードの keyPress フィールドが、 どちらもキーボードの押されたキーコードを取得する為にあるなど、ある程度似通ってはいます。

それでは同じファイルで CortonaContact 共にキー入力を受け付ける VRML を作ってみましょう。
type writer
VRML - ソース / X3D - ソース
Cortona Contact ならば、一度画面をクリックしてからキーボードのキーを押すと、その文字が画面に羅列されます。  (テンキー、カーソルキー、Shift キーなどは対応していません。)  Cosmo などキー入力に対応していないブラウザーならば「Sorry...」と表示され、キー入力は受け付けません。
DEF AddKeyboardSensor-Sc Script {
eventIn MFNode nodeAdded
eventOut MFNode children
eventOut MFString string

field MFString keySensorUrl "keysensor.wrl" # Contact用キー入力センサーノードが記述されたファイル
field SFNode thisNode USE AddKeyboardSensor-Sc # このスクリプトノード
field SFNode inputSc USE KeyInput-Sc # キー入力処理スクリプトノード

url "javascript:

function nodeAdded (nodes) {

children[0] = nodes[0];
Browser.addRoute( nodes[0], 'keyPress', inputSc, 'set_keyCode' );

}

function initialize() {

var brwName = Browser.getName();

if ( brwName == 'Cortona VRML Client' ) {

var keySensorNode = new SFNode ( 'KbdSensor { isActive TRUE }' );
children[0] = keySensorNode;
Browser.addRoute( keySensorNode, 'keyDown', inputSc, 'set_keyCode' );

}
else if ( brwName == 'blaxxunCC3D' ) {

Browser.createVrmlFromURL ( keySensorUrl, thisNode, 'nodeAdded' );

}
else {

string[0] = 'Sorry...';
string[1] = 'This does not operate in ' + brwName + '.';

}
}

"
}
スクリプトのソース以外のVRMLコードはどのVRMLブラウザーでも実行できるように記述されています。

AddKeyboardSensor-Sc で定義されたスクリプトの initialize 関数で、実行しているブラウザー名を判断し、 Cortona もしくは Contact ならばキー入力センサーノードと ROUTE を追加しています。  実行ブラウザーが Cortona ならば、KbdSensor ノードを文字列から生成し、 Contact ならば外部ファイルの KeySensor ノードを読み込んでいます。

ちなみに、Cortona の場合、KbdSensor ノードの生成は外部ファイルの読み込みでも問題なく動作しますが、 ContactKeySensor ノードを文字列から生成するとキー入力を受け付けませんでした。

以下は ContactKeySensor ノードが記述されたファイルです。
VRML - ソース / X3D - ソース

このページのトップ | 前へ ノードのコピー | 次へ サンプル集