<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile='Immersive' version='3.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-3.0.xsd'>
  <head>
    <meta content='Figure30.5ScriptTorusBuilder.x3d' name='title'/>
    <meta content='Figure 30.5, The VRML 2.0 Sourcebook, Copyright [1997] By Andrea L. Ames, David R. Nadeau, and John L. Moreland' name='creator'/>
    <meta content='http://www.wiley.com/legacy/compbooks/vrml2sbk/ch30/30fig05.htm' name='reference'/>
    <meta content='Don Brutzman' name='translator'/>
    <meta content='28 September 2000' name='created'/>
    <meta content='11 January 2014' name='modified'/>
    <meta content='A torus shape built with a donut-maker program script. Also see Figures 31.6 and 31.7 for comparison.' name='description'/>
    <meta content='http://www.web3d.org/x3d/content/examples/Vrml2Sourcebook/Chapter30-Scripts/Figure30.5ScriptTorusBuilder.x3d' name='identifier'/>
    <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/>
    <meta content='../../license.html' name='license'/>
  </head>
  <Scene>
    <Viewpoint description='Torus' orientation='1 0 0 -0.78' position='0 5 5'/>
    <Group>
      <Shape>
        <Extrusion DEF='Donut' beginCap='false' convex='false' creaseAngle='1.57' endCap='false'/>
        <Appearance>
          <Material diffuseColor='0 0.4 0.8'/>
        </Appearance>
      </Shape>
      <Script DEF='DonutMakerExternalScript' url='"donutmaker.js" "http://www.web3d.org/x3d/content/examples/Vrml2Sourcebook/Chapter30-Scripts/donutmaker.js"'>
        <field accessType='initializeOnly' name='spineRadius' type='SFFloat' value='2'/>
        <field accessType='initializeOnly' name='crossSectionRadius' type='SFFloat' value='1'/>
        <field accessType='initializeOnly' name='spineResolution' type='SFInt32' value='16'/>
        <field accessType='initializeOnly' name='crossSectionResolution' type='SFInt32' value='16'/>
        <field accessType='inputOnly' name='set_spineRadius' type='SFFloat'/>
        <field accessType='inputOnly' name='set_crossSectionRadius' type='SFFloat'/>
        <field accessType='outputOnly' name='spine_changed' type='MFVec3f'/>
        <field accessType='outputOnly' name='crossSection_changed' type='MFVec2f'/>
      </Script>
      <Script DEF='DonutMakerInternalScript'>
        <field accessType='initializeOnly' name='spineRadius' type='SFFloat' value='2'/>
        <field accessType='initializeOnly' name='crossSectionRadius' type='SFFloat' value='1'/>
        <field accessType='initializeOnly' name='spineResolution' type='SFInt32' value='16'/>
        <field accessType='initializeOnly' name='crossSectionResolution' type='SFInt32' value='16'/>
        <field accessType='inputOnly' name='set_spineRadius' type='SFFloat'/>
        <field accessType='inputOnly' name='set_crossSectionRadius' type='SFFloat'/>
        <field accessType='outputOnly' name='spine_changed' type='MFVec3f'/>
        <field accessType='outputOnly' name='crossSection_changed' type='MFVec2f'/>
        <![CDATA[
ecmascript:

function initialize( ) {
    generateCrossSection( );
    generateSpine( );
}

function set_crossSectionRadius( csr, ts ) {
    crossSectionRadius = csr;
    generateCrossSection( );
//  Browser.print ('crossSectionRadius = ' + csr);
}

function set_spineRadius( sr, ts ) {
    spineRadius = sr;
    generateSpine( );
//  Browser.print ('spineRadius = ' + sr);
}

function generateCrossSection( ) {
    angle = 0.0;
    delta = (2 * 3.141592653) / crossSectionResolution;
    for ( i = 0; i <= crossSectionResolution; i++ ) {
        crossSection_changed[i][0] =  crossSectionRadius * Math.cos( angle );
        crossSection_changed[i][1] = -crossSectionRadius * Math.sin( angle );
        angle += delta;
    }
    // added code to make ends meet
    crossSection_changed[crossSectionResolution + 1][0] = crossSection_changed[0][0];
    crossSection_changed[crossSectionResolution + 1][1] = crossSection_changed[0][1];
}

function generateSpine( ) {
    angle = 0.0;
    delta = (2 * 3.141592653) / spineResolution;
    for ( i = 0; i <= spineResolution; i++ ) {
        spine_changed[i][0] =  spineRadius * Math.cos( angle );
        spine_changed[i][1] =  0.0;
        spine_changed[i][2] = -spineRadius * Math.sin( angle );
        angle += delta;
    }
    // added code to make ends meet
    spine_changed[spineResolution + 1][0] = spine_changed[0][0];
    spine_changed[spineResolution + 1][1] = 0.0;
    spine_changed[spineResolution + 1][2] = spine_changed[0][2];
}
]]>
      </Script>
    </Group>
    <!-- Either ROUTE from DonutMakerExternalScript or DonutMakerInternalScript, both methods work -->
    <ROUTE fromField='spine_changed' fromNode='DonutMakerInternalScript' toField='set_spine' toNode='Donut'/>
    <ROUTE fromField='crossSection_changed' fromNode='DonutMakerInternalScript' toField='set_crossSection' toNode='Donut'/>
  </Scene>
</X3D>