<?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 name='titlecontent=' TestPositionFollower.x3d '/>
<meta name='descriptioncontent='X3D Follower example'/>
<meta name='creatorcontent='Herbert Stocker'/>
<meta name='translatorcontent='Don Brutzman'/>
<meta name='createdcontent='18 April 2006'/>
<meta name='translatedcontent='2 December 2011'/>
<meta name='modifiedcontent='20 October 2019'/>
<meta name='referencecontent='originals/test_PosFollower.wrl'/>
<meta name='referencecontent=' Stocker_06_Followers.pdf '/>
<meta name='referencecontent=' http://www.hersto.com/Publications/Followers '/>
<meta name='requirescontent='X3D version 3.2 or greater'/>
<meta name='subjectcontent='X3D Follower Chaser Damper'/>
<meta name=' warning content=' under development, instantReality works but BS Contact fails silently '/>
<meta name='referencecontent=' https://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/components/followers.html '/>
<meta name='referencecontent=' https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html '/>
<meta name='identifiercontent=' https://www.web3d.org/x3d/content/examples/Basic/Followers/TestPositionFollower.x3d '/>
<meta name='generatorcontent=' Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html '/>
<meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!-- -->
<Scene>
<WorldInfo title='TestPositionFollower.x3d'/>
<Viewpoint description='TestPositionFollowerfieldOfView='0.716position='0.0 0.0 15.0'/>
<NavigationInfo type='"NONE"'/>
<Group>

<Transform translation='0.0 0.0 -0.05'>
<Shape>
<Appearance>
<Material ambientIntensity='0.0333diffuseColor='0.0 0.0 0.0emissiveColor='0.177 0.19 0.208shininess='0.54'/>
</Appearance>
<Box size='10.0 10.0 0.1'/>
</Shape>
</Transform>
</Group>
<!-- ROUTE information for TrObjectDirect node:  [from PlaneSensorPosition.trackPoint_changed to translation ] -->
<Transform DEF='TrObjectDirectscale='0.8 0.8 0.8'>
<Shape>
<Appearance>
<Material ambientIntensity='0.0333diffuseColor='0.02 0.24 0.53emissiveColor='0.01 0.12 0.27shininess='0.54specularColor='0.32 0.4 0.4'/>
</Appearance>
<Sphere DEF='GeomObjectradius='0.3'/>
</Shape>
</Transform>
< ROUTE  fromNode=' PlaneSensorPosition' fromField='trackPoint_changed' toNode=' TrObjectDirect' toField='translation'/>
<!-- ROUTE information for SwObjectDampered node:  [from ScrBtnMgr.WcDamper to whichChoice ] -->
<Switch DEF='SwObjectDamperedwhichChoice='0'>
<!-- ROUTE information for TrObjectDampered node:  [from PositionDamperNode.value_changed to translation ] [from translation to ScrTrailer.DamperPos ] -->
<Transform DEF='TrObjectDampered'>
<Shape>
<Appearance DEF='AppObjectDampered'>
<Material ambientIntensity='0.0333diffuseColor='0.53 0.02 0.24emissiveColor='0.27 0.01 0.12shininess='0.54specularColor='0.4 0.32 0.4'/>
</Appearance>
<Sphere USE=' GeomObject'/>
</Shape>
</Transform>
</Switch>
<!-- ROUTE information for PositionDamperNode node:  [from PlaneSensorPosition.trackPoint_changed to set_destination ] [from value_changed to TrObjectDampered.translation ] -->
<PositionDamper DEF='PositionDamperNodecontainerField='children'/>

< ROUTE  fromNode=' PlaneSensorPosition' fromField='trackPoint_changed' toNode=' PositionDamperNode' toField='set_destination'/>
< ROUTE  fromNode=' PositionDamperNode' fromField='value_changed' toNode=' TrObjectDampered' toField='translation'/>
<!-- ROUTE information for SwObjectFollowed node:  [from ScrBtnMgr.WcChaser to whichChoice ] -->
<Switch DEF='SwObjectFollowedwhichChoice='0'>
<!-- ROUTE information for TrObjectFollowed node:  [from PositionChaserNode.value_changed to translation ] [from translation to ScrTrailer.ChaserPos ] -->
<Transform DEF='TrObjectFollowed'>
<Shape>
<Appearance DEF='AppObjectFollowed'>
<Material ambientIntensity='0.0333diffuseColor='0.24 0.53 0.02emissiveColor='0.12 0.27 0.01shininess='0.54specularColor='0.4 0.4 0.32'/>
</Appearance>
<Sphere USE=' GeomObject'/>
</Shape>
</Transform>
</Switch>
<!-- ROUTE information for PositionChaserNode node:  [from PlaneSensorPosition.trackPoint_changed to set_destination ] [from value_changed to TrObjectFollowed.translation ] -->
<PositionChaser DEF='PositionChaserNodeduration='1.5containerField='children'/>

< ROUTE  fromNode=' PlaneSensorPosition' fromField='trackPoint_changed' toNode=' PositionChaserNode' toField='set_destination'/>
< ROUTE  fromNode=' PositionChaserNode' fromField='value_changed' toNode=' TrObjectFollowed' toField='translation'/>
<ProtoDeclare name='ToggleButton'>
<ProtoInterface>
<field name='HottColortype='SFColorvalue='0.8 0.8 0.3accessType='initializeOnly'/>
<field name='initiallyOntype='SFBoolvalue='falseaccessType='initializeOnly'/>
<field name='ColdColortype='SFColorvalue='0.2 0.2 0.0accessType='initializeOnly'/>
<field name='isOntype='SFBoolaccessType='outputOnly'/>
</ProtoInterface>
<ProtoBody>
<Transform scale='0.4 0.4 0.4'>
<TouchSensor DEF='TouchPositiondescription='move ball to demonstrate PositionChaser2D, PositionDamper2D'/>
<Shape DEF='ShRect'>
<Appearance>
<Material DEF='MatambientIntensity='0.04diffuseColor='0.0 0.0 0.0shininess='0.11'/>
</Appearance>
<IndexedFaceSet coordIndex='0 1 2 3 -1'>
<Coordinate point='-1 -1 0 1 -1 0 1 1 0 -1 1 0'/>
</IndexedFaceSet>
</Shape>
</Transform>
<Script DEF='ScrToggleButton'>
<field name='TS_Touchedtype='SFTimeaccessType='inputOnly'/>
<field name='Colortype='SFColoraccessType='outputOnly'/>
<field name='isOntype='SFBoolaccessType='outputOnly'/>
<field name='ColdColortype='SFColoraccessType='initializeOnly'/>
<field name='Tautype='SFFloataccessType='outputOnly'/>
<field name='initiallyOntype='SFBoolaccessType='initializeOnly'/>
<field name='DamperSTheretype='SFBoolaccessType='inputOnly'/>
<field name='HottColortype='SFColoraccessType='initializeOnly'/>
<IS>
<connect nodeField='isOnprotoField='isOn'/>
<connect nodeField='ColdColorprotoField='ColdColor'/>
<connect nodeField='initiallyOnprotoField='initiallyOn'/>
<connect nodeField='HottColorprotoField='HottColor'/>
</IS>
<![CDATA[
          
ecmascript:

function DamperSThere()
{
    activate(initiallyOn);
}

function activate(a)
{
    isOn= a;
    Tau=  a? .1 : .2;
    Color= a? HottColor : ColdColor;
}

function set_id(i)
{
    id= i;
}

function TS_Touched()
{
    activate(!isOn);
}

        
]]>
</Script>
<ColorDamper DEF='ColorDamperNodeorder='1containerField='children'/>
</ProtoBody>
</ProtoDeclare>
<Transform translation='-5.7 4.0 0.0'>
<!-- ROUTE information for BtnDamper node:  [from isOn to ScrBtnMgr.BtnDamperIsOn ] -->
<ProtoInstance name='ToggleButtonDEF='BtnDamper'>
<fieldValue name='HottColorvalue='0.8 0.03 0.36'/>
<fieldValue name='initiallyOnvalue='true'/>
<fieldValue name='ColdColorvalue='0.2 0.0080 0.09'/>
</ProtoInstance>
</Transform>
<Transform translation='-8.0 3.9 0.0'>
<Shape>
<Appearance DEF='AppLabels'>
<Material diffuseColor='0.0 0.0 0.0emissiveColor='0.8 0.8 0.8'/>
</Appearance>
<Text string='"Damper"'>
<FontStyle DEF='FntLabelsfamily='"Arial" "SANS"size='0.5'/>
</Text>
</Shape>
</Transform>
<Transform translation='-5.7 2.8 0.0'>
<!-- ROUTE information for BtnChaser node:  [from isOn to ScrBtnMgr.BtnChaserIsOn ] -->
<ProtoInstance name='ToggleButtonDEF='BtnChaser'>
<fieldValue name='HottColorvalue='0.36 0.8 0.03'/>
<fieldValue name='initiallyOnvalue='true'/>
<fieldValue name='ColdColorvalue='0.09 0.2 0.0080'/>
</ProtoInstance>
</Transform>
<Transform translation='-8.0 2.7 0.0'>
<Shape>
<Appearance USE=' AppLabels'/>
<Text string='"Chaser"'>
<FontStyle USE=' FntLabels'/>
</Text>
</Shape>
</Transform>
<field name='BtnChaserIsOntype='SFBoolaccessType='inputOnly'/>
<field name='WcDampertype='SFInt32accessType='outputOnly'/>
<field name='WcChasertype='SFInt32accessType='outputOnly'/>
<field name='BtnDamperIsOntype='SFBoolaccessType='inputOnly'/>
<![CDATA[
      
ecmascript:

function BtnDamperIsOn(on)
{
    WcDamper= on? 0:-1;
}
function BtnChaserIsOn(on)
{
    WcChaser= on? 0:-1;
}

    
]]>
</Script>
< ROUTE  fromNode=' BtnDamper' fromField='isOn' toNode=' ScrBtnMgr' toField='BtnDamperIsOn'/>
< ROUTE  fromNode=' BtnChaser' fromField='isOn' toNode=' ScrBtnMgr' toField='BtnChaserIsOn'/>
< ROUTE  fromNode=' ScrBtnMgr' fromField='WcDamper' toNode=' SwObjectDampered' toField='whichChoice'/>
< ROUTE  fromNode=' ScrBtnMgr' fromField='WcChaser' toNode=' SwObjectFollowed' toField='whichChoice'/>
<!-- ROUTE information for SwDamperTrail node:  [from ScrBtnMgr.WcDamper to whichChoice ] -->
<Switch DEF='SwDamperTrailwhichChoice='0'>
<Group DEF='GrDamperTrail'/>
</Switch>
<!-- ROUTE information for SwChaserTrail node:  [from ScrBtnMgr.WcChaser to whichChoice ] -->
<Switch DEF='SwChaserTrailwhichChoice='0'>
<Group DEF='GrChaserTrail'/>
</Switch>
<!-- ROUTE information for TmrTrail node:  [from cycleTime to ScrTrailer.Tick ] -->
<TimeSensor DEF='TmrTrailcycleInterval='0.020000000000000004loop='true'/>

<!-- ROUTE information for ScrTrailer node:  [from TmrTrail.cycleTime to Tick ] [from TrObjectDampered.translation to DamperPos ] [from TrObjectFollowed.translation to ChaserPos ] -->
<Script DEF='ScrTrailerdirectOutput='true'>
<field name='cShapeDamperTrailPointtype='SFNodeaccessType='initializeOnly'>
<Shape>
<Appearance USE=' AppObjectDampered'/>
<Sphere DEF='GeomTrailradius='0.1'/>
</Shape>
</field>
<field name='lastDamperPostype='SFVec3fvalue='0.0 0.0 0.0accessType='initializeOnly'/>
<field name='ChaserTrailstype='MFNodeaccessType='initializeOnly'>
<!-- no initialization nodes since this is a local field to hold content -->
</field>
<field name='cShapeChaserTrailPointtype='SFNodeaccessType='initializeOnly'>
<Shape>
<Appearance USE=' AppObjectFollowed'/>
<Sphere USE=' GeomTrail'/>
</Shape>
</field>
<field name='DamperTrailstype='MFNodeaccessType='initializeOnly'>
<!-- no initialization nodes since this is a local field to hold content -->
</field>
<field name='GrChaserTrailtype='SFNodeaccessType='initializeOnly'>
<Group USE=' GrChaserTrail'/>
</field>
<field name='ChaserPostype='SFVec3faccessType='inputOnly'/>
<field name='cNumTrailPointstype='SFInt32value='35accessType='initializeOnly'/>
<field name='lastChaserPostype='SFVec3fvalue='0.0 0.0 0.0accessType='initializeOnly'/>
<field name='Ticktype='SFTimeaccessType='inputOnly'/>
<field name='DamperPostype='SFVec3faccessType='inputOnly'/>
<field name='GrDamperTrailtype='SFNodeaccessType='initializeOnly'>
<Group USE=' GrDamperTrail'/>
</field>
<![CDATA[
      
ecmascript:

function initialize()
{
    DamperTrails.length=
    ChaserTrails.length= cNumTrailPoints;

    for(var C= 0; C<cNumTrailPoints; C++ )
    {
        DamperTrails[C]= new SFNode('Transform{}');
        ChaserTrails[C]= new SFNode('Transform{}');

        DamperTrails[C].children[0]= cShapeDamperTrailPoint;
        ChaserTrails[C].children[0]= cShapeChaserTrailPoint;
    }

    GrDamperTrail.children= DamperTrails;
    GrChaserTrail.children= ChaserTrails;
}
function DamperPos(Pos)
{
    lastDamperPos= Pos;
}
function ChaserPos(Pos)
{
    lastChaserPos= Pos;
}
function Tick()
{
    for(var C= cNumTrailPoints - 1; C>0; C-- )
    {
        DamperTrails[C].translation= DamperTrails[  C - 1].translation;
        ChaserTrails[C].translation= ChaserTrails[C - 1].translation;
    }

    DamperTrails[0].translation= lastDamperPos;
    ChaserTrails[0].translation= lastChaserPos;
}

    
]]>
</Script>
< ROUTE  fromNode=' TmrTrail' fromField='cycleTime' toNode=' ScrTrailer' toField='Tick'/>
< ROUTE  fromNode=' TrObjectDampered' fromField='translation' toNode=' ScrTrailer' toField='DamperPos'/>
< ROUTE  fromNode=' TrObjectFollowed' fromField='translation' toNode=' ScrTrailer' toField='ChaserPos'/>
< ROUTE  fromNode=' ScrBtnMgr' fromField='WcDamper' toNode=' SwDamperTrail' toField='whichChoice'/>
< ROUTE  fromNode=' ScrBtnMgr' fromField='WcChaser' toNode=' SwChaserTrail' toField='whichChoice'/>
</Scene>
</X3D>
<!--

to top <!-- Event Graph ROUTE Table shows event connections -->
 
<!-- Index for DEF nodes: AppLabels, AppObjectDampered, AppObjectFollowed, BtnChaser, BtnDamper, ColorDamperNode, FntLabels, GeomObject, GeomTrail, GrChaserTrail, GrDamperTrail, Mat, PlaneSensorPosition, PositionChaserNode, PositionDamperNode, ScrBtnMgr, ScrToggleButton, ScrTrailer, ShRect, SwChaserTrail, SwDamperTrail, SwObjectDampered, SwObjectFollowed, TmrTrail, TouchPosition, TrObjectDampered, TrObjectDirect, TrObjectFollowed

Index for Viewpoint node: Viewpoint_1

Index for ProtoDeclare definition: ToggleButton
-->

Event Graph ROUTE Table entries with 14 ROUTE connections 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.

TmrTrail
TimeSensor
cycleTime
SFTime

ROUTE
event to
(1)
ScrTrailer
Script
Tick
SFTime


      ScrTrailer
Script
No ROUTE connection found for output from this node.
Contains SFNode field with indirect access to another node. 


BtnChaser
ProtoInstance
isOn
SFBool

ROUTE
event to
(1)
ScrBtnMgr
Script
BtnChaserIsOn
SFBool

 
 
then
ScrBtnMgr
Script
WcChaser
SFInt32

ROUTE
event to
(2)
SwObjectFollowed
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcChaser
SFInt32

ROUTE
event to
(2)
SwChaserTrail
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcDamper
SFInt32

ROUTE
event to
(2)
SwObjectDampered
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcDamper
SFInt32

ROUTE
event to
(2)
SwDamperTrail
Switch
whichChoice
SFInt32


BtnDamper
ProtoInstance
isOn
SFBool

ROUTE
event to
(1)
ScrBtnMgr
Script
BtnDamperIsOn
SFBool

 
 
then
ScrBtnMgr
Script
WcChaser
SFInt32

ROUTE
event to
(2)
SwObjectFollowed
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcChaser
SFInt32

ROUTE
event to
(2)
SwChaserTrail
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcDamper
SFInt32

ROUTE
event to
(2)
SwObjectDampered
Switch
whichChoice
SFInt32
 
 
 
then
ScrBtnMgr
Script
WcDamper
SFInt32

ROUTE
event to
(2)
SwDamperTrail
Switch
whichChoice
SFInt32


PlaneSensorPosition
PlaneSensor
trackPoint_changed
SFVec3f

ROUTE
event to
(1)
TrObjectDirect
Transform
translation
SFVec3f
PlaneSensorPosition
PlaneSensor
trackPoint_changed
SFVec3f

ROUTE
event to
(1)
PositionDamperNode
PositionDamper
set_destination
SFVec3f

 
 
then
PositionDamperNode
PositionDamper
value_changed
SFVec3f

ROUTE
event to
(2)
TrObjectDampered
Transform
translation
SFVec3f

 
 
then
TrObjectDampered
Transform
translation
SFVec3f

ROUTE
event to
(3)
ScrTrailer
Script
DamperPos
SFVec3f
PlaneSensorPosition
PlaneSensor
trackPoint_changed
SFVec3f

ROUTE
event to
(1)
PositionChaserNode
PositionChaser
set_destination
SFVec3f

 
 
then
PositionChaserNode
PositionChaser
value_changed
SFVec3f

ROUTE
event to
(2)
TrObjectFollowed
Transform
translation
SFVec3f

 
 
then
TrObjectFollowed
Transform
translation
SFVec3f

ROUTE
event to
(3)
ScrTrailer
Script
ChaserPos
SFVec3f


-->

<!-- Online at
https://www.web3d.org/x3d/content/examples/Basic/Followers/TestPositionFollowerIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/Followers/TestPositionFollower.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)
    <ProtoInstance name='ProtoName'> <field name='fieldName'/> </ProtoInstance> -->

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