<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.2//EN" "https://www.web3d.org/specifications/x3d-3.2.dtd">
<X3D profile='Immersive' version='3.2' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.2.xsd'>
  <head>
    <meta content='CloudsProcedural1.x3d' name='title'/>
    <meta content='X3D utilizing ecmascript to develop quasi volumetric 3D clouds from png image textured billboard nodes.' name='description'/>
    <meta content='Capt Darren W. Murphy' name='creator'/>
    <meta content='1 November 2007' name='created'/>
    <meta content='20 October 2019' name='modified'/>
    <meta content='https://www.web3d.org/x3d/content/examples/Savage/Environment/Atmosphere/CloudsProcedural1.x3d' name='identifier'/>
    <meta content='X3D-Edit, https://www.web3d.org/x3d/content/README.X3D-Edit.html' name='generator'/>
    <meta content='../../license.html' name='license'/>
    <meta content='fix links' name='TODO'/>
  </head>
  <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'/>
    <Group DEF='Terrain'>
      <Transform scale='50 50 50' translation='25000 0 25000'>
        <Inline url='"../../Locations/MontereyBayCalifornia/MontereyBayLargeMesh.x3d" "https://www.web3d.org/x3d/content/examples/Savage/Locations/MontereyBayCalifornia/MontereyBayLargeMesh.x3d" "../../Locations/MontereyBayCalifornia/MontereyBayLargeMesh.wrl" "https://www.web3d.org/x3d/content/examples/Savage/Locations/MontereyBayCalifornia/MontereyBayLargeMesh.wrl"'/>
      </Transform>
      <Transform rotation='1 0 0 1.57' translation='25000 0 25000'>
        <Shape>
          <Rectangle2D size='77000 55000'/>
          <Appearance>
            <ImageTexture url='"ocean.png" "https://www.web3d.org/x3d/content/examples/Savage/Environment/Atmosphere/ocean.png"'/>
          </Appearance>
        </Shape>
      </Transform>
    </Group>
    <Group DEF='Placemarks'>
      <Transform scale='50 50 50' translation='45000 30 44000'>
        <Inline url='"Lighthouse.x3d" "https://www.web3d.org/x3d/content/examples/Savage/Environment/Atmosphere/Lighthouse.x3d" "Lighthouse.wrl" "https://www.web3d.org/x3d/content/examples/Savage/Environment/Atmosphere/Lighthouse.wrl"'/>
      </Transform>
    </Group>
    <Group DEF='Clouds'>
      <Transform DEF='Cumulus'/>
      <Transform DEF='Cirrus'/>
      <Script DEF='PixelScript' directOutput='true'>
        <field accessType='initializeOnly' name='Cumulus' type='SFNode'>
          <Transform USE='Cumulus'/>
        </field>
        <field accessType='initializeOnly' name='Cirrus' type='SFNode'>
          <Transform USE='Cirrus'/>
        </field>
        <![CDATA[
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://www.web3d.org/x3d/content/examples/Savage/Environment/Spheretexture.png\" \n';
  	}

  		else
  	{
	image = ' \"Spheretexture.png\" \"https://www.web3d.org/x3d/content/examples/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://www.web3d.org/x3d/content/examples/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();
}
]]>
      </Script>
    </Group>
  </Scene>
</X3D>