<
head>
</
head>
<!--
-->
<
Scene>
<
NavigationInfo avatarSize='
0.01 0 0'
type='
"EXAMINE" "ANY"'
transitionType='
"ANIMATE"'/>
<
Viewpoint description='
Start'
fieldOfView='
0.9'
position='
0 0 0'/>
<
Viewpoint description='
Looking up from start'
orientation='
1 0 0 1.57'
position='
0 0 0'/>
<
Viewpoint description='
10m above, looking straight up'
orientation='
1 0 0 1.57'
position='
0 10 0'/>
<
Viewpoint description='
10m above start'
position='
0 10 0'/>
<
Viewpoint description='
10m above, looking straight down'
orientation='
1 0 0 -1.57'
position='
0 10 0'/>
<
Viewpoint description='
10m below, looking down'
orientation='
1 0 0 -1.57'
position='
0 -10 0'/>
<
Viewpoint description='
10m below start'
position='
0 -10 0'/>
<
Viewpoint description='
10m below, looking up'
orientation='
1 0 0 1.57'
position='
0 -10 0 '/>
<!--
Water ROUTE:
[
from ChangeVisibility.visibility_changed to visibilityRange
]
-->
<
Fog DEF='
Water'
color='
0.2 0.2 0.4'
fogType='
EXPONENTIAL'
bindTime=''
isBound=''/>
<!-- Proximity sensor must be large enough to encompass the entire scene -->
<!--
ProxSensor ROUTEs:
[
from position_changed to ChangeVisibility.get_depth
]
[
from orientation_changed to ChangeVisibility.set_visibility
]
-->
<
ProximitySensor DEF='
ProxSensor'
size='
1000 1000 1000'/>
<!-- TimeSensor triggering reduces frequency of calculations for performance reasons. -->
<!--
Clock ROUTE:
[
from cycleTime to ChangeVisibility.get_clock_hit
]
-->
<
TimeSensor DEF='
Clock'
loop='
true'/>
<!--
ChangeVisibility ROUTEs:
[
from Clock.cycleTime to get_clock_hit
]
[
from ProxSensor.position_changed to get_depth
]
[
from ProxSensor.orientation_changed to set_visibility
]
[
from visibility_changed to Water.visibilityRange
]
-->
<
Script DEF='
ChangeVisibility'>
<field name='get_clock_hit' type='SFTime' accessType='inputOnly'/>
<field name='run_script' type='SFBool' value='false' accessType='initializeOnly'/>
<field name='get_depth' type='SFVec3f' accessType='inputOnly'/>
<field name='visibility_changed' type='SFFloat' accessType='outputOnly'/>
<field name='set_visibility' type='SFRotation' accessType='inputOnly'/>
<field name='checked' type='SFBool' value='false' accessType='initializeOnly'/>
<field name='moved' type='SFBool' value='false' accessType='initializeOnly'/>
<![CDATA[
ecmascript:
// REF: http://astronomy.swin.edu.au/pbourke/geometry/rotate/
function initialize () {
visibility = 20;
depth = 0;
pos = (0,0,0);
Browser.print ('Position output from ProximitySensor.');
}
function get_clock_hit (clock_msg) {
run_script = true;
}
function get_depth ( position ) {
pos = position;
depth = position[1] - 30;
}
function set_visibility( rotation ) {
if (run_script) {
//z coordinate of the default viewpoint direction(0,0,-1)
initZ = -1;
rX = rotation[0]; // x coordinate of the rotation
rY = rotation[1]; // y coordinate of the rotation
rZ = rotation[2]; // z coordinate of the rotation
theta = rotation[3]; // angle of rotation in radians
print ('theta: ' + theta);
cosTheta = Math.cos(theta);
sinTheta = Math.sin(theta);
print ('cosTheta: ' + cosTheta + ' sinTheta: '+ sinTheta);
// calculate the y coordinate of the point after rotation
/* there are 8 other terms in the full conversion, but 6 are equal
to zero because of the choice of a starting point on the z-axis. The
other two are not calculated since all we need is the y coordinate
*/
finalY = ((1 - cosTheta) * rY * rZ - rX * sinTheta) * initZ;
print ('final y: ' + finalY);
//calculate the elevation/depression angle of the final point location
elevation = Math.asin(finalY);
print ('elevation: ' + elevation);
directionFactor = 1 + 0.2 * (4 * elevation / Math.PI);
depthAdjust = (60 + depth)/60
depthFactor = Math.max(depthAdjust,0.05);
visibility_changed = 60 * depthFactor * directionFactor;
Browser.print ('depth=' + depth + ', elevation=' + elevation +
', visibility_changed=' + visibility_changed);
run_script = false;
}
}
]]>
</
Script>
<
ROUTE fromNode='
Clock'
fromField='
cycleTime'
toNode='
ChangeVisibility'
toField='
get_clock_hit'/>
<
ROUTE fromNode='
ProxSensor'
fromField='
position_changed'
toNode='
ChangeVisibility'
toField='
get_depth'/>
<
ROUTE fromNode='
ProxSensor'
fromField='
orientation_changed'
toNode='
ChangeVisibility'
toField='
set_visibility'/>
<
ROUTE fromNode='
ChangeVisibility'
fromField='
visibility_changed'
toNode='
Water'
toField='
visibilityRange'/>
<!-- A set of arrows is used to show visibility and direction -->
<
Transform DEF='
Pointer'
translation='
0 0 -15'>
<
Transform translation='
0 4 0'>
<
Shape>
<
Cone bottomRadius='
0.4'/>
<
Appearance DEF='
ShapeApp'>
<Material ambientIntensity='0.8' diffuseColor='1 1 0.3' shininess='0.6'/>
</
Appearance>
</
Shape>
</
Transform>
<
Shape>
<
Cylinder height='
6'
radius='
0.2'/>
<
Appearance USE='
ShapeApp'/>
</
Shape>
</
Transform>
<
Transform translation='
0 10 0'>
</
Transform>
<
Transform translation='
0 -10 0'>
</
Transform>
<!-- A pair of disks used to show visibility -->
<
Transform translation='
0 15 0'>
<
Shape DEF='
Disk'>
<
Cylinder height='
0.01'/>
<
Appearance USE='
ShapeApp'/>
</
Shape>
</
Transform>
<
Transform translation='
0 -15 0'>
</
Transform>
<!-- An indexed face set box used to bound the working area -->
<
Transform scale='
20 20 20'>
<
Shape DEF='
IFSBox'>
<
Appearance>
<Material diffuseColor='1 1 1'/>
</
Appearance>
<
IndexedFaceSet ccw='
false'
colorPerVertex='
false'
colorIndex='
0, 2, 2, 2, 2, 1'
coordIndex='
0, 1, 2, 3, -1,
7, 6, 5, 4, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0'>
<Coordinate point='-1.0 1.0 1.0,
1.0 1.0 1.0,
1.0 1.0 -1.0,
-1.0 1.0 -1.0,
-1.0 -1.0 1.0,
1.0 -1.0 1.0,
1.0 -1.0 -1.0,
-1.0 -1.0 -1.0'/>
<Color color='1 1 1, 0 0 0, 0.2 0.2 0.8'/>
</
IndexedFaceSet>
</
Shape>
</
Transform>
</
Scene>
</