package Basic.Followers;

import org.web3d.x3d.jsail.Core.*;
import org.web3d.x3d.jsail.EnvironmentalEffects.*;
import org.web3d.x3d.jsail.EnvironmentalSensor.*;
import org.web3d.x3d.jsail.fields.*;
import org.web3d.x3d.jsail.Followers.*;
import org.web3d.x3d.jsail.Geometry3D.*;
import org.web3d.x3d.jsail.Grouping.*;
import org.web3d.x3d.jsail.Lighting.*;
import org.web3d.x3d.jsail.Navigation.*;
import org.web3d.x3d.jsail.PointingDeviceSensor.*;
import org.web3d.x3d.jsail.Rendering.*;
import org.web3d.x3d.jsail.Scripting.*;
import org.web3d.x3d.jsail.Shape.*;
import org.web3d.x3d.jsail.Texturing.*;
import org.web3d.x3d.jsail.Time.*;

// Javadoc metadata annotations follow, see below for X3DJSAIL Java source code.
/**
 * <p> X3D Follower example. </p>
 <p> Related links: Catalog page <a href="../../../Followers/ThirdPersonViewFollowerIndex.html" target="_blank">ThirdPersonViewFollower</a>,  source <a href="../../../Followers/ThirdPersonViewFollower.java">ThirdPersonViewFollower.java</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>, and <a href="https://www.web3d.org/x3d/content/X3dTooltips.html" target="_blank">X3D Tooltips</a>. </p>
	<table style="color:black; border:0px solid; border-spacing:10px 0px;">
        <caption>Scene Meta Information</caption>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center; padding:10px 0px;"><i>meta tags</i></td>
			<td style="text-align:left;   padding:10px 0px;">&nbsp; Document Metadata </td>
		</tr>

		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> title </i> </td>
			<td> <a href="../../../Followers/ThirdPersonViewFollower.x3d">ThirdPersonViewFollower.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> description </i> </td>
			<td> X3D Follower example </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> creator </i> </td>
			<td> Herbert Stocker </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> translator </i> </td>
			<td> Don Brutzman </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> created </i> </td>
			<td> 18 April 2006 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> translated </i> </td>
			<td> 2 December 2011 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> modified </i> </td>
			<td> 20 October 2019 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> originals/3rdPersonView-f.wrl </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="../../../Followers/Stocker_06_Followers.pdf">Stocker_06_Followers.pdf</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="http://www.hersto.com/Publications/Followers" target="_blank">http://www.hersto.com/Publications/Followers</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> requires </i> </td>
			<td> X3D version 3.2 or greater </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> subject </i> </td>
			<td> X3D Follower Chaser Damper </td>
		</tr>
		<tr style="color:burntorange">
			<td style="text-align:right; vertical-align: text-top;"> <i> warning </i> </td>
			<td> under development </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="https://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/components/followers.html" target="_blank">https://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/components/followers.html</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> identifier </i> </td>
			<td> <a href="https://www.web3d.org/x3d/content/examples/Basic/Followers/ThirdPersonViewFollower.x3d" target="_blank">https://www.web3d.org/x3d/content/examples/Basic/Followers/ThirdPersonViewFollower.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> generator </i> </td>
			<td> Vrml97ToX3dNist, <a href="http://ovrt.nist.gov/v2_x3d.html" target="_blank">http://ovrt.nist.gov/v2_x3d.html</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> generator </i> </td>
			<td> X3D-Edit 3.3, <a href="https://savage.nps.edu/X3D-Edit" target="_blank">https://savage.nps.edu/X3D-Edit</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> license </i> </td>
			<td> <a href="../../../Followers/../license.html">../license.html</a> </td>
		</tr>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center;" colspan="2">  &nbsp; </td>
		</tr>
	</table>

	<p>
		This program uses the
		<a href="https://www.web3d.org/specifications/java/X3DJSAIL.html" target="_blank">X3D Java Scene Access Interface Library (X3DJSAIL)</a>.
		It has been produced using the 
		<a href="https://www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">X3dToJava.xslt</a>
		stylesheet
	       (<a href="https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">version control</a>)
                which is used to create Java source code from an original <code>.x3d</code> model.
	</p>

	* @author Herbert Stocker
 */

public class ThirdPersonViewFollower
{
	/** Default constructor to create this object. */
	public ThirdPersonViewFollower ()
	{
	  initialize();
	}

	/** Create and initialize the X3D model for this object. */
	public final void initialize()
	{
            try { // catch-all
  x3dModel = new X3D().setProfile(X3D.PROFILE_IMMERSIVE).setVersion(X3D.VERSION_3_3)
  .setHead(new head()
    .addMeta(new meta().setName(meta.NAME_TITLE      ).setContent("ThirdPersonViewFollower.x3d"))
    .addMeta(new meta().setName(meta.NAME_DESCRIPTION).setContent("X3D Follower example"))
    .addMeta(new meta().setName(meta.NAME_CREATOR    ).setContent("Herbert Stocker"))
    .addMeta(new meta().setName(meta.NAME_TRANSLATOR ).setContent("Don Brutzman"))
    .addMeta(new meta().setName(meta.NAME_CREATED    ).setContent("18 April 2006"))
    .addMeta(new meta().setName(meta.NAME_TRANSLATED ).setContent("2 December 2011"))
    .addMeta(new meta().setName(meta.NAME_MODIFIED   ).setContent("20 October 2019"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("originals/3rdPersonView-f.wrl"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("Stocker_06_Followers.pdf"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("http://www.hersto.com/Publications/Followers"))
    .addMeta(new meta().setName(meta.NAME_REQUIRES   ).setContent("X3D version 3.2 or greater"))
    .addMeta(new meta().setName(meta.NAME_SUBJECT    ).setContent("X3D Follower Chaser Damper"))
    .addMeta(new meta().setName(meta.NAME_WARNING    ).setContent("under development"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("https://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/components/followers.html"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html"))
    .addMeta(new meta().setName(meta.NAME_IDENTIFIER ).setContent("https://www.web3d.org/x3d/content/examples/Basic/Followers/ThirdPersonViewFollower.x3d"))
    .addMeta(new meta().setName(meta.NAME_GENERATOR  ).setContent("Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html"))
    .addMeta(new meta().setName(meta.NAME_GENERATOR  ).setContent("X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"))
    .addMeta(new meta().setName(meta.NAME_LICENSE    ).setContent("../license.html")))
  .setScene(new Scene()
    .addChild(new WorldInfo().setTitle("ThirdPersonViewFollower.x3d"))
    .addChild(new NavigationInfo("ForceViewpointAnimation").setHeadlight(false).setType("\"NONE\""))
    .addChild(new Background().setSkyColor(new MFColor(new double[] {0.6,0.7,1.0})))
    .addChild(new DirectionalLight().setDirection(1.0,-1.0,1.0))
    .addChild(new ProximitySensor("Proxi").setSize(1.0E30,1.0E30,1.0E30))
    .addChild(new Viewpoint("VP").setDescription("3rd Person View Follower").setFieldOfView(1.0))
    .addChild(new PositionDamper("PositionDamperNode").setOrder(1).setTau(0.1))
    .addChild(new OrientationDamper("OrientationDamperNode").setOrder(1).setTau(0.1))
    .addChild(new PositionChaser("PositionChaserNode").setDuration(0.3))
    .addChild(new OrientationChaser("OrientationChaserNode").setDuration(0.3))
    .addChild(new ProtoDeclare("Tree").setName("Tree")
      .setProtoInterface(new ProtoInterface()
        .addField(new field().setName("position").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue(new SFVec3f(0.0,0.0,0.0)))
        .addField(new field().setName("set_Color").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_Size").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY)))
      .setProtoBody(new ProtoBody()
        .addChild(new Transform()
          .setIS(new IS()
            .addConnect(new connect().setNodeField("translation").setProtoField("position")))
          .addChild(new Transform("TrTrunc").setTranslation(0.0,1.0,0.0)
            .addChild(new Shape()
              .setAppearance(new Appearance()
                .setMaterial(new Material().setAmbientIntensity(0.06).setDiffuseColor(0.376,0.161,0.0196).setEmissiveColor(0.318,0.208,0.0667).setShininess(0.93)))
              .setGeometry(new Cylinder().setRadius(0.2))))
          .addChild(new Transform("TrCrown").setTranslation(0.0,3.5,0.0)
            .addChild(new Shape()
              .setAppearance(new Appearance()
                .setMaterial(new Material("MatCrown").setAmbientIntensity(0.0633).setDiffuseColor(0.11,0.369,0.0902).setEmissiveColor(0.051,0.176,0.0275).setShininess(0.09).setSpecularColor(0.09,0.09,0.09)))
              .setGeometry(new Sphere().setRadius(1.5)))))
        .addChild(new Script("ScrTree").setSourceCode("""
ecmascript:

function set_Color(Col)
{
    croneDiffuseColor= new  SFColor( Col.r * .7
                                   , Col.g * .7
                                   , Col.b * .7
                                   );
    croneEmissiveColor= new SFColor( Col.r * .3
                                   , Col.g * .3
                                   , Col.b * .3
                                   );
}
""")
          .addField(new field().setName("croneEmissiveColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
          .addField(new field().setName("set_Color").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INPUTONLY))
          .addField(new field().setName("croneDiffuseColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
          .setIS(new IS()
            .addConnect(new connect().setNodeField("set_Color").setProtoField("set_Color"))))
        .addChild(new ROUTE().setFromNode("ScrTree").setFromField("croneDiffuseColor").setToNode("MatCrown").setToField("diffuseColor"))
        .addChild(new ROUTE().setFromNode("ScrTree").setFromField("croneEmissiveColor").setToNode("MatCrown").setToField("emissiveColor"))))
    .addChild(new Transform("TrGround").setTranslation(-120.0,0.0,-120.0)
      .addChild(new Shape("ShGround")
        .setAppearance(new Appearance()
          .setMaterial(new Material().setAmbientIntensity(0.0).setDiffuseColor(0.2,0.41,0.0).setEmissiveColor(0.15,0.21,0.0).setShininess(0.0)))
        .setGeometry(new ElevationGrid("EvGridGround").setCreaseAngle(4.0).setXDimension(40).setXSpacing(6.0).setZDimension(40).setZSpacing(6.0))))
    .addChild(new Script("ScrEvGridIniter").setDirectOutput(true).setSourceCode("""
ecmascript:

function sin0(x)
{
    return Math.sin(x * 6.28318530717959); // We don't use 2*Math.PI in the hope it will increase performance.
}

function cos0(x)
{
    return Math.cos(x * 6.28318530717959); // We don't use 2*Math.PI in the hope it will increase performance.
}

function initialize()
{
    var Heights= new MFFloat;
    Heights.length= Grid.xDimension * Grid.zDimension;

    var ZFrom= -Grid.zDimension*Grid.zSpacing/2;
    var ZTo=    Grid.zDimension*Grid.zSpacing/2 - Grid.zSpacing * .1;
    var ZStep=  Grid.zSpacing;
    var XFrom= -Grid.xDimension*Grid.xSpacing/2;
    var XTo=    Grid.xDimension*Grid.xSpacing/2 - Grid.xSpacing * .1;
    var XStep=  Grid.xSpacing;

//        ZFrom+= Grid.zSpacing;
//        ZTo-=   Grid.zSpacing;
//        XFrom+= Grid.xSpacing;
//        XTo-=   Grid.xSpacing;

    var Idx= 0;

//        Idx+= 1 + Grid.xDimension * 1;

    for(var Z= ZFrom; Z<=ZTo; Z+= ZStep)
    {
        for(var X= XFrom; X<=XTo; X+= XStep)
        {
            var s= 9;

            var H= .7*( cos0(Z*s / 30) + cos0(X*s / 35 + X*X*s*s / 34) + sin0(X*Z*s / 40));
            H+= cos0(Math.sqrt(X*X + Z*Z) / 300) * 15;
            Heights[Idx++]= H;
        }
//            Idx+= 2;
    }
    Grid.height= Heights;
}
""")
      .addField(new field().setName("Grid").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ElevationGrid().setUSE("EvGridGround"))))
    .addChild(new Group("GrTrees")
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(2.0,0.0,-50.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(80.0,0.0,56.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-98.0,0.0,6.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(62.0,0.0,56.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-82.0,0.0,2.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(16.0,0.0,14.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(54.0,0.0,-62.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(0.0,0.0,58.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(78.0,0.0,0.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(88.0,0.0,-18.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(76.0,0.0,6.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(94.0,0.0,24.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(46.0,0.0,-52.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-82.0,0.0,96.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(70.0,0.0,-14.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-46.0,0.0,-98.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(6.0,0.0,-2.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-78.0,0.0,-18.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(70.0,0.0,34.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(6.0,0.0,2.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(22.0,0.0,48.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-82.0,0.0,-40.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-44.0,0.0,-80.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-44.0,0.0,66.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-34.0,0.0,-76.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-96.0,0.0,42.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-74.0,0.0,56.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-24.0,0.0,2.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-60.0,0.0,62.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(68.0,0.0,32.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-38.0,0.0,44.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-100.0,0.0,28.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(86.0,0.0,-70.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(68.0,0.0,36.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(4.0,0.0,52.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-76.0,0.0,16.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-100.0,0.0,86.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-36.0,0.0,-86.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(96.0,0.0,12.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(78.0,0.0,-78.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-36.0,0.0,-4.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(88.0,0.0,92.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-92.0,0.0,-66.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-68.0,0.0,-22.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-46.0,0.0,64.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-68.0,0.0,70.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-100.0,0.0,26.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-58.0,0.0,-82.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-48.0,0.0,64.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(78.0,0.0,-30.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-86.0,0.0,-46.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(56.0,0.0,24.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-68.0,0.0,76.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-30.0,0.0,-34.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-58.0,0.0,32.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-98.0,0.0,-28.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-4.0,0.0,-64.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-48.0,0.0,-86.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(50.0,0.0,-30.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(56.0,0.0,-96.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(10.0,0.0,34.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-42.0,0.0,-84.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(28.0,0.0,32.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(8.0,0.0,18.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(32.0,0.0,-32.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(60.0,0.0,86.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(38.0,0.0,76.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(10.0,0.0,-74.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-24.0,0.0,-14.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(96.0,0.0,48.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(30.0,0.0,30.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-70.0,0.0,-16.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-52.0,0.0,8.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-54.0,0.0,-84.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-70.0,0.0,-74.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(28.0,0.0,12.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-8.0,0.0,-94.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-96.0,0.0,8.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-32.0,0.0,-26.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-44.0,0.0,12.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(56.0,0.0,-50.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-2.0,0.0,78.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(52.0,0.0,-16.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(56.0,0.0,-46.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-10.0,0.0,-76.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-72.0,0.0,34.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(52.0,0.0,-44.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-18.0,0.0,6.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(0.0,0.0,-94.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(32.0,0.0,-66.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(4.0,0.0,72.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(98.0,0.0,22.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-38.0,0.0,-88.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-90.0,0.0,96.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(34.0,0.0,-70.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-12.0,0.0,-98.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-28.0,0.0,-58.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-30.0,0.0,54.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(54.0,0.0,16.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-36.0,0.0,66.0))))
      .addChild(new ProtoInstance("Tree").setContainerField("children")
        .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(-78.0,0.0,86.0)))))
    .addChild(new Script("ScrTreeHightIniter").setDirectOutput(true).setSourceCode("""
ecmascript:

function initialize()
{
    Trees= TreeGroup.children;

    for(var C= 0; C<Trees.length; C++ )
        Trees[C].position= AddGroundHeight(Trees[C].position);
}

// receives an SFVec3f of a position over ground, evaluates the ground height at that 
// position and adds it to the y value of the vector.

function AddGroundHeight(Vec)
{
    var PosOnGrid= Vec.subtract(GroundTrans.translation);

    var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing;
    var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing;

    var FracX= FloatIdxX - Math.floor(FloatIdxX);
    var FracZ= FloatIdxZ - Math.floor(FloatIdxZ);

    // We do linear interpolation in the square we have.

    var IdxLowerX= Math.floor(FloatIdxX);
    var IdxLowerZ= Math.floor(FloatIdxZ);
    var IdxHigherX= IdxLowerX + 1;
    var IdxHigherZ= IdxLowerZ + 1;

    if(IdxLowerX  < 0) IdxLowerX= 0;
    if(IdxLowerZ  < 0) IdxLowerZ= 0;
    if(IdxHigherX < 0) IdxHigherX= 0;
    if(IdxHigherZ < 0) IdxHigherZ= 0;
    if(IdxLowerX  >= GroundGrid.xDimension) IdxLowerX=  GroundGrid.xDimension - 1;
    if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1;
    if(IdxLowerZ  >= GroundGrid.zDimension) IdxLowerZ=  GroundGrid.zDimension - 1;
    if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1;

    var LowerXHeight=  GetGroundGridHeightAt(IdxLowerX,  IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX,  IdxHigherZ) * FracZ;
    var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ;

    var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX;

    return new SFVec3f(Vec.x, Vec.y + Height, Vec.z);
}

function GetGroundGridHeightAt(IdxX, IdxZ)
{
    return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension];
}
""")
      .addField(new field().setName("TreeGroup").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new Group().setUSE("GrTrees")))
      .addField(new field().setName("GroundTrans").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new Transform().setUSE("TrGround")))
      .addField(new field().setName("GroundGrid").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ElevationGrid().setUSE("EvGridGround")))
      .addField(new field().setName("Trees").setType(field.TYPE_MFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addComments(" no initialization nodes since this is a local field to hold content ")))
    .addChild(new Transform("TransObject")
      .addChild(new Transform().setRotation(0.0,1.0,0.0,3.1415927).setTranslation(0.0,0.3,0.5)
        .addChild(new Transform().setRotation(-0.074,0.991,0.113,-1.177).setTranslation(-0.0,1.386,0.5)
          .addChild(new Shape()
            .setAppearance(new Appearance()
              .setMaterial(new Material("Mat").setAmbientIntensity(0.04).setDiffuseColor(0.44,0.27,0.17).setEmissiveColor(0.21,0.13,0.08).setShininess(0.19).setSpecularColor(0.29,0.31,0.05)))
            .setGeometry(new IndexedFaceSet().setCreaseAngle(4.0).setCoordIndex(getIndexedFaceSet_7_279_coordIndex())
              .setCoord(new Coordinate("coord_Suzanne").setPoint(getcoord_Suzanne_8_279_point())))))))
    .addChild(new Transform("TrHud")
      .addChild(new Collision().setEnabled(false)
        .addChild(new Transform().setScale(0.5,0.5,0.5).setTranslation(0.0,0.0,-0.2)
          .addChild(new TouchSensor("TchNavi").setDescription("touch to activate"))
          .addChild(new Shape()
            .setAppearance(new Appearance()
              .setMaterial(new Material().setDiffuseColor(0.0,0.0,0.0).setEmissiveColor(0.3,0.3,0.3).setTransparency(1.0)))
            .setGeometry(new IndexedFaceSet().setCoordIndex(new int[] {0,1,2,3,-1})
              .setCoord(new Coordinate().setPoint(new MFVec3f(new double[] {-1.0,-1.0,0.0,1.0,-1.0,0.0,1.0,1.0,0.0,-1.0,1.0,0.0}))))))))
    .addChild(new ROUTE().setFromNode("Proxi").setFromField("position_changed").setToNode("TrHud").setToField("translation"))
    .addChild(new ROUTE().setFromNode("Proxi").setFromField("orientation_changed").setToNode("TrHud").setToField("rotation"))
    .addChild(new Script("ScrNaviSens").setSourceCode("""
ecmascript:

function set_hitCoord(C)
{
    hitCoord= C;

    if(SensIsActive)
    {
        userInput= C.subtract(ActivationCoords).multiply(cScale);
    }
}

function set_activated(a)
{
    SensIsActive= a;
    if(a)
        ActivationCoords= hitCoord;
    else
        userInput= new SFVec2f(0, 0);
}
""")
      .addField(new field().setName("hitCoord").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec2f(0.0,0.0)))
      .addField(new field().setName("userInput").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("set_hitCoord").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("set_activated").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("cScale").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(15.0))
      .addField(new field().setName("ActivationCoords").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec2f(0.0,0.0)))
      .addField(new field().setName("SensIsActive").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(false)))
    .addChild(new ROUTE().setFromNode("TchNavi").setFromField("hitTexCoord_changed").setToNode("ScrNaviSens").setToField("set_hitCoord"))
    .addChild(new ROUTE().setFromNode("TchNavi").setFromField("isActive").setToNode("ScrNaviSens").setToField("set_activated"))
    .addChild(new ScalarDamper("DieAwayMoveDamper").setOrder(4).setTau(0.2))
    .addChild(new ScalarDamper("DieAwayRotateDamper").setTau(0.1))
    .addChild(new Script("ScrNavi").setDirectOutput(true).setSourceCode("""
ecmascript:

function NonLin(x)
{
    var cAmount= .3;
    var cBmount= 1 - cAmount;
    return (x * x * (x>0? 1:-1)) * cAmount + (x) * cBmount; // TBD: Some exponential function would be better.
}

function userInput(inp)
{
    lastUserInput= inp;

    if(sensorIsActive)
    {
        ProcessMoveInput(inp.y);
        ProcessRotateInput(inp.x);
    }
}

function damperedMoveInput(inp)
{
    if(!sensorIsActive)
        ProcessMoveInput(inp);
}

function damperedRotateInput(inp)
{
    if(!sensorIsActive)
        ProcessRotateInput(inp);
}

function ProcessMoveInput(inp)
{
    MoveSpeed= NonLin(inp / cInputNominalX) * cNominalMoveSpeed;
}

function ProcessRotateInput(inp)
{
    OriSpeed=  NonLin(inp / cInputNominalY) * cNominalOriSpeed;
}

function set_sensorIsActive(a)
{
    sensorIsActive= a;

    if(!a)
    {
        DieAwayMoveDamper.set_value= lastUserInput.y;
        DieAwayMoveDamper.set_destination= 0;

        DieAwayRotateDamper.set_value= lastUserInput.x;
        DieAwayRotateDamper.set_destination= 0;

        // They now creates a transition from lastUserInput.y to 0.
    }
}

function Tick(Now)
{
    if(!lastTick)
    {
        lastTick= Now;
        return;
    }

    var DeltaT= Now - lastTick;
    lastTick= Now;

    if(OriSpeed || MoveSpeed)
    {
        ObjectOri= ObjectOri.multiply(new SFRotation(0, 1, 0, -OriSpeed * DeltaT));
        ObjectPos= ObjectPos.add(ObjectOri.multVec(new SFVec3f(0, 0, -MoveSpeed * DeltaT)));

        objectPos_changed= AddGroundHeight(ObjectPos);
        objectOri_changed=                 ObjectOri;
    }
}

// receives an SFVec3f of a position over ground, evaluates the ground height at that 
// position and adds it to the y value of the vector.

function AddGroundHeight(Vec)
{
    var PosOnGrid= Vec.subtract(GroundTrans.translation);

    var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing;
    var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing;

    var FracX= FloatIdxX - Math.floor(FloatIdxX);
    var FracZ= FloatIdxZ - Math.floor(FloatIdxZ);

    // We do linear interpolation in the square we have.

    var IdxLowerX= Math.floor(FloatIdxX);
    var IdxLowerZ= Math.floor(FloatIdxZ);
    var IdxHigherX= IdxLowerX + 1;
    var IdxHigherZ= IdxLowerZ + 1;

    if(IdxLowerX  < 0) IdxLowerX= 0;
    if(IdxLowerZ  < 0) IdxLowerZ= 0;
    if(IdxHigherX < 0) IdxHigherX= 0;
    if(IdxHigherZ < 0) IdxHigherZ= 0;
    if(IdxLowerX  >= GroundGrid.xDimension) IdxLowerX=  GroundGrid.xDimension - 1;
    if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1;
    if(IdxLowerZ  >= GroundGrid.zDimension) IdxLowerZ=  GroundGrid.zDimension - 1;
    if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1;

    var LowerXHeight=  GetGroundGridHeightAt(IdxLowerX,  IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX,  IdxHigherZ) * FracZ;
    var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ;

    var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX;

    return new SFVec3f(Vec.x, Vec.y + Height, Vec.z);
}

function GetGroundGridHeightAt(IdxX, IdxZ)
{
    return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension];
}
""")
      .addField(new field().setName("Tick").setType(field.TYPE_SFTIME).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("GroundTrans").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new Transform().setUSE("TrGround")))
      .addField(new field().setName("cInputNominalY").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(1.0))
      .addField(new field().setName("cNominalMoveSpeed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(10.0))
      .addField(new field().setName("cInputNominalX").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(1.0))
      .addField(new field().setName("ObjectOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.0,0.0,1.0,0.0)))
      .addField(new field().setName("objectOri_changed").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("cNominalOriSpeed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(1.0))
      .addField(new field().setName("DieAwayMoveDamper").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ScalarDamper().setUSE("DieAwayMoveDamper")))
      .addField(new field().setName("damperedMoveInput").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("MoveSpeed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(0.0))
      .addField(new field().setName("set_sensorIsActive").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("damperedRotateInput").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("ObjectPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,0.0,0.0)))
      .addField(new field().setName("lastTick").setType(field.TYPE_SFTIME).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(0.0))
      .addField(new field().setName("userInput").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("sensorIsActive").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(false))
      .addField(new field().setName("initial_objectOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.02,-0.999,0.027,2.08)))
      .addField(new field().setName("GroundGrid").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ElevationGrid().setUSE("EvGridGround")))
      .addField(new field().setName("objectPos_changed").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("lastUserInput").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec2f(0.0,0.0)))
      .addField(new field().setName("DieAwayRotateDamper").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ScalarDamper().setUSE("DieAwayRotateDamper")))
      .addField(new field().setName("initial_objectPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(-37.577,1.65,-83.856)))
      .addField(new field().setName("OriSpeed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(0.0)))
    .addChild(new ROUTE().setFromNode("ScrNaviSens").setFromField("userInput").setToNode("ScrNavi").setToField("userInput"))
    .addChild(new ROUTE().setFromNode("TchNavi").setFromField("isActive").setToNode("ScrNavi").setToField("set_sensorIsActive"))
    .addChild(new ROUTE().setFromNode("DieAwayMoveDamper").setFromField("value_changed").setToNode("ScrNavi").setToField("damperedMoveInput"))
    .addChild(new ROUTE().setFromNode("DieAwayRotateDamper").setFromField("value_changed").setToNode("ScrNavi").setToField("damperedRotateInput"))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectPos_changed").setToNode("TransObject").setToField("translation"))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectOri_changed").setToNode("TransObject").setToField("rotation"))
    .addChild(new TimeSensor("Timer").setLoop(true))
    .addChild(new ROUTE().setFromNode("Timer").setFromField("time").setToNode("ScrNavi").setToField("Tick"))
    .addChild(new Script("ScriptThirdPersonView").setSourceCode("""
ecmascript:

function set_avatarPos(Pos)
{
    avatarPos= Pos;
    Update();
}

function set_avatarOri(Ori)
{
    avatarOri= Ori;
    Update();
}

function Update()
{
    var viewPos= avatarPos.add(avatarOri.multVec(cCameraOffsetPos));
    var viewOri= cCameraOffsetOri.multiply(avatarOri);

    if( viewPos_changed != viewPos)
        viewPos_changed=   viewPos;

    if( viewOri_changed != viewOri)
        viewOri_changed=   viewOri;
}
""")
      .addField(new field().setName("avatarPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,0.0,0.0)))
      .addField(new field().setName("cCameraOffsetPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,4.0,5.0)))
      .addField(new field().setName("set_avatarPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("avatarOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.0,0.0,1.0,0.0)))
      .addField(new field().setName("cCameraOffsetOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(1.0,0.0,0.0,-0.2)))
      .addField(new field().setName("viewPos_changed").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("set_avatarOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("viewOri_changed").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY)))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectPos_changed").setToNode("ScriptThirdPersonView").setToField("set_avatarPos"))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectOri_changed").setToNode("ScriptThirdPersonView").setToField("set_avatarOri"))
    .addChild(new ROUTE().setFromNode("ScriptThirdPersonView").setFromField("viewPos_changed").setToNode("PositionDamperNode").setToField("set_destination"))
    .addChild(new ROUTE().setFromNode("ScriptThirdPersonView").setFromField("viewOri_changed").setToNode("OrientationDamperNode").setToField("set_destination"))
    .addChild(new Script("ScrCombiner").setSourceCode("""
ecmascript:

function set_DampPos(Pos)
{
    DampPos= Pos;
    UpdatePos();
}

function set_ChsPos(Pos)
{
    ChsPos= Pos;
    UpdatePos();
}

function set_DampOri(Ori)
{
    DampOri= Ori;
    UpdateOri();
}

function set_ChsOri(Ori)
{
    ChsOri= Ori;
    UpdateOri();
}

function UpdatePos()
{
    Pos_changed= DampPos.multiply(1 - cAlpha).add(ChsPos.multiply(cAlpha));
}

function UpdateOri()
{
    Ori_changed= DampOri.slerp(ChsOri, cAlpha);
}
""")
      .addField(new field().setName("ChsPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,0.0,0.0)))
      .addField(new field().setName("set_DampPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("ChsOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.0,0.0,1.0,0.0)))
      .addField(new field().setName("set_DampOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("cAlpha").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(0.5))
      .addField(new field().setName("DampPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,0.0,0.0)))
      .addField(new field().setName("Pos_changed").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("set_ChsPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("DampOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.0,0.0,1.0,0.0)))
      .addField(new field().setName("Ori_changed").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("set_ChsOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTONLY)))
    .addChild(new ROUTE().setFromNode("PositionDamperNode").setFromField("value_changed").setToNode("ScrCombiner").setToField("set_DampPos"))
    .addChild(new ROUTE().setFromNode("OrientationDamperNode").setFromField("value_changed").setToNode("ScrCombiner").setToField("set_DampOri"))
    .addChild(new ROUTE().setFromNode("PositionChaserNode").setFromField("value_changed").setToNode("ScrCombiner").setToField("set_ChsPos"))
    .addChild(new ROUTE().setFromNode("OrientationChaserNode").setFromField("value_changed").setToNode("ScrCombiner").setToField("set_ChsOri"))
    .addChild(new ROUTE().setFromNode("ScrCombiner").setFromField("Pos_changed").setToNode("VP").setToField("position"))
    .addChild(new ROUTE().setFromNode("ScrCombiner").setFromField("Ori_changed").setToNode("VP").setToField("orientation"))
    .addChild(new Transform("TrShadow").setScale(1.75,1.0,1.2)
      .addChild(new Shape()
        .setAppearance(new Appearance()
          .setMaterial(new Material().setDiffuseColor(0.0,0.0,0.0).setEmissiveColor(1.0,1.0,1.0).setTransparency(0.9))
          .setTexture(new ImageTexture().setUrl(new String[] {"MonkeyShadow.png","https://www.web3d.org/x3d/content/examples/Basic/Followers/MonkeyShadow.png"})))
        .setGeometry(new IndexedFaceSet().setSolid(false).setCoordIndex(new int[] {0,1,2,3,-1})
          .setTexCoord(new TextureCoordinate().setPoint(new MFVec2f(new double[] {1.0,1.0,0.0,1.0,0.0,0.0,1.0,0.0})))
          .setCoord(new Coordinate().setPoint(new MFVec3f(new double[] {-1.0,0.0,-1.0,1.0,0.0,-1.0,1.0,0.0,1.0,-1.0,0.0,1.0}))))))
    .addChild(new Script("ScrShadowMgr").setSourceCode("""
ecmascript:

function set_MonkeyPos(Pos)
{
    MonkeyPos= Pos;
    Update();
}

function set_MonkeyOri(Ori)
{
    MonkeyOri= Ori;
    Update();
}

function Update()
{
    ShadowPos_changed= AddGroundHeight(new SFVec3f(MonkeyPos.x, .4, MonkeyPos.z));

    var ViewDir= MonkeyOri.multVec(new SFVec3f(0, 0, -1));
    ViewDir.y= 0; // make it horizontal.

    var HorzOri= new SFRotation(new SFVec3f(0, 0, -1), ViewDir);
    // now we have a horizontal orientation only.

    // figure out the normal vector of the ground.
    // for this, figure out three points on the ground around the monkey position.

    var cRadius= 2.3;

    var EvGridPointA= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f(  0, 0, -1  )).multiply(cRadius))));
    var EvGridPointB= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f( .866, 0, .5)).multiply(cRadius))));
    var EvGridPointC= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f(-.866, 0, .5)).multiply(cRadius))));

    var Normal= EvGridPointC.subtract(EvGridPointA).cross(EvGridPointB.subtract(EvGridPointA));

    var NormalOri= new SFRotation(new SFVec3f(0, 1, 0), Normal);

    ShadowOri_changed= HorzOri.multiply(NormalOri);
}

// receives an SFVec3f of a position over ground, evaluates the ground height at that 
// position and adds it to the y value of the vector.

function AddGroundHeight(Vec)
{
    var PosOnGrid= Vec.subtract(GroundTrans.translation);

    var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing;
    var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing;

    var FracX= FloatIdxX - Math.floor(FloatIdxX);
    var FracZ= FloatIdxZ - Math.floor(FloatIdxZ);

    // We do linear interpolation in the square we have.

    var IdxLowerX= Math.floor(FloatIdxX);
    var IdxLowerZ= Math.floor(FloatIdxZ);
    var IdxHigherX= IdxLowerX + 1;
    var IdxHigherZ= IdxLowerZ + 1;

    if(IdxLowerX  < 0) IdxLowerX= 0;
    if(IdxLowerZ  < 0) IdxLowerZ= 0;
    if(IdxHigherX < 0) IdxHigherX= 0;
    if(IdxHigherZ < 0) IdxHigherZ= 0;
    if(IdxLowerX  >= GroundGrid.xDimension) IdxLowerX=  GroundGrid.xDimension - 1;
    if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1;
    if(IdxLowerZ  >= GroundGrid.zDimension) IdxLowerZ=  GroundGrid.zDimension - 1;
    if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1;

    var LowerXHeight=  GetGroundGridHeightAt(IdxLowerX,  IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX,  IdxHigherZ) * FracZ;
    var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ;

    var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX;

    return new SFVec3f(Vec.x, Vec.y + Height, Vec.z);
}

function GetGroundGridHeightAt(IdxX, IdxZ)
{
    return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension];
}
""")
      .addField(new field().setName("ShadowPos_changed").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("set_MonkeyPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("ShadowOri_changed").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("MonkeyPos").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFVec3f(0.0,0.0,0.0)))
      .addField(new field().setName("GroundTrans").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new Transform().setUSE("TrGround")))
      .addField(new field().setName("set_MonkeyOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("GroundGrid").setType(field.TYPE_SFNODE).setAccessType(field.ACCESSTYPE_INITIALIZEONLY)
        .addChild(new ElevationGrid().setUSE("EvGridGround")))
      .addField(new field().setName("MonkeyOri").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(new SFRotation(0.0,0.0,1.0,0.0))))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectPos_changed").setToNode("ScrShadowMgr").setToField("set_MonkeyPos"))
    .addChild(new ROUTE().setFromNode("ScrNavi").setFromField("objectOri_changed").setToNode("ScrShadowMgr").setToField("set_MonkeyOri"))
    .addChild(new ROUTE().setFromNode("ScrShadowMgr").setFromField("ShadowPos_changed").setToNode("TrShadow").setToField("translation"))
    .addChild(new ROUTE().setFromNode("ScrShadowMgr").setFromField("ShadowOri_changed").setToNode("TrShadow").setToField("rotation")));
            }
            catch (Exception ex)
            {       
                System.err.println ("*** Further hints on X3DJSAIL errors and exceptions at");
                System.err.println ("*** https://www.web3d.org/specifications/java/X3DJSAIL.html");
                throw (ex);
            }
	}
	// end of initialize() method

		/** Define subarrays using type int[] */
		private int[] getIndexedFaceSet_7_279_coordIndex_1()
		{
			int[] value = {46,0,2,44,-1,3,1,47,45,-1,44,2,4,42,-1,5,3,45,43,-1,2,8,6,4,-1,7,9,3,5,-1,0,10,8,2,-1,9,11,1,3,-1,10,12,14,8,-1,15,13,11,9,-1,8,14,16,6,-1,17,15,9,7,-1,14,20,18,16,-1,19,21,15,17,-1,12,22,20,14,-1,21,23,13,15,-1,22,24,26,20,-1,27,25,23,21,-1,20,26,28,18,-1,29,27,21,19,-1,26,32,30,28,-1,31,33,27,29,-1,24,34,32,26,-1,33,35,25,27,-1,34,36,38,32,-1,39,37,35,33,-1,32,38,40,30,-1,41,39,33,31,-1,38,44,42,40,-1,43,45,39,41,-1,36,46,44,38,-1,45,47,37,39,-1,46,36,50,48,-1,51,37,47,49,-1,36,34,52,50,-1,53,35,37,51,-1,34,24,54,52,-1,55,25,35,53,-1,24,22,56,54,-1,57,23,25,55,-1,22,12,58,56,-1,59,13,23,57,-1,12,10,62,58,-1,63,11,13,59,-1,10,0,64,62,-1,65,1,11,63,-1,0,46,48,64,-1,49,47,1,65,-1,60,64,48,-1,49,65,61,-1,62,64,60,-1,61,65,63,-1,60,58,62,-1,63,59,61,-1,60,56,58,-1,59,57,61,-1,60,54,56,-1,57,55,61,-1,60,52,54,-1,55,53,61,-1,60,50,52,-1,53,51,61,-1,60,48,50,-1,51,49,61,-1,88,173,175,90,-1,175,174,89,90,-1,86,171,173,88,-1,174,172,87,89,-1,84,169,171,86,-1,172,170,85,87,-1,82,167,169,84,-1,170,168,83,85,-1,80,165,167,82,-1,168,166,81,83,-1,78,91,145,163,-1,146,92,79,164,-1,91,93,147,145,-1,148,94,92,146,-1,93,95,149,147,-1,150,96,94,148,-1,95,97,151,149,-1,152,98,96,150,-1,97,99,153,151,-1,154,100,98,152,-1,99,101,155,153,-1,156,102,100,154,-1,101,103,157,155,-1,158,104,102,156,-1,103,105,159,157,-1,160,106,104,158,-1,105,107,161,159,-1,162,108,106,160,-1,107,66,67,161,-1,67,66,108,162,-1,109,127,159,161,-1,160,128,110,162,-1,127,178,157,159,-1,158,179,128,160,-1,125,155,157,178,-1,158,156,126,179,-1,123,153,155,125,-1,156,154,124,126,-1,121,151,153,123,-1,154,152,122,124,-1,119,149,151,121,-1,152,150,120,122,-1,117,147,149,119,-1,150,148,118,120,-1,115,145,147,117,-1,148,146,116,118,-1,113,163,145,115,-1,146,164,114,116,-1,113,180,176,163,-1,176,181,114,164,-1,109,161,67,111,-1,67,162,110,112,-1,111,67,177,182,-1,177,67,112,183,-1,176,180,182,177,-1,183,181,176,177,-1,134,136,175,173,-1,175,136,135,174,-1,132,134,173,171,-1,174,135,133,172,-1,130,132,171,169,-1,172,133,131,170,-1,165,186,184,167,-1,185,187,166,168,-1,130,169,167,184,-1,168,170,131,185,-1,143,189,188,186,-1,188,189,144,187,-1,184,186,188,68,-1,188,187,185,68,-1,129,130,184,68,-1,185,131,129,68,-1,141,192,190,143,-1,191,193,142,144,-1,139,194,192,141,-1,193,195,140,142,-1,138,196,194,139,-1,195,197,138,140,-1,137,70,196,138,-1,197,70,137,138,-1,189,143,190,69,-1,191,144,189,69,-1,69,190,205,207,-1,206,191,69,207,-1,70,198,199,196,-1,200,198,70,197,-1,196,199,201,194,-1,202,200,197,195,-1,194,201,203,192,-1,204,202,195,193,-1,192,203,205,190,-1,206,204,193,191,-1,198,203,201,199,-1,202,204,198,200,-1,198,207,205,203,-1,206,207,198,204,-1,138,139,163,176,-1,164,140,138,176,-1,139,141,210,163,-1,211,142,140,164,-1,141,143,212,210,-1,213,144,142,211,-1,143,186,165,212,-1,166,187,144,213,-1,80,208,212,165,-1,213,209,81,166,-1,208,214,210,212,-1,211,215,209,213,-1,78,163,210,214,-1,211,164,79,215,-1,130,129,71,221,-1,71,129,131,222,-1,132,130,221,219,-1,222,131,133,220,-1,134,132,219,217,-1,220,133,135,218,-1,136,134,217,216,-1,218,135,136,216,-1,216,217,228,230,-1,229,218,216,230,-1,217,219,226,228,-1,227,220,218,229,-1,219,221,224,226,-1,225,222,220,227,-1,221,71,223,224,-1,223,71,222,225,-1,223,230,228,224,-1,229,230,223,225,-1,224,228,226,-1,227,229,225,-1,182,180,233,231,-1,234,181,183,232,-1,111,182,231,253,-1,232,183,112,254,-1,109,111,253,255,-1,254,112,110,256,-1,180,113,251,233,-1,252,114,181,234,-1,113,115,249,251,-1,250,116,114};
			return value;
		}
		private int[] getIndexedFaceSet_7_279_coordIndex_2()
		{
			int[] value = {252,-1,115,117,247,249,-1,248,118,116,250,-1,117,119,245,247,-1,246,120,118,248,-1,119,121,243,245,-1,244,122,120,246,-1,121,123,241,243,-1,242,124,122,244,-1,123,125,239,241,-1,240,126,124,242,-1,125,178,235,239,-1,236,179,126,240,-1,178,127,237,235,-1,238,128,179,236,-1,127,109,255,237,-1,256,110,128,238,-1,237,255,257,275,-1,258,256,238,276,-1,235,237,275,277,-1,276,238,236,278,-1,239,235,277,273,-1,278,236,240,274,-1,241,239,273,271,-1,274,240,242,272,-1,243,241,271,269,-1,272,242,244,270,-1,245,243,269,267,-1,270,244,246,268,-1,247,245,267,265,-1,268,246,248,266,-1,249,247,265,263,-1,266,248,250,264,-1,251,249,263,261,-1,264,250,252,262,-1,233,251,261,279,-1,262,252,234,280,-1,255,253,259,257,-1,260,254,256,258,-1,253,231,281,259,-1,282,232,254,260,-1,231,233,279,281,-1,280,234,232,282,-1,66,107,283,72,-1,284,108,66,72,-1,107,105,285,283,-1,286,106,108,284,-1,105,103,287,285,-1,288,104,106,286,-1,103,101,289,287,-1,290,102,104,288,-1,101,99,291,289,-1,292,100,102,290,-1,99,97,293,291,-1,294,98,100,292,-1,97,95,295,293,-1,296,96,98,294,-1,95,93,297,295,-1,298,94,96,296,-1,93,91,299,297,-1,300,92,94,298,-1,307,308,327,337,-1,328,308,307,338,-1,306,307,337,335,-1,338,307,306,336,-1,305,306,335,339,-1,336,306,305,340,-1,88,90,305,339,-1,305,90,89,340,-1,86,88,339,333,-1,340,89,87,334,-1,84,86,333,329,-1,334,87,85,330,-1,82,84,329,331,-1,330,85,83,332,-1,329,335,337,331,-1,338,336,330,332,-1,329,333,339,335,-1,340,334,330,336,-1,325,331,337,327,-1,338,332,326,328,-1,80,82,331,325,-1,332,83,81,326,-1,208,341,343,214,-1,344,342,209,215,-1,80,325,341,208,-1,342,326,81,209,-1,78,214,343,345,-1,344,215,79,346,-1,78,345,299,91,-1,300,346,79,92,-1,76,323,351,303,-1,352,324,76,303,-1,303,351,349,77,-1,350,352,303,77,-1,77,349,347,304,-1,348,350,77,304,-1,304,347,327,308,-1,328,348,304,308,-1,325,327,347,341,-1,348,328,326,342,-1,295,297,317,309,-1,318,298,296,310,-1,75,315,323,76,-1,324,316,75,76,-1,301,357,355,302,-1,356,358,301,302,-1,302,355,353,74,-1,354,356,302,74,-1,74,353,315,75,-1,316,354,74,75,-1,291,293,361,363,-1,362,294,292,364,-1,363,361,367,365,-1,368,362,364,366,-1,365,367,369,371,-1,370,368,366,372,-1,371,369,375,373,-1,376,370,372,374,-1,313,377,373,375,-1,374,378,314,376,-1,315,353,373,377,-1,374,354,316,378,-1,353,355,371,373,-1,372,356,354,374,-1,355,357,365,371,-1,366,358,356,372,-1,357,359,363,365,-1,364,360,358,366,-1,289,291,363,359,-1,364,292,290,360,-1,73,359,357,301,-1,358,360,73,301,-1,283,285,287,289,-1,288,286,284,290,-1,283,289,359,73,-1,360,290,284,73,-1,72,283,73,-1,73,284,72,-1,293,295,309,361,-1,310,296,294,362,-1,309,311,367,361,-1,368,312,310,362,-1,311,381,369,367,-1,370,382,312,368,-1,313,375,369,381,-1,370,376,314,382,-1,347,349,385,383,-1,386,350,348,384,-1,317,383,385,319,-1,386,384,318,320,-1,297,299,383,317,-1,384,300,298,318,-1,299,343,341,383,-1,342,344,300,384,-1,341,347,383,-1,384,348,342,-1,299,345,343,-1,344,346,300,-1,313,321,379,377,-1,380,322,314,378,-1,315,377,379,323,-1,380,378,316,324,-1,319,385,379,321,-1,380,386,320,322,-1,349,351,379,385,-1,380,352,350,386,-1,323,379,351,-1,352,380,324,-1,399,387,413,401,-1,414,388,400,402,-1,399,401,403,397,-1,404,402,400,398,-1,397,403,405,395,-1,406,404,398,396,-1,395,405,407,393,-1,408,406,396,394,-1,393,407,409,391,-1,410,408,394,392,-1,391,409,411,389,-1,412,410,392,390,-1,409,419,417,411,-1,418,420,410,412,-1,407,421,419,409,-1,420,422,408,410,-1,405,423,421,407,-1,422,424,406,408,-1,403,425,423,405,-1,424,426,404,406,-1,401,427,425,403,-1,426,428,402,404,-1,401,413,415,427,-1,416,414,402,428,-1,317,319,443,441,-1,444,320,318,442,-1,319,389,411,443,-1,412,390,320,444,-1,309,317,441,311,-1,442,318,310,312,-1,381,429,413,387,-1,414,430,382,388,-1,411,417,439,443,-1,440};
			return value;
		}
		private int[] getIndexedFaceSet_7_279_coordIndex_3()
		{
			int[] value = {418,412,444,-1,437,445,443,439,-1,444,446,438,440,-1,433,445,437,435,-1,438,446,434,436,-1,431,447,445,433,-1,446,448,432,434,-1,429,447,431,449,-1,432,448,430,450,-1,413,429,449,415,-1,450,430,414,416,-1,311,447,429,381,-1,430,448,312,382,-1,311,441,445,447,-1,446,442,312,448,-1,441,443,445,-1,446,444,442,-1,415,449,451,475,-1,452,450,416,476,-1,449,431,461,451,-1,462,432,450,452,-1,431,433,459,461,-1,460,434,432,462,-1,433,435,457,459,-1,458,436,434,460,-1,435,437,455,457,-1,456,438,436,458,-1,437,439,453,455,-1,454,440,438,456,-1,439,417,473,453,-1,474,418,440,454,-1,427,415,475,463,-1,476,416,428,464,-1,425,427,463,465,-1,464,428,426,466,-1,423,425,465,467,-1,466,426,424,468,-1,421,423,467,469,-1,468,424,422,470,-1,419,421,469,471,-1,470,422,420,472,-1,417,419,471,473,-1,472,420,418,474,-1,457,455,479,477,-1,480,456,458,478,-1,477,479,481,483,-1,482,480,478,484,-1,483,481,487,485,-1,488,482,484,486,-1,485,487,489,491,-1,490,488,486,492,-1,463,475,485,491,-1,486,476,464,492,-1,451,483,485,475,-1,486,484,452,476,-1,451,461,477,483,-1,478,462,452,484,-1,457,477,461,459,-1,462,478,458,460,-1,453,473,479,455,-1,480,474,454,456,-1,471,481,479,473,-1,480,482,472,474,-1,469,487,481,471,-1,482,488,470,472,-1,467,489,487,469,-1,488,490,468,470,-1,465,491,489,467,-1,490,492,466,468,-1,463,491,465,-1,466,492,464,-1,391,389,503,501,-1,504,390,392,502,-1,393,391,501,499,-1,502,392,394,500,-1,395,393,499,497,-1,500,394,396,498,-1,397,395,497,495,-1,498,396,398,496,-1,399,397,495,493,-1,496,398,400,494,-1,387,399,493,505,-1,494,400,388,506,-1,493,501,503,505,-1,504,502,494,506,-1,493,495,499,501,-1,500,496,494,502,-1,495,497,499,-1,500,498,496,-1,313,381,387,505,-1,388,382,314,506,-1,313,505,503,321,-1,504,506,314,322,-1,319,321,503,389,-1,504,322,320,390,-1};
			return value;
		}


		/** Define subarrays using type double[] */
		private double[] getcoord_Suzanne_8_279_point_1()
		{
			double[] value = {0.86,0.251,-0.044,0.466,0.211,0.737,0.826,0.177,-0.135,0.376,0.131,0.757,0.754,0.131,-0.226,0.262,0.081,0.749,0.708,0.048,-0.035,0.392,0.015,0.593,0.793,0.111,0.011,0.477,0.079,0.639,0.838,0.218,0.04,0.522,0.185,0.667,0.814,0.247,0.117,0.568,0.221,0.604,0.741,0.169,0.155,0.558,0.15,0.517,0.64,0.119,0.154,0.5,0.105,0.433,0.593,0.303,0.227,0.523,0.296,0.367,0.698,0.313,0.21,0.571,0.3,0.461,0.792,0.323,0.145,0.574,0.301,0.577,0.797,0.41,0.117,0.551,0.385,0.605,0.711,0.464,0.155,0.528,0.445,0.517,0.602,0.5,0.154,0.461,0.486,0.433,0.654,0.584,-0.034,0.338,0.552,0.593,0.751,0.531,0.012,0.434,0.498,0.639,0.816,0.443,0.04,0.499,0.411,0.667,0.843,0.415,-0.044,0.45,0.374,0.737,0.796,0.473,-0.135,0.346,0.427,0.757,0.715,0.512,-0.226,0.223,0.461,0.75,0.756,0.32,-0.303,0.194,0.262,0.812,0.825,0.327,-0.198,0.319,0.275,0.806,0.859,0.33,-0.075,0.437,0.287,0.761,0.877,0.332,-0.075,0.448,0.288,0.775,0.86,0.424,-0.044,0.459,0.383,0.751,0.835,0.461,0.051,0.518,0.428,0.678,0.814,0.419,0.134,0.575,0.395,0.608,0.806,0.324,0.169,0.602,0.303,0.573,0.832,0.241,0.134,0.593,0.216,0.608,0.869,0.331,0.061,0.553,0.298,0.688,0.861,0.204,0.05,0.544,0.172,0.678,0.878,0.245,-0.044,0.477,0.204,0.751,0.616,0.493,0.336,0.693,0.423,0.371,0.72,-0.611,0.331,0.725,-0.249,0.353,0.726,-0.116,0.36,0.715,-0.706,0.324,0.493,0.458,0.272,0.449,0.618,0.258,-0.575,0.845,-0.246,-0.812,0.484,-0.384,-0.742,-0.0040,-0.374,-0.274,-0.412,-0.159,0.609,-0.127,0.073,0.427,-0.146,0.435,0.691,-0.37,-0.021,0.409,-0.399,0.536,0.734,-0.625,-0.056,0.418,-0.657,0.571,0.726,-0.822,-0.088,0.395,-0.856,0.567,0.707,-0.879,-0.057,0.412,-0.909,0.528,0.67,-0.906,0.09,0.508,-0.923,0.41,0.612,-0.928,0.26,0.682,-0.073,-0.15,0.289,-0.113,0.63,0.767,0.038,-0.321,0.198,-0.02,0.808,0.753,0.225,-0.537,0.0080,0.149,0.94,0.87,0.52,-0.498,0.097,0.441,1.035,0.826,0.57,-0.351};
			return value;
		}
		private double[] getcoord_Suzanne_8_279_point_2()
		{
			double[] value = {0.186,0.505,0.917,0.771,0.682,-0.128,0.329,0.637,0.75,0.72,0.834,0.047,0.432,0.804,0.619,0.671,0.79,0.204,0.53,0.775,0.483,0.644,0.559,0.284,0.588,0.553,0.395,0.719,0.488,0.204,0.571,0.473,0.496,0.705,0.377,0.235,0.593,0.365,0.458,0.741,0.169,0.155,0.558,0.15,0.517,0.791,0.095,-0.017,0.454,0.061,0.652,0.811,0.145,-0.135,0.369,0.099,0.743,0.838,0.273,-0.264,0.276,0.215,0.851,0.834,0.383,-0.278,0.258,0.323,0.865,0.822,0.46,-0.236,0.281,0.404,0.837,0.787,0.519,-0.058,0.401,0.479,0.709,0.738,0.545,0.12,0.513,0.522,0.566,0.728,-0.697,0.331,0.773,-0.645,0.234,0.675,-0.655,0.429,0.767,-0.763,0.216,0.662,-0.774,0.425,0.734,-0.814,0.258,0.677,-0.819,0.369,0.699,-0.825,0.31,0.685,-0.128,0.339,0.673,-0.074,0.335,0.719,-0.077,0.245,0.628,-0.086,0.426,0.745,-0.153,0.227,0.632,-0.165,0.45,0.726,-0.218,0.259,0.649,-0.226,0.412,0.78,0.031,-0.052,0.422,-0.0050,0.659,0.827,0.138,-0.268,0.272,0.081,0.833,0.84,0.289,-0.376,0.187,0.222,0.92,0.879,0.466,-0.365,0.211,0.397,0.959,0.913,0.508,-0.284,0.294,0.445,0.942,0.849,0.635,-0.029,0.456,0.595,0.751,0.818,0.726,0.1,0.537,0.697,0.657,0.785,0.699,0.205,0.603,0.68,0.567,0.751,0.507,0.291,0.66,0.498,0.473,0.787,-0.023,0.256,0.675,-0.035,0.479,0.77,-0.37,0.133,0.581,-0.39,0.509,0.793,-0.627,0.087,0.568,-0.65,0.533,0.791,-0.745,0.063,0.552,-0.769,0.536,0.759,-0.842,0.076,0.548,-0.864,0.494,0.728,-0.861,0.139,0.581,-0.876,0.432,0.663,-0.884,0.289,0.64,0.111,0.329,0.658,0.278,0.346,0.759,0.555,0.043,0.463,0.525,0.629,0.725,0.214,0.193,0.578,0.199,0.486,0.711,0.283,0.224,0.592,0.271,0.461,0.773,-0.613,0.227,0.668,-0.624,0.436,0.745,-0.373,0.269,0.675,-0.38,0.408,0.71,-0.376,0.339,0.692,-0.261,0.335,0.763,-0.198,0.269,0.679,-0.207,0.437,0.79,-0.148,0.242,0.67,-0.161,0.479,0.756,-0.058,0.256,0.657,-0.068,0.451,0.723,-0.053,0.318,0.688,-0.057,0.388,0.755,-0.129,0.374,0.757,-0.073,0.325};
			return value;
		}
		private double[] getcoord_Suzanne_8_279_point_3()
		{
			double[] value = {0.715,-0.078,0.409,0.779,-0.079,0.284,0.695,-0.088,0.451,0.807,-0.147,0.277,0.708,-0.157,0.472,0.774,-0.174,0.294,0.704,-0.181,0.433,0.743,-0.216,0.364,0.64,-0.25,0.021,0.408,-0.274,0.48,0.729,-0.17,0.175,0.581,-0.185,0.468,0.743,-0.239,0.161,0.581,-0.256,0.481,0.623,-0.189,0.042,0.412,-0.21,0.46,0.698,-0.81,0.31,0.718,-0.8,0.268,0.676,-0.804,0.352,0.755,-0.749,0.237,0.671,-0.757,0.404,0.761,-0.67,0.244,0.677,-0.678,0.411,0.661,-0.719,0.296,0.707,-0.683,0.216,0.622,-0.692,0.383,0.692,-0.747,0.205,0.608,-0.756,0.372,0.668,-0.789,0.243,0.626,-0.793,0.327,0.648,-0.799,0.285,0.749,0.295,0.2,0.594,0.279,0.507,0.755,0.233,0.183,0.586,0.216,0.517,0.781,0.51,0.043,0.478,0.479,0.643,0.767,0.501,0.106,0.521,0.476,0.594,0.836,0.485,-0.026,0.457,0.446,0.726,0.835,0.438,-0.187,0.329,0.386,0.816,0.845,0.376,-0.211,0.318,0.322,0.834,0.844,0.281,-0.208,0.324,0.228,0.823,0.842,0.187,-0.1,0.413,0.143,0.75,0.821,0.145,0.0010,0.484,0.111,0.67,0.784,0.189,0.151,0.58,0.168,0.555,0.744,0.373,0.193,0.583,0.357,0.514,0.751,0.452,0.165,0.561,0.433,0.542,0.742,0.436,0.134,0.531,0.414,0.552,0.731,0.372,0.169,0.555,0.354,0.517,0.769,0.203,0.127,0.551,0.181,0.559,0.805,0.167,-0.0060,0.468,0.133,0.663,0.82,0.2,-0.093,0.405,0.158,0.729,0.821,0.295,-0.184,0.329,0.244,0.792,0.818,0.365,-0.191,0.319,0.314,0.799,0.809,0.419,-0.166,0.331,0.37,0.782,0.813,0.474,-0.03,0.44,0.436,0.709,0.766,0.477,0.096,0.513,0.451,0.597,0.776,0.486,0.04,0.474,0.455,0.639,0.74,0.247,0.158,0.557,0.228,0.52,0.731,0.301,0.165,0.555,0.283,0.514,0.544,0.518,0.178,0.445,0.508,0.374,0.569,0.725,0.106,0.393,0.707,0.454,0.609,0.752,-0.03,0.307,0.721,0.569,0.655,0.624,-0.181,0.219,0.579,0.683,0.697,0.526,-0.383,0.086,0.463,0.829,0.727,0.482,-0.502,0.01,0.408,0.92,0.664,0.232,-0.52,-0.032,0.161,0.86,0.638,0.065,-0.349,0.097,0.0090,0.724,0.622,-0.031,-0.178};
			return value;
		}
		private double[] getcoord_Suzanne_8_279_point_4()
		{
			double[] value = {0.229,-0.072,0.602,0.167,0.92,0.132,-0.168,0.972,-0.034,-0.577,-0.254,-0.304,0.213,-0.442,0.084,0.507,-0.931,0.207,0.386,-0.77,0.155,0.341,-0.539,0.144,0.298,-0.457,0.127,0.408,0.277,-0.735,-0.358,0.199,0.784,0.313,0.354,-0.787,-0.46,0.275,0.746,-0.067,0.261,-0.887,-0.763,0.19,0.492,-0.46,0.394,-0.729,-0.875,0.352,0.094,0.397,-0.0060,-0.623,-0.263,-0.074,0.687,0.134,-0.112,-0.604,-0.4,-0.166,0.455,-0.092,-0.016,-0.766,-0.669,-0.076,0.377,-0.444,0.011,-0.6,-0.746,-0.02,-0.0010,0.501,-0.303,-0.026,0.29,-0.325,0.392,0.351,-0.381,-0.044,0.189,-0.397,0.276,0.541,-0.66,-0.085,0.281,-0.687,0.43,0.509,-0.451,-0.047,0.284,-0.474,0.399,0.593,-0.859,-0.113,0.298,-0.889,0.472,0.465,-0.715,0.04,0.338,-0.728,0.291,0.429,-0.499,0.05,0.317,-0.51,0.273,0.557,-0.894,0.051,0.409,-0.909,0.343,0.508,-0.232,-0.0010,0.311,-0.252,0.389,0.534,-0.174,0.024,0.344,-0.194,0.4,0.552,-0.117,0.045,0.37,-0.136,0.407,0.28,-0.364,-0.114,0.09,-0.384,0.262,-0.071,-0.321,-0.385,-0.338,-0.348,0.144,-0.309,-0.18,-0.551,-0.618,-0.211,0.063,-0.223,0.85,-0.576,-0.63,0.808,0.232,0.048,0.94,-0.435,-0.359,0.898,0.373,0.327,0.889,-0.297,-0.081,0.847,0.511,0.536,0.58,-0.216,0.122,0.538,0.606,0.584,0.468,-0.496,-0.069,0.401,0.8,0.489,0.505,-0.437,-0.08,0.447,0.692,0.266,0.734,-0.546,-0.31,0.675,0.597,0.413,0.608,-0.654,-0.304,0.534,0.768,0.193,0.64,-0.763,-0.524,0.567,0.658,0.04,0.758,-0.659,-0.537,0.699,0.484,-0.175,0.666,-0.772,-0.751,0.607,0.371,-0.014,0.541,-0.873,-0.731,0.468,0.549,-0.275,0.303,-0.815,-0.83,0.246,0.286,-0.27,-0.0030,-0.679,-0.706,-0.048,0.185,0.156,0.346,-0.823,-0.582,0.271,0.64,0.332,-0.139,-0.295,-0.034,-0.177,0.429,0.026,-0.193,-0.479,-0.361,-0.233,0.288,0.152,0.424,-0.9,-0.649,0.342,0.689,0.251,-0.115,-0.747,-0.445,-0.187,0.633,0.186,-0.082,-1.075,-0.748,-0.178,0.778,0.19,0.075,-1.337,-0.963,-0.043,0.949,0.201,0.344,-1.396,-1.014,0.219,1.015,0.13,0.525,-1.291,-0.98,0.411,0.911,0.135,0.494,-1.054};
			return value;
		}
		private double[] getcoord_Suzanne_8_279_point_5()
		{
			double[] value = {-0.785,0.399,0.772,0.159,0.433,-1.036,-0.755,0.339,0.776,0.144,0.455,-1.235,-0.925,0.346,0.883,0.18,0.31,-1.312,-0.959,0.193,0.945,0.176,0.098,-1.264,-0.913,-0.014,0.896,0.197,-0.018,-1.058,-0.73,-0.114,0.782,0.262,-0.044,-0.799,-0.483,-0.12,0.679,0.185,0.381,-0.921,-0.645,0.296,0.724,0.138,0.321,-0.974,-0.712,0.234,0.713,0.212,-0.0010,-0.883,-0.582,-0.083,0.692,0.142,0.015,-1.093,-0.793,-0.081,0.761,0.13,0.109,-1.26,-0.939,-0.0010,0.858,0.135,0.266,-1.302,-0.975,0.152,0.9,0.103,0.373,-1.243,-0.951,0.265,0.848,0.107,0.357,-1.075,-0.814,0.263,0.751,0.163,0.308,-0.848,-0.596,0.23,0.657,0.116,0.185,-0.869,-0.636,0.108,0.622,0.089,0.104,-0.799,-0.593,0.034,0.552,0.118,0.099,-0.855,-0.62,0.023,0.608,0.135,0.03,-0.876,-0.624,-0.048,0.629,0.124,-0.0020,-0.848,-0.607,-0.077,0.601,0.264,0.027,-0.68,-0.389,-0.04,0.616,0.173,-0.0050,-0.719,-0.473,-0.072,0.563,0.153,0.055,-0.726,-0.494,-0.011,0.556,0.151,0.22,-0.806,-0.566,0.147,0.616,0.141,0.258,-0.914,-0.661,0.176,0.675,0.093,0.246,-0.939,-0.708,0.164,0.65,0.083,-0.0070,-0.87,-0.648,-0.082,0.58,0.097,0.026,-0.904,-0.669,-0.052,0.615,0.08,0.087,-0.883,-0.665,0.011,0.594,0.051,0.1,-0.828,-0.638,0.029,0.538,0.078,0.181,-0.897,-0.681,0.104,0.608,0.067,0.338,-1.114,-0.868,0.242,0.74,0.07,0.354,-1.278,-0.998,0.244,0.84,0.105,0.255,-1.344,-1.027,0.139,0.9,0.106,0.098,-1.299,-0.983,-0.013,0.861,0.096,0.011,-1.124,-0.845,-0.086,0.743,0.163,0.0020,-0.908,-0.631,-0.08,0.667,0.095,0.301,-1.005,-0.763,0.213,0.695,0.098,0.121,-0.943,-0.703,0.039,0.646,0.117,0.076,-0.988,-0.726,-0.011,0.684,0.111,0.138,-1.058,-0.788,0.046,0.726,0.103,0.184,-1.016,-0.761,0.095,0.698,0.101,0.247,-1.075,-0.813,0.153,0.737,0.116,0.201,-1.114,-0.833,0.104,0.768,0.131,0.226,-1.166,-0.867,0.124,0.813,0.114,0.287,-1.145,-0.863,0.187,0.792,-0.013,0.44,-1.131,-0.934,0.345,0.694,0.03,0.476,-1.362,-1.095,0.36,0.868,0.142,0.314,-1.445,-1.088,0.188,0.994,0.113,0.068,-1.411};
			return value;
		}
		private double[] getcoord_Suzanne_8_279_point_6()
		{
			double[] value = {-1.067,-0.053,0.93,0.039,-0.081,-1.149,-0.896,-0.177,0.704,0.076,-0.117,-0.852,-0.634,-0.19,0.555,0.0080,0.387,-0.939,-0.765,0.307,0.594};
			return value;
		}

		/** Large attribute array: IndexedFaceSet coordIndex field, scene-graph level=7, element #279, 2468 total numbers.
		 * Reassemble split array as single method to improve readability and runnability.
		 * Provide large array values via separate methods, hoping to avoid 'code too large' Java compilation errors. 
		 * Individual Java methods (including aggregated initializations) are limited to 64KB.
		 * @see https://stackoverflow.com/questions/2407912/code-too-large-compilation-error-in-java
		 * @see https://stackoverflow.com/questions/11437905/java-too-many-constants-jvm-error
		 */
		private MFInt32 getIndexedFaceSet_7_279_coordIndex()
		{
			MFInt32 IndexedFaceSet_7_279_coordIndex = new MFInt32()/*2.finalize*/
				.append(new MFInt32(getIndexedFaceSet_7_279_coordIndex_1()))
				.append(new MFInt32(getIndexedFaceSet_7_279_coordIndex_2()))
				.append(new MFInt32(getIndexedFaceSet_7_279_coordIndex_3()));
			return IndexedFaceSet_7_279_coordIndex;
		}
		/** Large attribute array: Coordinate DEF='coord_Suzanne' point field, scene-graph level=8, element #279, 1521 total numbers made up of 507 3-tuple values.
		 * Reassemble split array as single method to improve readability and runnability.
		 * Provide large array values via separate methods, hoping to avoid 'code too large' Java compilation errors. 
		 * Individual Java methods (including aggregated initializations) are limited to 64KB.
		 * @see https://stackoverflow.com/questions/2407912/code-too-large-compilation-error-in-java
		 * @see https://stackoverflow.com/questions/11437905/java-too-many-constants-jvm-error
		 */
		private MFVec3f getcoord_Suzanne_8_279_point()
		{
			MFVec3f coord_Suzanne_8_279_point = new MFVec3f()/*2.finalize*/
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_1()))
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_2()))
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_3()))
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_4()))
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_5()))
				.append(new MFVec3f(getcoord_Suzanne_8_279_point_6()));
			return coord_Suzanne_8_279_point;
		}

	/** The initialized model object, created within initialize() method. */
	private X3D x3dModel;

	/** 
	 * Provide a 
	 * <a href="https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim" target="_blank">shallow copy</a>
	 * of the X3D model.
	 * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html">X3D</a>
	 * @return ThirdPersonViewFollower model
	 */
	public X3D getX3dModel()
	{	  
		return x3dModel;
	}
	   
    /** 
     * Default main() method provided for test purposes, uses CommandLine to set global ConfigurationProperties for this object.
     * @param args array of input parameters, provided as arguments
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#handleArguments-java.lang.String:A-">X3D.handleArguments(args)</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#validationReport--">X3D.validationReport()</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html">CommandLine</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html#USAGE">CommandLine.USAGE</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/ConfigurationProperties.html">ConfigurationProperties</a>
     */
    public static void main(String args[])
    {
        System.out.println("Build this X3D model, showing validation diagnostics...");
        X3D thisExampleX3dModel = new ThirdPersonViewFollower().getX3dModel();
//      System.out.println("X3D model construction complete.");
	
        // next handle command line arguments
        boolean hasArguments = (args != null) && (args.length > 0);
        boolean validate = true; // default
        boolean argumentsLoadNewModel = false;
        String  fileName = new String();

        if (args != null)
        {
                for (String arg : args)
                {
                        if (arg.toLowerCase().startsWith("-v") || arg.toLowerCase().contains("validate"))
                        {
                                validate = true; // making sure
                        }
                        if (arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3D) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_CLASSICVRML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3DB) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_VRML97) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_EXI) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_GZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_ZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_HTML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_XHTML))
                        {
                                argumentsLoadNewModel = true;
                                fileName = arg;
                        }
                }
        }
        if      (argumentsLoadNewModel)
                System.out.println("WARNING: \"Basic.Followers.ThirdPersonViewFollower\" model invocation is attempting to load file \"" + fileName + "\" instead of simply validating itself... file loading ignored.");
        else if (hasArguments) // if no arguments provided, this method produces usage warning
                thisExampleX3dModel.handleArguments(args);
	
        if (validate)
        {
            //  System.out.println("--- TODO fix duplicated outputs ---"); // omit when duplicated outputs problem is solved/refactored
		String validationResults = thisExampleX3dModel.validationReport();
            //  System.out.println("-----------------------------------"); // omit when duplicated outputs problem is solved/refactored
                System.out.print("Basic.Followers.ThirdPersonViewFollower self-validation test confirmation: ");
                if (!validationResults.equals("success"))
                    System.out.println();
                System.out.println(validationResults.trim());

                // experimental: test X3DJSAIL output files
                // Followers/ThirdPersonViewFollower_JavaExport.* file validation is checked when building X3D Example Archives
                String filenameX3D  = "Followers/ThirdPersonViewFollower_JavaExport.x3d"; 
                String filenameX3DV = "Followers/ThirdPersonViewFollower_JavaExport.x3dv"; 
                String filenameJSON = "Followers/ThirdPersonViewFollower_JavaExport.json";
                thisExampleX3dModel.toFileX3D        (filenameX3D);
                thisExampleX3dModel.toFileClassicVRML(filenameX3DV);
// TODO         thisExampleX3dModel.toFileJSON       (filenameJSON);
        }
    }
}
