<?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>
<!-- ROUTE information for PlaneSensorPosition node:  [from trackPoint_changed to TrObjectDirect.translation ] [from trackPoint_changed to PositionDamperNode.set_destination ] [from trackPoint_changed to PositionChaserNode.set_destination ] -->
<PlaneSensor DEF='PlaneSensorPositiondescription='touch to activate'/>
<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='PlaneSensorPositionfromField='trackPoint_changedtoNode='TrObjectDirecttoField='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='PositionDamperNode'/>
<ROUTE fromNode='PlaneSensorPositionfromField='trackPoint_changedtoNode='PositionDamperNodetoField='set_destination'/>
<ROUTE fromNode='PositionDamperNodefromField='value_changedtoNode='TrObjectDamperedtoField='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.5'/>
<ROUTE fromNode='PlaneSensorPositionfromField='trackPoint_changedtoNode='PositionChaserNodetoField='set_destination'/>
<ROUTE fromNode='PositionChaserNodefromField='value_changedtoNode='TrObjectFollowedtoField='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='1'/>
</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>
<!-- ROUTE information for ScrBtnMgr node:  [from BtnDamper.isOn to BtnDamperIsOn ] [from BtnChaser.isOn to BtnChaserIsOn ] [from WcDamper to SwObjectDampered.whichChoice ] [from WcChaser to SwObjectFollowed.whichChoice ] [from WcDamper to SwDamperTrail.whichChoice ] [from WcChaser to SwChaserTrail.whichChoice ] -->
<Script DEF='ScrBtnMgr'>
<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='BtnDamperfromField='isOntoNode='ScrBtnMgrtoField='BtnDamperIsOn'/>
<ROUTE fromNode='BtnChaserfromField='isOntoNode='ScrBtnMgrtoField='BtnChaserIsOn'/>
<ROUTE fromNode='ScrBtnMgrfromField='WcDampertoNode='SwObjectDamperedtoField='whichChoice'/>
<ROUTE fromNode='ScrBtnMgrfromField='WcChasertoNode='SwObjectFollowedtoField='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='TmrTrailfromField='cycleTimetoNode='ScrTrailertoField='Tick'/>
<ROUTE fromNode='TrObjectDamperedfromField='translationtoNode='ScrTrailertoField='DamperPos'/>
<ROUTE fromNode='TrObjectFollowedfromField='translationtoNode='ScrTrailertoField='ChaserPos'/>
<ROUTE fromNode='ScrBtnMgrfromField='WcDampertoNode='SwDamperTrailtoField='whichChoice'/>
<ROUTE fromNode='ScrBtnMgrfromField='WcChasertoNode='SwChaserTrailtoField='whichChoice'/>
</Scene>
</X3D>
<!--

Index for ProtoDeclare definition : ToggleButton

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 image : Viewpoint_1
-->

<!-- Color key: <X3dNode DEF='idName' field='value'/> matches <XmlElement DEF='idName' attribute='value'/>
(Light blue background: behavior node) (Grey background: inserted documentation) (Magenta background: X3D Extensibility)
    <Prototype name='ProtoName'> <field name='fieldName'/> </Prototype> -->

<!-- Additional help information about X3D scenes: X3D Resources, X3D Scene Authoring Hints and X3D Tooltips -->