X3D Model Documentation: ProjectileInterpolatorPrototype.x3d

  1  <?xml version="1.0" encoding="UTF-8"?>
  2 
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
  3  <X3D profile='Immersive' version='3.0 xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.0.xsd'>
  4       <head>
  5            <meta name='titlecontent='ProjectileInterpolatorPrototype.x3d'/>
  6            <meta name='descriptioncontent='A proto which simulates x-y plane projectile motion.'/>
  7            <meta name='creatorcontent='Ozan APAYDIN'/>
  8            <meta name='createdcontent='10 December 2001'/>
  9            <meta name='modifiedcontent='30 November 2024'/>
 10            <meta name='identifiercontent='https://www.web3d.org/x3d/content/examples/Basic/StudentProjects/ProjectileInterpolatorPrototype.x3d'/>
 11            <meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
 12            <meta name='licensecontent='../license.html'/>
 13       </head>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF node: ProjectileMotionTrackerScript

Index for ProtoDeclare definition: ProjectileInterpolator
-->
 14       <Scene>
 15            <WorldInfo title='ProjectileInterpolatorPrototype.x3d'/>
 16            <ProtoDeclare name='ProjectileInterpolatorappinfo='This prototype is a Projectile Motion Interpolator. It takes Inputs : Initial Velocity and Angle then calculates trajectory of the projectile on x-y plane according to given dt time and B_m. It outputs value_changed values(SFVec3f).'>
 17                 <ProtoInterface>
 18                      <field name='Vitype='SFFloatvalue='0.0accessType='initializeOnly'
                     appinfo='Initial Velocity value of the object.'/>
 19                      <field name='thetatype='SFFloatvalue='0.0accessType='initializeOnly'
                     appinfo='Launch Angle. The angle between horizantal and launch direction'/>
 20                      <field name='B_mtype='SFFloatvalue='0.00004accessType='initializeOnly'
                     appinfo='Proportional to drag force = B2/m'/>
 21                      <field name='dttype='SFFloatvalue='0.1accessType='initializeOnly'
                     appinfo='Time step.'/>
 22                      <field name='fractiontype='SFFloatvalue='0.05accessType='initializeOnly'
                     appinfo='SFFloat Values ranging [0..1].'/>
 23                      <field name='set_fractiontype='SFFloataccessType='inputOnly'
                     appinfo='The set_fraction eventIn receives an SFFloat event and causes the interpolator function to evaluate resulting in a value_changed eventOut with the same timestamp as the set_fraction event.'/>
 24                      <field name='set_thetatype='SFFloataccessType='inputOnly'
                     appinfo='Sets theta to the value of eventIn.'/>
 25                      <field name='set_Vitype='SFFloataccessType='inputOnly'
                     appinfo='Sets Vi to the value of eventIn.'/>
 26                      <field name='value_changedtype='SFVec3faccessType='outputOnly'
                     appinfo='The interpolator function eventOut results as Vector3Float.'/>
 27                 </ProtoInterface>
 28                 <ProtoBody>
 29                      <Script DEF='ProjectileMotionTrackerScript'>
 30                           <field name='Vitype='SFFloataccessType='initializeOnly'/>
 31                           <field name='thetatype='SFFloataccessType='initializeOnly'/>
 32                           <field name='B_mtype='SFFloataccessType='initializeOnly'/>
 33                           <field name='dttype='SFFloataccessType='initializeOnly'/>
 34                           <field name='fractiontype='SFFloataccessType='initializeOnly'
                          appinfo='In range [01]'/>
 35                           <field name='set_fractiontype='SFFloataccessType='inputOnly'/>
 36                           <field name='set_thetatype='SFFloataccessType='inputOnly'/>
 37                           <field name='set_Vitype='SFFloataccessType='inputOnly'/>
 38                           <field name='value_changedtype='SFVec3faccessType='outputOnly'/>
 39                           <IS>
 40                                <connect nodeField='ViprotoField='Vi'/>
 41                                <connect nodeField='thetaprotoField='theta'/>
 42                                <connect nodeField='B_mprotoField='B_m'/>
 43                                <connect nodeField='dtprotoField='dt'/>
 44                                <connect nodeField='fractionprotoField='fraction'/>
 45                                <connect nodeField='set_fractionprotoField='set_fraction'/>
 46                                <connect nodeField='set_thetaprotoField='set_theta'/>
 47                                <connect nodeField='set_ViprotoField='set_Vi'/>
 48                                <connect nodeField='value_changedprotoField='value_changed'/>
 49                           </IS>
  <![CDATA[
          
ecmascript:
var x;
var y;
var Vx;
var Vy;
var B_m;
var dt;
var blocksize;
var Vi;
var theta;

var key;
var keyValue;
var previousFraction;
var previousFractionIndex;
var blockSize;
var outputArray;

function tracePrint (outputString)
{
	var traceEnabled = true;
	if (traceEnabled) Browser.println ('[WaypointInterpolator]' + outputString);
}
function alwaysPrint (outputString)
{
	Browser.println ('[WaypointInterpolator]' + outputString);
}



function initialize() {
   key = new Array();
   keyValue = new MFVec3f();
   x = new Array();
   y = new Array();
   calculateTrajectory();

   previousFractionIndex = -1;
	previousFraction = 0;
	// check key array ranges [0..1] and is monotonically increasing
	// check that size of keyValue array is integer multiple of size of key array
	tracePrint ('key            =' + key);
	tracePrint ('key.length= ' + key.length);
	tracePrint ('keyValue=   ' + keyValue);
	tracePrint ('keyValue.length=' + keyValue.length);
	blockSize =  3; //keyValue.length/key.length;
	tracePrint ('blockSize=' + blockSize);
	if (blockSize != Math.round(blockSize))
	{
	  alwaysPrint ('*** warning:  blockSize not an integer multiple. check sizes of key and keyValue');
	}
	if (key[0] != 0)
	{
	  alwaysPrint ('*** warning:  key[0] != 0');
	}
	if (key[key.length-1] != 1)
	{
	  alwaysPrint ('*** warning:  key[' + (key.length - 1) + '] != 1, reset from' + key[key.length-1] + ' to 1');
	  key[key.length-1] = 1;
	}
	for (index = 0; index < blockSize; index++)
	{
		if ((key[index] < 0) || (key[index] > 1))
		{
		   alwaysPrint ('*** warning:  key[' + index + '] =' + key[index] + ', out of range [0..1]');
		}
	}
	// instantiate default array, later computations just update it
	outputArray = new SFVec3f();
	outputArray = keyValue[0];
	tracePrint ('initial outputArray=' + outputArray);

}

function set_fraction (inputFloat, timestamp) {
	fraction = inputFloat;
	tracePrint ('previousFractionIndex=' + previousFractionIndex
		 + ', fraction=' + fraction + ', previousFraction=' + previousFraction);

	if (fraction < 0)
	{
		tracePrint ('*** illegal fraction' + fraction + ' set to 0');
		fraction = 0;
		previousFractionIndex = 0; // first
	}
	else if (fraction > 1)
	{
		alwaysPrint ('*** illegal fraction' + fraction + ' set to 1');
		fraction = 1;
		previousFractionIndex = blockSize - 1; // last
	}
	else if (previousFractionIndex == -1)
	{
		previousFractionIndex = 0; // first
		tracePrint ('previousFractionIndex initialized for first event');
	}
	else if ((fraction >= previousFraction) && (fraction >= key[previousFractionIndex+1]))
	{
		previousFractionIndex++;
	}
	else if (fraction < previousFraction) // regress, or loop repeat without reaching one
	{

		previousFractionIndex = 0;
		while ((fraction >= key[previousFractionIndex+1]) && (previousFractionIndex < blockSize))
		{
			previousFractionIndex++;
		}
		tracePrint ('reset/reincrement previousFractionIndex to' + previousFractionIndex);
	}

	if (fraction == 1) // use final block
	{
		tracePrint ('(fraction == 1)');


        	outputArray = keyValue[(keyValue.length -1)];

		previousFractionIndex = -1; // setup for restart
		tracePrint ('finished final fraction==1 block');
	}
	// when fraction matches index, calculate value_changed from corresponding keyValue array
	else if (fraction == key[previousFractionIndex])
	{
		tracePrint ('(fraction == key[previousFractionIndex])');


		// update outputArray - need to interpolate next
		outputArray = keyValue[previousFractionIndex];

	}
        else {

              delta = key[previousFractionIndex + 1] -  key[previousFractionIndex];
              differ = fraction - key[previousFractionIndex];
              percentDiffer = differ / delta;

              valueDelta = new SFVec3f();
              for(index = 0; index < blockSize; index++) {
                 valueDelta[index] =  keyValue[(previousFractionIndex + 1)][index] - keyValue[previousFractionIndex][index];
                 outputArray[index]  = keyValue[previousFractionIndex][index] + valueDelta[index] * percentDiffer;
		 Browser.println ('valueDelta' + valueDelta[index]);
                 Browser.println ('perDiffer' + percentDiffer);
              }

        }

	value_changed = outputArray;
	previousFraction = fraction;
	tracePrint ('value_changed=' + value_changed);

}


function set_Vi(initialVelocity, timeStamp) {
   Vi = initialVelocity;
   initialize(timeStamp);
}


function set_theta(angle, timeStamp) {
   theta = angle;
   initialize(timeStamp);
}


function calculateTrajectory() {

   x[0] = 0;
   y[0] = 0;

   var timeKeys = new Array();
   timeKeys[0] = 0.0;

   //convert degree to radian
   angle = Math.PI * theta / 180;

   Vx = Vi * Math.cos(angle);
   Vy = Vi * Math.sin(angle);

   var i = 0;

   do {
      i = i + 1;
      timeKeys[i] = timeKeys[i - 1] + dt;
      Browser.println ('timeKeys' + timeKeys[i]);
      x[i] = x[i - 1] + Vx * dt;
      y[i] = y[i - 1] + Vy * dt;


      f = B_m * Math.sqrt(Vx * Vx + Vy * Vy) * Math.exp(-y[i] / 0.0001);

      Vy = Vy - 9.8 * dt - f * Vy * dt;
      Vx = Vx - f * Vx * dt;
      Browser.println ('Vy' + Vy);
   }while(y[i] > 0);
   Browser.println ('Im here' + x.length);

   //interpolate to find landing point
   var a = -y[i] / y[i-1];
   x[i] = (x[i] + a * x[i-1]) / (1+a);
   y[i] = 0;

   //copy x, y values to keyValues
   copyToKeyValues();
   //finding keys
   for(j = 0; j < timeKeys.length; j++) {
      key[j] = timeKeys[j] / timeKeys[timeKeys.length - 1];
      Browser.println (' ' + key[j]);

   }

}

function copyToKeyValues() {
   for(i = 0; i < x.length; i++) {
     Browser.println ('x' + x[i]);
      keyValue[i][0] = x[i];
      keyValue[i][1] = y[i];
      keyValue[i][2] = 0;
   Browser.println ('keyValue' + i + ' ' + keyValue[i][0]);
   }

}

        
]]>
 51                      </Script>
 52                 </ProtoBody>
 53            </ProtoDeclare>
 54            <!-- ==================== -->
 55            <Anchor description='ProjectileInterpolatorArenaparameter='"target=_blank"'   url=' "ProjectileInterpolatorArena.wrl" "https://www.web3d.org/x3d/content/examples/Basic/StudentProjects/ProjectileInterpolatorArena.wrl" "ProjectileInterpolatorArena.x3d" "https://www.web3d.org/x3d/content/examples/Basic/StudentProjects/ProjectileInterpolatorArena.x3d" '>
 56                 <Shape>
 57                      <Text string='"ProjectileInterpolatorPrototype" "defines a prototype" "" "Click on this text to see" "ProjectileInterpolatorArena" " scene"'>
 58                           <FontStyle justify='"MIDDLE" "MIDDLE"size='0.7'/>
 59                      </Text>
 60                      <Appearance>
 61                           <Material diffuseColor='1 1 0.2'/>
 62                      </Appearance>
 63                 </Shape>
 64            </Anchor>
 65            <PositionInterpolator/>
 66       </Scene>
 67  </X3D>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF node: ProjectileMotionTrackerScript

Index for ProtoDeclare definition: ProjectileInterpolator
-->
X3D Tooltips element index: Anchor, Appearance, connect, field, FontStyle, head, IS, Material, meta, PositionInterpolator, ProtoBody, ProtoDeclare, ProtoInterface, Scene, Script, Shape, Text, WorldInfo, X3D, accessType and type, XML data types, field types

-->
<!-- Online at
https://www.web3d.org/x3d/content/examples/Basic/StudentProjects/ProjectileInterpolatorPrototypeIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/StudentProjects/ProjectileInterpolatorPrototype.x3d -->

<!-- Color legend: X3D terminology <X3dNode  DEF='idNamefield='value'/> matches XML terminology <XmlElement  DEF='idNameattribute='value'/>
(Light-blue background: event-based behavior node or statement) (Grey background inside box: inserted documentation) (Magenta background: X3D Extensibility)
    <ProtoDeclare name='ProtoName'> <field name='fieldName'/> ProtoDeclare> -->

to top <!-- For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints. -->