X3D Model Documentation: PositionInterpolator2dPrototype.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='PositionInterpolator2dPrototype.x3d'/>
  6            <meta name='descriptioncontent='PositionInterpolator2D prototype declaration to pairwise interpolate across an array of Vector2Float/SFVec2f values to produce a single Vector2Float value - click text to see example.'/>
  7            <meta name='creatorcontent='Don Brutzman, Jeff Weekley, Jane Wu'/>
  8            <meta name='createdcontent='16 October 2001'/>
  9            <meta name='modifiedcontent='20 January 2020'/>
 10            <meta name='referencecontent='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/concepts.html#4.6.8'/>
 11            <meta name='referencecontent='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#CoordinateInterpolator'/>
 12            <meta name='subjectcontent='PositionInterpolator2D'/>
 13            <meta name='identifiercontent='https://www.web3d.org/x3d/content/examples/Basic/development/PositionInterpolator2dPrototype.x3d'/>
 14            <meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
 15            <meta name='licensecontent='../license.html'/>
 16       </head>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->
<!-- to top Index for DEF nodes: InterpolationScript, KeyHolder, KeyValueHolder, SilenceWarnings

Index for ProtoDeclare definition: PositionInterpolator2D
-->
 17       <Scene>
 18            <WorldInfo title='PositionInterpolator2dPrototype.x3d'/>
 19            <ProtoDeclare name='PositionInterpolator2Dappinfo='Provide interpolation capability for Vector2Float/SFVec2f values' documentation='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/concepts.html#4.6.8'>
 20                 <ProtoInterface>
 21                      <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.'>
 22                           <!-- Regular interpolator-style input -->
 23                      </field>
 24                      <field name='set_keytype='MFFloataccessType='inputOnly'/>
 25                      <field name='keytype='MFFloataccessType='inputOutput'
                     appinfo='keyValue holds the array of Vector2FloatArrays that match each animation key.'>
 26                           <!-- initial value is [] null array -->
 27                      </field>
 28                      <field name='key_changedtype='MFFloataccessType='outputOnly'
                     appinfo='Array sequentially increasing typically [0..1]. Must have the same number of keys as keyValues.'/>
 29                      <field name='set_keyValuetype='MFVec2faccessType='inputOnly'
                     appinfo='Array of integer values. Must have the same number of keys as keyValues.'/>
 30                      <field name='keyValuetype='MFVec2faccessType='inputOutput'
                     appinfo='keyValue holds the array of Vector2Float values that match each animation key.'>
 31                           <!-- initial value is [] null array -->
 32                      </field>
 33                      <field name='keyValue_changedtype='MFVec2faccessType='outputOnly'
                     appinfo='Array of integer values. Must have the same number of keys as keyValues.'/>
 34                      <field name='value_changedtype='SFVec2faccessType='outputOnly'
                     appinfo='The interpolator function averages between respective keyValue Vector2Floats resulting in a Vector2Float value_changed eventOut with the same timestamp as the set_fraction event.'>
 35                           <!-- Regular interpolator-style output -->
 36                      </field>
 37                 </ProtoInterface>
 38                 <ProtoBody>
 39                      <Group>
 40                           <Switch whichChoice='-1'>
 41 
                              <!-- ScalarInterpolator KeyHolder is a DEF node that has 1 USE node: USE_1 -->
                              <ScalarInterpolator DEF='KeyHolder'>
 42                                     <IS>
 43                                          <connect nodeField='keyprotoField='key'/>
 44                                     </IS>
 45                                </ScalarInterpolator>
 46                                <Shape>
 47                                     <IndexedFaceSet>
 48 
                                        <!-- TextureCoordinate KeyValueHolder is a DEF node that has 1 USE node: USE_1 -->
                                        <TextureCoordinate DEF='KeyValueHolder'>
 49                                               <IS>
 50                                                    <connect nodeField='pointprotoField='keyValue'/>
 51                                               </IS>
 52                                          </TextureCoordinate>
 53                                     </IndexedFaceSet>
 54                                     <Appearance DEF='SilenceWarnings'/>
 55                                </Shape>
 56                           </Switch>
 57                           <Script DEF='InterpolationScriptdirectOutput='true'>
 58                                <!-- Regular interpolator-style input -->
 59                                <field name='set_fractiontype='SFFloataccessType='inputOnly'/>
 60                                <field name='fractiontype='SFFloatvalue='0accessType='initializeOnly'
                               appinfo='local variable'/>
 61                                <field name='set_keytype='MFFloataccessType='inputOnly'/>
 62                                <field name='keyHolderNodetype='SFNodeaccessType='initializeOnly'>
 63                                     <ScalarInterpolator USE='KeyHolder'/>
 64                                </field>
 65                                <field name='key_changedtype='MFFloataccessType='outputOnly'/>
 66                                <field name='set_keyValuetype='MFVec2faccessType='inputOnly'/>
 67                                <field name='keyValueHolderNodetype='SFNodeaccessType='initializeOnly'>
 68                                     <TextureCoordinate USE='KeyValueHolder'/>
 69                                </field>
 70                                <field name='keyValue_changedtype='MFVec2faccessType='outputOnly'/>
 71                                <!-- Regular interpolator-style output -->
 72                                <field name='value_changedtype='SFVec2faccessType='outputOnly'/>
 73                                <IS>
 74                                     <connect nodeField='set_fractionprotoField='set_fraction'/>
 75                                     <connect nodeField='set_keyprotoField='set_key'/>
 76                                     <connect nodeField='key_changedprotoField='key_changed'/>
 77                                     <connect nodeField='set_keyValueprotoField='set_keyValue'/>
 78                                     <connect nodeField='keyValue_changedprotoField='keyValue_changed'/>
 79                                     <connect nodeField='value_changedprotoField='value_changed'/>
 80                                </IS>
  <![CDATA[
            
ecmascript:

// internal global persistent variables
var previousFraction;
var previousFractionIndex;
var blockSize;
var outputArray;

var traceEnabled = false;

function tracePrint (outputString)
{
	if (traceEnabled) Browser.println ('[PositionInterpolator2d]' + outputString);
}
function alwaysPrint (outputString)
{
	Browser.println ('[PositionInterpolator2d]' + outputString);
}
function initialize ()
{
	key      = keyHolderNode.key;
	keyValue = keyValueHolderNode.point;
	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 =  keyValue.length/key.length;
	tracePrint ('blockSize=' + blockSize);
	if (blockSize != 1)
	{
	  alwaysPrint ('*** warning:  check sizes of key and keyValue, should be identical!');
	}
	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 < key.length; index++)
	{
		if ((key[index] < 0) || (key[index] > 1))
		{
		   alwaysPrint ('*** warning:  key[' + index + '] =' + key[index] + ', out of range [0..1]');
		}
	}
}

function set_fraction (inputFloat, timestamp) {
	fraction = inputFloat;
	outputResult = new SFVec2f ();
	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 = key.length - 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)');
		// update outputResult with final keyValue
		outputResult = keyValue[keyValue.length];

		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 outputResult with corresponding keyValue
		outputResult = keyValue[previousFractionIndex];
	}
	else // calculate value_changed by interpolating between adjacent keyValue arrays
	{
		partialFraction = fraction                     - key[previousFractionIndex];
		deltaFraction   = key[previousFractionIndex+1] - key[previousFractionIndex];
		percentFraction = partialFraction / deltaFraction;
	//	tracePrint ('deltaFraction   =' + deltaFraction);
	//	tracePrint ('partialFraction =' + partialFraction);
		tracePrint ('percentFraction =' + percentFraction);
		// no arithmetic operators provided for SFVec2f, treat element by element
		nextKeyValue  = keyValue[previousFractionIndex + 1];
		priorKeyValue = keyValue[previousFractionIndex];
		tracePrint (' nextKeyValue =' + nextKeyValue);
		tracePrint ('priorKeyValue =' + priorKeyValue);
		deltaKeyValue = new SFVec2f (	nextKeyValue[0] - priorKeyValue[0],
						nextKeyValue[1] - priorKeyValue[1]);
		//	tracePrint ('deltaKeyValue =' + deltaKeyValue);
		// update outputResult
		outputResult[0] = keyValue[previousFractionIndex][0]
			        + percentFraction * deltaKeyValue[0];
		outputResult[1] = keyValue[previousFractionIndex][1]
			        + percentFraction * deltaKeyValue[1];
	}
	value_changed = outputResult;
	previousFraction = fraction;
	tracePrint ('value_changed=' + value_changed);
}

function set_key (inputArray, timestamp) {
	key = inputArray;       // update key Vector2FloatArray
	keyHolderNode.key = key; // update holder
	initialize (timestamp); // reverify key, keyValue sizes
}

function set_keyValue (inputArray, timestamp) {
	keyValue = inputArray;  // update keyValue Vector2FloatArray
	keyValueHolderNode.point = keyValue; // update holder
	initialize (timestamp); // reverify key, keyValue sizes
}

          
]]>
 82                           </Script>
 83                      </Group>
 84                 </ProtoBody>
 85            </ProtoDeclare>
 86            <!-- ====================================== -->
 87            <!-- Example use -->
 88            <Anchor description='PositionInterpolator2D Example'   url=' "PositionInterpolator2dExample.x3d" "https://www.web3d.org/x3d/content/examples/Basic/development/PositionInterpolator2dExample.x3d" "PositionInterpolator2dExample.wrl" "https://www.web3d.org/x3d/content/examples/Basic/development/PositionInterpolator2dExample.wrl" '>
 89                 <Shape>
 90                      <Text string='"PositionInterpolator2dPrototype" "defines a prototype" "" "Click text to see" "PositionInterpolator2dExample" " scene"'>
 91                           <FontStyle justify='"MIDDLE" "MIDDLE"size='0.7'/>
 92                      </Text>
 93                      <Appearance>
 94                           <Material diffuseColor='1 1 0.2'/>
 95                      </Appearance>
 96                 </Shape>
 97            </Anchor>
 98       </Scene>
 99  </X3D>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->
<!-- to top Index for DEF nodes: InterpolationScript, KeyHolder, KeyValueHolder, SilenceWarnings

Index for ProtoDeclare definition: PositionInterpolator2D
-->
X3D Tooltips element index: Anchor, Appearance, connect, field, FontStyle, Group, head, IndexedFaceSet, IS, Material, meta, ProtoBody, ProtoDeclare, ProtoInterface, ScalarInterpolator, Scene, Script, Shape, Switch, Text, TextureCoordinate, WorldInfo, X3D, plus documentation for accessType definitions, type definitions, XML data types, and field types

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

<!-- Color-coding 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. -->