#X3D V3.2 utf8 PROFILE Immersive # [X3D] version=3.2 # [X3D] noNamespaceSchemaLocation=https://www.web3d.org/specifications/x3d-3.2.xsd # X3D-to-ClassicVRML XSL translation autogenerated by X3dToClassicVrmlEncoding.xslt and X3dToVrml97.xslt # https://www.web3d.org/x3d/content/X3dToClassicVrmlEncoding.xslt # https://www.web3d.org/x3d/content/X3dToVrml97.xslt # Transformation using XSLT processor: Saxonica # head META "title" "CloudsProcedural1.x3d" META "description" "X3D utilizing ecmascript to develop quasi volumetric 3D clouds from png image textured billboard nodes." META "creator" "Capt Darren W. Murphy" META "created" "1 November 2007" META "modified" "20 October 2019" META "identifier" "https://savage.nps.edu/Savage/Environment/Atmosphere/CloudsProcedural1.x3d" META "generator" "X3D-Edit, https://www.web3d.org/x3d/content/README.X3D-Edit.html" META "license" "../../license.html" META "TODO" "fix links" # [Scene] ========== ========== ========== # A png image file for the cloud texture must be designated in the ecmascript node. WorldInfo { title "CloudsProcedural1.x3d" } Viewpoint { description "Main" jump FALSE orientation 0 1 0 1.57 position 50000 1000 42000 } Viewpoint { description "Light House Tower" jump FALSE orientation 0 1 0 1.3 position 45000 1290 44000 } Viewpoint { description "centerWest" jump FALSE orientation 0 1 0 2.5 position 48000 1000 20000 } Background { groundColor [ 0 0 1 ] skyColor [ 0 0 1 ] } DirectionalLight { ambientIntensity 1 direction -1 0 0 global TRUE } DEF Terrain Group { children [ Transform { scale 50 50 50 translation 25000 0 25000 children [ Inline { url [ "../../Locations/MontereyBayCalifornia/MontereyBayLargeMesh.x3d" "https://savage.nps.edu/Savage/Locations/MontereyBayCalifornia/MontereyBayLargeMesh.x3d" "../../Locations/MontereyBayCalifornia/MontereyBayLargeMesh.wrl" "https://savage.nps.edu/Savage/Locations/MontereyBayCalifornia/MontereyBayLargeMesh.wrl" ] } ] } Transform { rotation 1 0 0 1.57 translation 25000 0 25000 children [ Shape { geometry Rectangle2D { size 77000 55000 } appearance Appearance { texture ImageTexture { url [ "ocean.png" "https://savage.nps.edu/Savage/Environment/Atmosphere/ocean.png" ] } } } ] } ] } DEF Placemarks Group { children [ Transform { scale 50 50 50 translation 45000 30 44000 children [ Inline { url [ "Lighthouse.x3d" "https://savage.nps.edu/Savage/Environment/Atmosphere/Lighthouse.x3d" "Lighthouse.wrl" "https://savage.nps.edu/Savage/Environment/Atmosphere/Lighthouse.wrl" ] } ] } ] } DEF Clouds Group { children [ DEF Cumulus Transform { } DEF Cirrus Transform { } DEF PixelScript Script { initializeOnly SFNode Cumulus USE Cumulus initializeOnly SFNode Cirrus USE Cirrus directOutput TRUE url [ "ecmascript: function cumulustranslation() // These values designate the boundary location of the cloud { X = 50000*Math.random(); // X horizontal range Y = 1000 + 300*Math.random(); // Y vertical base + range Z = 50000*Math.random(); // z horizontal range randomt = new String(X+' '+Y+' '+Z); return randomt; } function cumulusscale() // these values scale a cloud within a designated size { maxscale = 1; scale = Math.round(9+maxscale*Math.random()); X = 1.5*scale; Y = scale; Z = scale; randomscale = new String(X+' '+Y+' '+Z); return randomscale; } function cirrustranslation() // These values designate the boundary location of the cloud { X = 50000*Math.random(); // X horizontal range Y = 8000 + 1000*Math.random(); // Y vertical base + range Z = 50000*Math.random(); // z horizontal range randomt = new String(X+' '+Y+' '+Z); return randomt; } function cirrusscale() // these values scale a cloud within a designated size { maxscale = 1; scale = Math.round(9+maxscale*Math.random()); X = 1.5*scale; Y = 2*Math.random(); Z = 1.5*scale; randomscale = new String(X+' '+Y+' '+Z); return randomscale; } function cumulussectiontranslation() // These random values place another portion of cumulus type cloud { randomtheta = 6.28319*Math.random(); randomphi = .7854*Math.random(); randomradius = 90 + 5*Math.random();//the first whole number should be close to the sectionradius X = randomradius*Math.cos(randomtheta)*Math.sin(randomphi); Z = randomradius*Math.sin(randomtheta)*Math.sin(randomphi); Y = randomradius*Math.cos(randomphi); randomt = new String(X+' '+Y+' '+Z); return randomt; } function cirrussectiontranslation() // These random values place another portion of cirrus type cloud { randomtheta = 6.28319*Math.random(); randomphi = .7854*Math.random(); randomradius = 90 + 5*Math.random();//the first whole number should be close to the sectionradius X = randomradius*Math.cos(randomtheta)*Math.sin(randomphi); Z = randomradius*Math.sin(randomtheta)*Math.sin(randomphi); Y = randomradius*Math.cos(randomphi); randomt = new String(X+' '+Y+' '+Z); return randomt; } function rotation() // This random value is for the billboard rotation not used in this script { radians = 6.28*Math.random(); randomr = new String('0 0 1 ' + radians ); return randomr; } function cumulus() { maxi = 10; // number of clouds maxj = 5; // denotes how many portions affecting the size of the cloud maxk = 8; // number of billboards indicating cloud density sectionradius = 100; //radius of individual cloud sections for (var i=0; i < maxi; i++) { CloudStringA = ' Transform { \n' + ' scale '+ cumulusscale() + ' \n' + ' translation '+ cumulustranslation() + ' \n' + // cloud placement ' children [ \n'; CloudStringB = new Array(); CloudStringF = new Array(); for (var j=0; j < maxj; j++) { radius = 0; CloudStringB[j]= ' Transform { \n' + ' translation '+ cumulussectiontranslation() + ' \n' + // section placement ' children [ \n'; CloudStringC = new Array(); image = new String(); for (var k=1; k < maxk; k++) // maxk value denotes how many textured billboards make up the cloud { randomtheta = 6.28319*Math.random(); randomphi = 1.57079*Math.random(); radius = radius+(sectionradius/maxk); // radius incremental steps based on billow radius and max billboards X = radius*Math.cos(randomtheta)*Math.sin(randomphi); Z = radius*Math.sin(randomtheta)*Math.sin(randomphi); Y = radius*Math.cos(randomphi); if (Y <= 30) //cloud shading and lighting control { image = ' \"Spheretexture.png\" \"https://savage.nps.edu/Savage/Environment/Spheretexture.png\" \n'; } else { image = ' \"Spheretexture.png\" \"https://savage.nps.edu/Savage/Environment/Spheretexture.png\" \n'; } Billboardtranslation = new String(X+' '+Y+' '+Z); CloudStringC[k] = ' Transform { \n' + ' translation '+ Billboardtranslation + ' \n' + // random billboard placement within radius designated above ' children [ \n' + ' Billboard { \n' + ' axisOfRotation 0 0 0 \n' + // 0 0 0 designates rotation on all axis ' children [ \n' + ' Transform { \n' + ' rotation 0 0 0 0 \n' + // a rotation of the individual billboards can be defined ' children [ \n' + ' Shape { \n' + ' appearance Appearance { \n' + ' material Material { \n' + ' } \n' + ' texture ImageTexture { \n' + ' url [ ' + image + ' ] \n' + ' } \n' + ' } \n' + ' geometry Sphere { \n' + ' radius 50 \n' + ' } \n' + ' } \n' + ' ] \n' + ' } \n' + ' ] \n' + ' } \n' + ' ] \n' + ' } \n'; } CloudStringD = CloudStringC.join(' '); CloudStringE = ' ] \n' + ' } \n'; CloudStringF[j] = CloudStringB[j] + CloudStringD +CloudStringE; } CloudStringG = CloudStringF.join(' '); CloudStringH = ' ] \n' + ' } \n' + '######################################################### \n'; CloudString = CloudStringA + CloudStringG + CloudStringH; newNode = Browser.createVrmlFromString(CloudString); Cumulus.children[i] = newNode[0]; } } function cirrus() { maxi = 2; // number of clouds maxj = 5; // denotes how many portions affecting the size of the cloud maxk = 8; // number of billboards indicating cloud density sectionradius = 1000; //radius of individual cloud sections for (var i=0; i < maxi; i++) { CloudStringA = ' Transform { \n' + ' scale '+ cirrusscale() + ' \n' + ' translation '+ cirrustranslation() + ' \n' + // cloud placement ' children [ \n'; CloudStringB = new Array(); CloudStringF = new Array(); for (var j=0; j < maxj; j++) { radius = 0; CloudStringB[j]= ' Transform { \n' + ' translation '+ cirrussectiontranslation() + ' \n' + // section placement ' children [ \n'; CloudStringC = new Array(); for (var k=1; k < maxk; k++) // maxk value denotes how many textured billboards make up the cloud { randomtheta = 6.28319*Math.random(); randomphi = 1.57079*Math.random(); radius = radius+(sectionradius/maxk); // radius incremental steps based on section radius and max billboards X = radius*Math.cos(randomtheta)*Math.sin(randomphi); Z = radius*Math.sin(randomtheta)*Math.sin(randomphi); Y = radius*Math.cos(randomphi); Billboardtranslation = new String(X+' '+Y+' '+Z); CloudStringC[k] = ' Transform { \n' + ' translation '+ Billboardtranslation + ' \n' + // random billboard placement within radius designated above ' children [ \n' + ' Billboard { \n' + ' axisOfRotation 0 0 0 \n' + // 0 0 0 designates rotation on all axis ' children [ \n' + ' Transform { \n' + ' rotation ' + rotation() + ' \n' + ' children [ \n' + ' Shape { \n' + ' appearance Appearance { \n' + ' material Material { \n' + ' } \n' + ' texture ImageTexture { \n' + ' url [\"cloudtexture3.png\" \"https://savage.nps.edu/Savage/Environment/cloudtexture1_4.png\" ] \n' + ' } \n' + ' } \n' + ' geometry IndexedFaceSet { \n' + // define type of geometry to texture ' coordIndex [ 0, 1, 2, 3 ] \n' + ' solid FALSE \n' + ' coord Coordinate { \n' + ' point [ 500 500 0, \n' + // define size of the geometry. Here 100 meter 2D square. ' 500 -500 0, \n' + ' -500 -500 0, \n' + ' -500 500 0 ] \n' + ' } \n' + ' } \n' + ' } \n' + ' ] \n' + ' } \n' + ' ] \n' + ' } \n' + ' ] \n' + ' } \n'; } CloudStringD = CloudStringC.join(' '); CloudStringE = ' ] \n' + ' } \n'; CloudStringF[j] = CloudStringB[j] + CloudStringD +CloudStringE; } CloudStringG = CloudStringF.join(' '); CloudStringH = ' ] \n' + ' } \n' + '######################################################### \n'; CloudString = CloudStringA + CloudStringG + CloudStringH; newNode = Browser.createVrmlFromString(CloudString); Cirrus.children[i] = newNode[0]; } } function initialize() { cumulus(); cirrus(); } " ] } ] }