{ "X3D": {
"encoding":"UTF-8",
"@profile":"Immersive",
"@version":"3.3",
"@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd",
"JSON schema":"https://www.web3d.org/specifications/x3d-4.0-JSONSchema.autogenerated.json",
"head": {
"-children":[
{
"#comment":"javascript code for rotation calculations was derived from:"
}
],
"meta": [
{
"@name":"title",
"@content":"ChangingFog.x3d"
},
{
"@name":"description",
"@content":"A Fog node that adjusts as the viewer's orientation and position changes. This is a good candidate to become a Prototype since Fog does not automatically bind when inlined."
},
{
"@name":"creator",
"@content":"Matthew Braun"
},
{
"@name":"created",
"@content":"20 September 2001"
},
{
"@name":"modified",
"@content":"20 October 2019"
},
{
"@name":"reference",
"@content":"http://astronomy.swin.edu.au/pbourke/geometry/rotate/"
},
{
"@name":"rights",
"@content":"Copyright (c) Matthew Braun 2001"
},
{
"@name":"subject",
"@content":"Fog"
},
{
"@name":"identifier",
"@content":"https://X3dGraphics.com/examples/X3dForWebAuthors/KelpForestExhibit/ChangingFog.x3d"
},
{
"@name":"generator",
"@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
},
{
"@name":"license",
"@content":"../license.html"
},
{
"@name":"translated",
"@content":"25 April 2023"
},
{
"@name":"generator",
"@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
},
{
"@name":"reference",
"@content":"X3D JSON encoding: https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
}
]
},
"Scene": {
"-children":[
{ "WorldInfo":
{
"@title":"ChangingFog.x3d"
}
},
{ "NavigationInfo":
{
"@avatarSize":[0.01,0,0]
}
},
{ "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]
}
},
{ "Fog":
{
"@DEF":"Water",
"@color":[0.2,0.2,0.4],
"@fogType":"EXPONENTIAL"
}
},
{
"#comment":"Proximity sensor must be large enough to encompass the entire scene"
},
{ "ProximitySensor":
{
"@DEF":"ProxSensor",
"@size":[1000,1000,1000]
}
},
{
"#comment":"TimeSensor triggering reduces frequency of calculations for performance reasons."
},
{ "TimeSensor":
{
"@DEF":"Clock",
"@loop":true
}
},
{ "Script":
{
"@DEF":"ChangeVisibility",
"field": [
{
"@name":"get_clock_hit",
"@accessType":"inputOnly",
"@type":"SFTime"
},
{
"@name":"run_script",
"@accessType":"initializeOnly",
"@type":"SFBool",
"@value":false
},
{
"@name":"get_depth",
"@accessType":"inputOnly",
"@type":"SFVec3f"
},
{
"@name":"visibility_changed",
"@accessType":"outputOnly",
"@type":"SFFloat"
},
{
"@name":"set_visibility",
"@accessType":"inputOnly",
"@type":"SFRotation"
}
],
"-children":[
{
"#comment":" "
}
],
"#sourceCode":[
"",
"",
"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",
"\t",
"Browser.print ('theta:' + theta);",
"",
" cosTheta = Math.cos(theta);",
" sinTheta = Math.sin(theta);",
"",
"Browser.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;",
"",
"Browser.print ('final y:' + finalY);",
"",
"//calculate the elevation/depression angle of the final point location",
"",
" elevation = Math.asin(finalY);",
"",
"Browser.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;",
"",
" }",
"}",
"",
""
]
}
},
{ "ROUTE":
{
"@fromField":"cycleTime",
"@fromNode":"Clock",
"@toField":"get_clock_hit",
"@toNode":"ChangeVisibility"
}
},
{ "ROUTE":
{
"@fromField":"position_changed",
"@fromNode":"ProxSensor",
"@toField":"get_depth",
"@toNode":"ChangeVisibility"
}
},
{ "ROUTE":
{
"@fromField":"orientation_changed",
"@fromNode":"ProxSensor",
"@toField":"set_visibility",
"@toNode":"ChangeVisibility"
}
},
{ "ROUTE":
{
"@fromField":"visibility_changed",
"@fromNode":"ChangeVisibility",
"@toField":"visibilityRange",
"@toNode":"Water"
}
},
{
"#comment":"A set of arrows is used to show visibility and direction"
},
{ "Transform":
{
"@DEF":"Pointer",
"@translation":[0,0,-15],
"-children":[
{ "Transform":
{
"@translation":[0,4,0],
"-children":[
{ "Shape":
{
"-geometry":
{ "Cone":
{
"@bottomRadius":0.4
}
},
"-appearance":
{ "Appearance":
{
"@DEF":"ShapeApp",
"-material":
{ "Material":
{
"@ambientIntensity":0.8,
"@diffuseColor":[1,1,0.3],
"@shininess":0.6
}
}
}
}
}
}
]
}
},
{ "Shape":
{
"-geometry":
{ "Cylinder":
{
"@height":6,
"@radius":0.2
}
},
"-appearance":
{ "Appearance":
{
"@USE":"ShapeApp"
}
}
}
}
]
}
},
{ "Transform":
{
"@translation":[0,10,0],
"-children":[
{ "Transform":
{
"@USE":"Pointer"
}
}
]
}
},
{ "Transform":
{
"@translation":[0,-10,0],
"-children":[
{ "Transform":
{
"@USE":"Pointer"
}
}
]
}
},
{
"#comment":"A pair of disks used to show visibility"
},
{ "Transform":
{
"@translation":[0,15,0],
"-children":[
{ "Shape":
{
"@DEF":"Disk",
"-geometry":
{ "Cylinder":
{
"@height":0.01
}
},
"-appearance":
{ "Appearance":
{
"@USE":"ShapeApp"
}
}
}
}
]
}
},
{ "Transform":
{
"@translation":[0,-15,0],
"-children":[
{ "Shape":
{
"@USE":"Disk"
}
}
]
}
},
{
"#comment":"An indexed face set box used to bound the working area"
},
{ "Transform":
{
"@scale":[20,20,20],
"-children":[
{ "Shape":
{
"@DEF":"IFSBox",
"-appearance":
{ "Appearance":
{
"-material":
{ "Material":
{
"@diffuseColor":[1,1,1]
}
}
}
},
"-geometry":
{ "IndexedFaceSet":
{
"@ccw":false,
"@colorIndex":[0,2,2,2,2,1],
"@colorPerVertex":false,
"@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],
"-coord":
{ "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":
{
"@color":[1,1,1,0,0,0,0.2,0.2,0.8]
}
}
}
}
}
}
]
}
}
]
}
}
}