#VRML V2.0 utf8
Viewpoint {}
NavigationInfo {
type "EXAMINE"
headlight FALSE
}
# 照明
DEF DL DirectionalLight {
direction -0.7 -0.5 -1
}
# 箱
Shape {
appearance Appearance {
texture DEF PT PixelTexture {}
}
geometry Box {}
}
# 箱のテクスチャー作成スクリプト
DEF Sc Script {
eventOut SFImage image
field SFInt32 dt 128 # テクスチャの1辺のピクセル数
field SFColor colA 0.3 1.0 0.3 # 球の色
field SFColor colB 0.5 0.2 0.2 # 球の外側の色
field SFNode DL USE DL # 照明ノード
url "javascript:
// SFColorオブジェクトを 0 から 0xFFFFFF の間の整数に変換する為の関数。
function SFColor2Int (c) {
var r = Math.floor ( c.r * 255 );
var g = Math.floor ( c.g * 255 );
var b = Math.floor ( c.b * 255 );
return r * 65536 + g * 256 + b;
}
function initialize () {
// dr を光が差し込む向きとは正反対の単位ベクトルとする。
var dr = DL.direction.negate().normalize();
var col1 = SFColor2Int ( colB );
var ary = new MFInt32 ();
// 円の半径 r を dt の半分とする。
var r = dt / 2;
var rr = r * r;
var q = 0;
// テクスチャーの左下から順番に、全ピクセルに対して円の内外に位置するか否かを調べて塗り分ける。
for ( var y = 0; y < dt; y++ ) {
var y0 = y - r;
var yy = y0 * y0;
for ( var x = 0; x < dt; x++ ) {
var x0 = x - r;
var xx = x0 * x0;
if ( rr > xx + yy ) {
// ピクセルが円の内側にあるならば、x と y 座標から仮の球に対する z 座標を求める。
var z0 = Math.sqrt( rr - xx - yy );
// 仮の球の表面の位置ベクトル point を求める。 この球は原点が中心である為、point は法線ベクトルも意味する。
var point = new SFVec3f ( x0, y0, z0 );
// 正規化された point と dr との内積をとり、両ベクトルのコサイン値 ( -1 <= cos <= 1 )を得る。
var cos = point.normalize().dot( dr );
// コサイン値からピクセルの明るさを求める。 コサイン値が 1 ならば colA と同じ色であり、0 に近づく程に暗くなる。
var colC = new SFColor ();
colC.r = Math.max ( 0, Math.min ( 1, colA.r * cos ));
colC.g = Math.max ( 0, Math.min ( 1, colA.g * cos ));
colC.b = Math.max ( 0, Math.min ( 1, colA.b * cos ));
ary[q++] = SFColor2Int ( colC );
}
else ary[q++] = col1;
}
}
image = new SFImage ( dt, dt, 3, ary );
}
"
}
ROUTE Sc.image TO PT.image