#VRML V2.0 utf8

DEF GROUP Group 
  {
  }

DEF Script1 Script 
  {
  eventIn SFTime t
  eventIn SFVec3f force_in
  directOutput TRUE
  field SFNode particle_node   DEF TRANS Transform 
    {
    children 
      [
      DEF SHAPE Shape 
	{
	appearance 	DEF APP Appearance 
	  {
	  material 	  DEF MAT Material 
	    {
	    diffuseColor 0.372548 0.360783 0.360783
	    specularColor 1 0.901960 1
	    transparency 0.740000
	    }
	  }
	geometry 	DEF SPHERE Sphere 
	  {
	  }
	}
      ]
    }
  field SFInt32 number_particles 21
  field SFVec3f force 3 0 0
  field SFVec2f energyRange 3 4
  field SFVec2f angleRangeDEG 60 80
  field SFFloat startHeight 0
  field SFVec2f allowedHeightRange -10.020000 8.699995
  field SFVec2f sizeRange 0.400000 0.800000
  field SFFloat density 1
  field SFFloat gravitation 9.810000
  field SFNode group   USE GROUP
  field MFVec3f internPosition 
    [
    ]
  field MFVec3f internVector 
    [
    ]
  field SFFloat internT 0
  field MFFloat internMass 
    [
    ]
  field SFNode internNode NULL
  url 
    [
    "javascript:

 // field SFNode particle_node //

 // field SFInt32 number_particles //

 // field SFVec3f force //

 // field SFVec2f energyRange //

 // field SFVec2f angleRangeDEG //

 // field SFFloat startHeight //

 // field SFVec2f allowedHeightRange //

 // field SFVec2f sizeRange //

 // field SFFloat density //

 // field SFFloat gravitation //

 // field SFNode group //

 // field MFVec3f internPosition //

 // field MFVec3f internVector //

 // field SFFloat internT //

 // field MFFloat internMass //

 // field SFNode internNode //

 function newParticle(i)
    {
    size = sizeRange[0] + Math.random() * (sizeRange[1]-sizeRange[0]);

    internMass[i] = size * size * size * density;

    group.children[i].scale[0] = size;
    group.children[i].scale[1] = size;
    group.children[i].scale[2] = size;

    internPosition[i].x = 0;
    internPosition[i].y = startHeight; 
    internPosition[i].z = 0;
    }

 function startNewParticle(i)
    {
    newParticle(i);
    energy = energyRange[0] + Math.random() * (energyRange[1] - energyRange[0]);
    v = 0.5 * energy / internMass[i];
    alpha = Math.random() * 2.0 * Math.PI;
    angle = angleRangeDEG[0];
    angle +=  Math.random() * (angleRangeDEG[1]-angleRangeDEG[0]);
    angle *= 2.0* Math.PI / 360.0; 
    internVector[i].x = v * Math.cos(angle) * Math.cos(alpha);
    internVector[i].y = v * Math.sin(angle);
    internVector[i].z = v * Math.cos(angle) * Math.sin(alpha);
    }

 function  initialize()
    {
    if (allowedHeightRange[0] > startHeight) 
       {
       print('error: allowedHeightRange[0] must be bigger than startHeight');
       number_particles = 0;
       }
    if (allowedHeightRange[1] < startHeight) 
       {
       print('error: allowedHeightRange[1] must be smaller than startHeight');
       number_particles = 0;
       }
    for (i = 0; i < number_particles; i++)
       {
       internNode = Browser.createVrmlFromString('#VRML V2.0 utf8\nTransform {}');
       group.children[i] = internNode[0];
       group.children[i].children[0] = particle_node;
       startNewParticle(i);
       } 
    }

 function  t(value)
    {
    // value  SFTime
    delta = value - internT;
    for (i = 0; i < number_particles; i++) 
        {
        if (group.children[i].translation[1] < allowedHeightRange[0])
            startNewParticle(i);
        else if (group.children[i].translation[1] > allowedHeightRange[1])
            startNewParticle(i);
        else 
           {
           internVector[i].y -= delta * gravitation;

           internVector[i].x += delta * force.x;
           internVector[i].y += delta * force.y;
           internVector[i].z += delta * force.z;


           internPosition[i].x += internVector[i].x * delta;
           internPosition[i].y += internVector[i].y * delta;
           internPosition[i].z += internVector[i].z * delta;
           }
        group.children[i].translation[0] = internPosition[i].x;
        group.children[i].translation[1] = internPosition[i].y;
        group.children[i].translation[2] = internPosition[i].z;
        }
    internT = value;
    }



 function  force_in(value)
    {
    // value  SFVec3f
    force = value;
    }

    "
    ]
  }

DEF TimeSensor1 TimeSensor 
  {
  loop TRUE
  }

ROUTE TimeSensor1.time TO Script1.t

