clock_0.wrl source
#VRML V2.0 utf8

Viewpoint {
position 0 0 5
description "initial"
}

NavigationInfo {
type "EXAMINE"
}

# 時計本体
Transform {
rotation 1 0 0 1.5708
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1 1 1
}
}
geometry Cylinder {
radius 1.25
height 0.2
}
}
Shape {
appearance Appearance {
material Material {
diffuseColor 0.8 0.8 0.8
}
}
geometry Cylinder {
radius 0.1
height 0.3
}
}
]
}

# 文字盤
DEF DialPlate-Tr Transform {
translation 0 0 0.11
}

# 時計目盛り雛形
Switch {
choice [
# 目盛り大
DEF Scale1-Tf Transform {
translation 0 1.15 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.5 0 0
}
}
geometry Box {
size 0.05 0.08 0.02
}
}
]
}
# 目盛り小
DEF Scale2-Tf Transform {
translation 0 1.15 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0 0 0
}
}
geometry Box {
size 0.02 0.05 0.02
}
}
]
}
]
}

# 文字盤設置スクリプト
DEF Plate-Sc Script {
field SFNode DialPlate USE DialPlate-Tr
field SFNode DialFS FontStyle {
justify "MIDDLE"
size 0.3
}
field SFNode DialAp Appearance {
material Material {
diffuseColor 0 0 1
}
}
field SFNode Scale1 USE Scale1-Tf
field SFNode Scale2 USE Scale2-Tf

directOutput TRUE
url "javascript:
function initialize () {

var dial = new MFNode ();
var r = 1;

// 1 から 12 の文字をセットする。
for (var i=1; i<=12; i++) {

var Sp = new SFNode ( 'Shape { geometry Text {} }' );
Sp.appearance = DialAp;
Sp.geometry.fontStyle = DialFS;
Sp.geometry.string[0] = i;

var ang = 2 * Math.PI * i / 12;
var x = r * Math.sin ( ang );
var y = r * Math.cos ( ang ) - 0.1;

var Tf = new SFNode ( 'Transform {}' );
Tf.translation = new SFVec3f ( x, y, 0 );
Tf.children[0] = Sp;

dial[dial.length] = Tf;

}

// 60個の目盛りを付ける。
for (var i=0; i<60; i++) {

var ang = 2 * Math.PI * i / 60;

var Tf = new SFNode ( 'Transform {}' );
Tf.rotation = new SFRotation ( 0, 0, 1, ang );

// 5つ置きに大きな目盛りにする。
Tf.children[0] = ( i % 5 == 0 )? Scale1 : Scale2;

dial[dial.length] = Tf;

}

// 文字盤に数字と目盛りをセットする。
DialPlate.children = dial;

}
"
}

# 秒針
DEF SecondHand-Tf Transform {
children [
Transform {
translation 0 0.4 0.12
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0 0 0
}
}
geometry Cylinder {
radius 0.01
height 1.4
}
}
]
}
]
}

# 長針
DEF MinuteHand-Tf Transform {
children [
Transform {
translation 0 0.47 0.12
children [
Shape {
appearance DEF Hand-Ap Appearance {
material Material {
diffuseColor 1 0 0
}
}
geometry Cylinder {
radius 0.02
height 1.0
}
}
]
}
]
}

# 短針
DEF HourHand-Tf Transform {
children [
Transform {
translation 0 0.3 0.12
children [
Shape {
appearance USE Hand-Ap
geometry Cylinder {
radius 0.02
height 0.8
}
}
]
}
]
}

# タイムセンサー
DEF TiS TimeSensor {
loop TRUE
}

# 針回転スクリプト
DEF Time-Sc Script {
eventIn SFFloat set_fraction
eventOut SFRotation rotation_sec
eventOut SFRotation rotation_min
eventOut SFRotation rotation_hor
field SFRotation rotinit 0 0 -1 0
field SFFloat oldS 0
url "javascript:
function initialize () {

// 針の回転軸を初期化する。
rotation_sec = rotinit;
rotation_min = rotinit;
rotation_hor = rotinit;

}
function set_fraction () {

// 現在時刻を得る。
var d = new Date();
var s = d.getSeconds();
var m = d.getMinutes();
var h = d.getHours();

// 秒の変化がないならば、負荷軽減のためにこの関数を終える。
if (s == oldS) return;
oldS = s;

// 3本の針の回転角をセットする。
rotation_sec.angle = 2 * Math.PI * s / 60;
rotation_min.angle = 2 * Math.PI * ( m / 60 + s / 3600);
rotation_hor.angle = 2 * Math.PI * ( h / 12 + m / 720);

}

"
}

ROUTE TiS.fraction_changed TO Time-Sc.set_fraction
ROUTE Time-Sc.rotation_sec TO SecondHand-Tf.rotation
ROUTE Time-Sc.rotation_min TO MinuteHand-Tf.rotation
ROUTE Time-Sc.rotation_hor TO HourHand-Tf.rotation