<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
<![CDATA[
ecmascript: // internal global persistent variables var previousFraction; var previousFractionIndex; var blockSize; var outputArray; function tracePrint (outputString) { var traceEnabled = false; if (traceEnabled) Browser.println ('[CoordinateInterpolator2D]' + outputString); } function alwaysPrint (outputString) { Browser.println ('[CoordinateInterpolator2D]' + 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 != 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 MFVec2f (); for (index = 0; index < blockSize; index++) { // dynamically grow outputArray to match initial block outputArray[index] = keyValue[index]; } 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)'); for (index = 0; index < blockSize; index++) { // update outputArray with final four keyValues outputArray[4 - index] = keyValue[keyValue.length - index]; } 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])'); for (index = 0; index < blockSize; index++) { // update outputArray - need to interpolate next outputArray[index] = keyValue[blockSize * (previousFractionIndex) + index]; } } 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); for (index = 0; index < blockSize; index++) { // no arithmetic operators provided for SFVec2f, treat element by element nextKeyValue = keyValue[blockSize * (previousFractionIndex + 1) + index]; priorKeyValue = keyValue[blockSize * (previousFractionIndex) + index]; deltaKeyValue = new SFVec2f ( nextKeyValue[0] - priorKeyValue[0], nextKeyValue[1] - priorKeyValue[1]); // tracePrint ('deltaKeyValue =' + deltaKeyValue); // update outputArray outputArray[index][0] = keyValue[blockSize * (previousFractionIndex) + index][0] + percentFraction * deltaKeyValue[0]; outputArray[index][1] = keyValue[blockSize * (previousFractionIndex) + index][1] + percentFraction * deltaKeyValue[1]; } } value_changed = outputArray; 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 key_changed = key; // eventOut } function set_keyValue (inputArray, timestamp) { keyValue = inputArray; // update keyValue Vector2FloatArray keyValueHolderNode.point = keyValue; // update holder initialize (timestamp); // reverify key, keyValue sizes keyValue_changed = keyValue; // eventOut }
]]>
Event Graph ROUTE Table with 0 ROUTE total, showing X3D event-model relationships for this scene.
Each row shows an event cascade that may occur during a single timestamp interval between frame renderings, as part of the X3D execution model.
InterpolationScript
Script |
No ROUTE connection found for output from this node. Contains SFNode field with indirect access to another node. |
<!--
Online at
https://www.web3d.org/x3d/content/examples/Basic/development/CoordinateInterpolator2dPrototypeIndex.html
-->
<!--
Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/development/CoordinateInterpolator2dPrototype.x3d
-->
<!--
Color legend: X3D terminology
<X3dNode
DEF='idName' field='value'/>
matches XML terminology
<XmlElement
DEF='idName' attribute='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>
-->
<!-- For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints. -->