<?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=' CameraPrototypes.x3d '/>
<meta name='descriptioncontent='Camera, CameraShot and CameraMovement prototypes that demonstrate storyboard capabilities and precise camera operation. This is a developmental effort for potential X3D Specification improvement.'/>
<meta name='creatorcontent='Don Brutzman and Jeff Weekley'/>
<meta name='createdcontent='16 March 2009'/>
<meta name='modifiedcontent='20 January 2020'/>
<meta name=' TODO content=' Schematron rules, backed up by initialize() checks '/>
<meta name='referencecontent=' BeyondViewpointCameraNodesWeb3D2009.pdf '/>
<meta name='referencecontent=' https://www.web3d.org/x3d/specifications/ISO-IEC-FDIS-19775-1.2-X3D-AbstractSpecification/Part01/components/navigation.html '/>
<meta name='subjectcontent='Camera nodes for Viewpoint navigation control'/>
<meta name='referencecontent=' CameraExamples.x3d '/>
<meta name='identifiercontent=' https://www.web3d.org/x3d/content/examples/Basic/development/CameraPrototypes.x3d '/>
<meta name='referencecontent=' http://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/development/CameraPrototypes.x3d '/>
<meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../license.html'/>
</head>
<!-- -->
<Scene>
<!-- =============== Camera ============== -->
<WorldInfo title='CameraPrototypes.x3d'/>
<ProtoDeclare name='Cameraappinfo='Camera node provides direct control of scene view to enable cinematic camera animation shot by shot and move by move along with still digital-photography settings for offline rendering of camera images.' >
<!-- Viewpoint-related fields, NavigationInfo-related fields and Camera-unique fields -->
<ProtoInterface>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this Camera' />

<field name='positiontype='SFVec3fvalue='0 0 10accessType='inputOutput'
 appinfo='Camera position in local transformation frame, which is default prior to first CameraShot initialPosition getting activated' />

<field name='orientationtype='SFRotationvalue='0 0 1 0accessType='inputOutput'
 appinfo='Camera rotation in local transformation frame, which is default prior to first CameraShot initialPosition getting activated' />

<field name='fieldOfViewtype='SFFloatvalue='0.7854accessType='inputOutput'
 appinfo='pi/4' />

<field name='set_fractiontype='SFFloataccessType='inputOnly'
 appinfo='input fraction drives interpolators' />

<field name='set_bindtype='SFBoolaccessType='inputOnly'
 appinfo='input event binds or unbinds this Camera' />

<field name='bindTimetype='SFTimeaccessType='outputOnly'
 appinfo='output event indicates when this Camera is bound' />

<field name='isBoundtype='SFBoolaccessType='outputOnly'
 appinfo='output event indicates whether this Camera is bound or unbound' />

<field name='nearClipPlanetype='SFFloatvalue='0.25accessType='inputOutput'
 appinfo='Vector distance to near clipping plane corresponds to NavigationInfo.avatarSize[0]' />

<field name='farClipPlanetype='SFFloatvalue='0.0accessType='inputOutput'
 appinfo='Vector distance to far clipping plane corresponds to NavigationInfo.visibilityLimit' />

<field name='shotstype='MFNodeaccessType='inputOutput'
 appinfo='Array of CameraShot nodes which in turn contain CameraMovement nodes' >
<!-- initialization nodes (if any) go here -->
</field>
<field name='headlighttype='SFBoolvalue='trueaccessType='inputOutput'
 appinfo='Whether camera headlight is on or off' />

<field name='headlightColortype='SFColorvalue='1 1 1accessType='inputOutput'
 appinfo='Camera headlight color' />

<field name='headlightIntensitytype='SFFloatvalue='1accessType='inputOutput'
 appinfo='Camera headlight intensity' />

<field name='filterColortype='SFColorvalue='1 1 1accessType='inputOutput'
 appinfo='Camera filter color that modifies virtual lens capture' />

<field name='filterTransparencytype='SFFloatvalue='1accessType='inputOutput'
 appinfo='Camera filter transparency that modifies virtual lens capture' />

<field name='upVectortype='SFVec3fvalue='0 1 0accessType='inputOutput'
 appinfo='upVector changes modify camera orientation (and possibly vice versa)' />

<field name='fStoptype='SFFloatvalue='5.6accessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='focusDistancetype='SFFloatvalue='10accessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='totalDurationtype='SFTimeaccessType='outputOnly'
 appinfo='Total duration of contained enabled CameraShot (and thus CameraMovement) move durations' />

<field name='offlineRendertype='SFNodeaccessType='inputOutput'
 appinfo='OfflineRender node' >
<!-- initialization node (if any) goes here -->
</field>
<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />
</ProtoInterface>
<ProtoBody>
<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='positionprotoField='position'/>
<connect nodeField='orientationprotoField='orientation'/>
<connect nodeField='fieldOfViewprotoField='fieldOfView'/>
<connect nodeField='set_bindprotoField='set_bind'/>
<connect nodeField='bindTimeprotoField='bindTime'/>
<connect nodeField='isBoundprotoField='isBound'/>
</IS>
</Viewpoint>
<!-- NavInfo EXAMINE used since some browsers (InstantReality) try to lock view to vertical when flying to avoid disorientation -->
<!-- ROUTE information for CameraNavInfo node:  [from CameraScript.isActive to set_bind ] -->
<NavigationInfo DEF='CameraNavInfotype='"EXAMINE" "FLY" "ANY"'>
<IS>
<connect nodeField='set_bindprotoField='set_bind'/>
<!-- No need to bind outputs bindTime, isBound from NavigationInfo since Viewpoint outputs will suffice. TODO inform BitManagement that bindTime field is missing. -->
<connect nodeField='headlightprotoField='headlight'/>
<connect nodeField='visibilityLimitprotoField='farClipPlane'/>
</IS>
</NavigationInfo>
<!-- this DirectionalLight replaces NavigationInfo headlight in order to add color capability -->
<!-- ROUTE information for CameraDirectionalLight node:  [from CameraScript.isActive to on ] -->
<DirectionalLight DEF='CameraDirectionalLightglobal='true'>
<IS>
<connect nodeField='onprotoField='headlight'/>
<connect nodeField='colorprotoField='headlightColor'/>
<connect nodeField='intensityprotoField='headlightIntensity'/>
</IS>
<!-- TODO confirm other default field values match NavigationInfo spec -->
</DirectionalLight>
<!-- ROUTE information for CameraPositionInterpolator node:  [from value_changed to CameraViewpoint.position ] -->
<PositionInterpolator DEF='CameraPositionInterpolatorkey='0 1keyValue='0 0 0 0 0 0'>
<IS>
<connect nodeField='set_fractionprotoField='set_fraction'/>
</IS>
</PositionInterpolator>
<!-- ROUTE information for CameraOrientationInterpolator node:  [from value_changed to CameraViewpoint.orientation ] -->
<OrientationInterpolator DEF='CameraOrientationInterpolatorkey='0 1keyValue='0 1 0 0 0 1 0 0'>
<IS>
<connect nodeField='set_fractionprotoField='set_fraction'/>
</IS>
</OrientationInterpolator>
< ROUTE  fromNode=' CameraPositionInterpolator' fromField='value_changed' toNode=' CameraViewpoint' toField='position'/>
< ROUTE  fromNode=' CameraOrientationInterpolator' fromField='value_changed' toNode=' CameraViewpoint' toField='orientation'/>
<!-- binding is controlled externally, all camera operations proceed the same regardless of whether bound or not -->
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this Camera' />

<field name='positiontype='SFVec3faccessType='inputOutput'
 appinfo='Camera position in local transformation frame' />

<field name='orientationtype='SFRotationaccessType='inputOutput'
 appinfo='Camera rotation in local transformation frame' />

<field name='set_fractiontype='SFFloataccessType='inputOnly'
 appinfo='input fraction drives interpolators' />

<field name='set_bindtype='SFBoolaccessType='inputOnly'
 appinfo='input event binds or unbinds this Camera' />

<field name='fieldOfViewtype='SFFloataccessType='inputOutput'
 appinfo='pi/4' />

<field name='nearClipPlanetype='SFFloataccessType='inputOutput'
 appinfo='Vector distance to near clipping plane' />

<field name='farClipPlanetype='SFFloataccessType='inputOutput'
 appinfo='Vector distance to far clipping plane' />

<field name='shotstype='MFNodeaccessType='inputOutput'
 appinfo='Array of CameraShot nodes which in turn contain CameraMovement nodes' >
<!-- initialization nodes (if any) go here -->
</field>
<field name='filterColortype='SFColoraccessType='inputOutput'
 appinfo='Camera filter color that modifies virtual lens capture' />

<field name='filterTransparencytype='SFFloataccessType='inputOutput'
 appinfo='Camera filter transparency that modifies virtual lens capture' />

<field name='upVectortype='SFVec3faccessType='inputOutput'
 appinfo='upVector changes modify camera orientation (and possibly vice versa)' />

<field name='fStoptype='SFFloataccessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='focusDistancetype='SFFloataccessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='totalDurationtype='SFTimeaccessType='outputOnly'
 appinfo='Total duration of contained enabled CameraShot (and thus CameraMovement) move durations' />

<field name='offlineRendertype='SFNodeaccessType='inputOutput'
 appinfo='OfflineRender node' >
<!-- initialization node (if any) goes here -->
</field>
<field name='ViewpointNodetype='SFNodeaccessType='initializeOnly'
 appinfo='node reference to permit getting setting fields from within Script' >
<Viewpoint USE=' CameraViewpoint'/>
</field>
<field name='NavInfoNodetype='SFNodeaccessType='initializeOnly'
 appinfo='node reference to permit getting setting fields from within Script' >
<NavigationInfo USE=' CameraNavInfo'/>
</field>
<field name='CameraPItype='SFNodeaccessType='initializeOnly'
 appinfo='node reference to permit getting setting fields from within Script' >
<PositionInterpolator USE=' CameraPositionInterpolator'/>
</field>
<field name='CameraOItype='SFNodeaccessType='initializeOnly'
 appinfo='node reference to permit getting setting fields from within Script' >
<OrientationInterpolator USE=' CameraOrientationInterpolator'/>
</field>
<field name='keytype='MFFloataccessType='inputOutput'
 appinfo='key array for interpolators' />

<field name='keyValuePositiontype='MFVec3faccessType='inputOutput'
 appinfo='keyValue array for PositionInterpolator' />

<field name='keyValueOrientationtype='MFRotationaccessType='inputOutput'
 appinfo='keyValue array for OrientationInterpolator' />

<field name='animatedtype='SFBoolvalue='falseaccessType='inputOutput'
 appinfo='whether internal CameraShot and CameraMove nodes are tracking or changed via ROUTE events' />

<field name='initializedtype='SFBoolvalue='falseaccessType='initializeOnly'
 appinfo='perform checkShots() function once immediately after initialization' />

<field name='shotCounttype='SFInt32value='0accessType='initializeOnly'
 appinfo='how many CameraShot nodes are contained in shots array' />

<field name='movesCounttype='SFInt32value='0accessType='initializeOnly'
 appinfo='how many CameraMove nodes are contained in moves array' />

<field name='frameCounttype='SFFloatvalue='0accessType='initializeOnly'
 appinfo='how many frames were created in current loop' />

<field name='startTimetype='SFTimevalue='0accessType='initializeOnly'
 appinfo='holding variable' />

<field name='priorTraceTimetype='SFTimevalue='0accessType='initializeOnly'
 appinfo='holding variable' />

<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />

<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='positionprotoField='position'/>
<connect nodeField='orientationprotoField='orientation'/>
<connect nodeField='set_fractionprotoField='set_fraction'/>
<connect nodeField='set_bindprotoField='set_bind'/>
<connect nodeField='fieldOfViewprotoField='fieldOfView'/>
<connect nodeField='nearClipPlaneprotoField='nearClipPlane'/>
<connect nodeField='farClipPlaneprotoField='farClipPlane'/>
<connect nodeField='shotsprotoField='shots'/>
<connect nodeField='filterColorprotoField='filterColor'/>
<connect nodeField='filterTransparencyprotoField='filterTransparency'/>
<connect nodeField='upVectorprotoField='upVector'/>
<connect nodeField='fStopprotoField='fStop'/>
<connect nodeField='focusDistanceprotoField='focusDistance'/>
<connect nodeField='isActiveprotoField='isActive'/>
<connect nodeField='totalDurationprotoField='totalDuration'/>
<connect nodeField='offlineRenderprotoField='offlineRender'/>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
</IS>
<![CDATA[
          
ecmascript:
function initialize () // CameraScript
{
//  tracePrint ('initialize start...');

    NavInfoNode.avatarSize[0]   = nearClipPlane;

    // remaining setups deferred to invocation of checkShots() method
    // thanks to Yvonne Jung Fraunhofer for diagnosing better approach to function initialization
    alwaysPrint ('initialize complete');
}

function checkShots (eventValue)
{
    tracePrint ('checkShots() method should only occur after initialize() methods in all other Scripts are complete');

    // compute totalDuration by summing durations from contained CameraShot and CameraMovement nodes
    totalDuration= 0;
    shotCount  = shots.length;
    movesCount = 0;
    for (i = 0; i < shotCount; i++) // shots index
    {
       tracePrint ('shots[' + i + '].moves.length=' + shots[i].moves.length);
       movesCount   += shots[i].moves.length;
       totalDuration = totalDuration + shots[i].shotDuration;
       if (shots[i].moves.length == 0)
       {
          alwaysPrint ('warning: CameraShot[' + i + '][' + shots[i].description + '] has no contained CameraMove nodes');
       }
    }
    // size checks before proceeding
    if (shotCount == 0)
    {
       alwaysPrint ('warning: no CameraShot nodes found for the shots, nothing to do!');
       return;
    }
    else if (movesCount == 0)
    {
       alwaysPrint ('warning: no CameraMove nodes found for the shots, nothing to do!');
       return;
    }
    else if (totalDuration == 0)
    {
       alwaysPrint ('warning: totalDuration = 0 seconds, nothing to do!');
       return;
    }
    tracePrint ('number of contained CameraShot nodes=' + shotCount);
    tracePrint ('number of contained CameraMove nodes=' + movesCount);
    tracePrint ('totalDuration=' + totalDuration + ' seconds for all shots and moves');

    // compute interpolators
    var k = 0; // index for latest key, keyValuePosition, keyValueOrientation
    for (i = 0; i < shotCount; i++) // shots index
    {
        if (i==0) // initial entries
        {
           key[0]                   = 0.0; // no previous move
           keyValuePosition[0]      = shots[i].initialPosition;
           keyValueOrientation[0]   = shots[i].initialOrientation;
        }
        else     // new shot repositions, reorients camera as clean break from preceding shot/move
        {
           key[k+1]                 = key[k]; // start from end from previous move
           keyValuePosition[k+1]    = shots[i].initialPosition;
           keyValueOrientation[k+1] = shots[i].initialOrientation;
           k++;
        }
        tracePrint (shots[i].description);
        tracePrint ('shots[i].moves.length=' + shots[i].moves.length);

        for (j = 0; j < shots[i].moves.length; j++) // moves index
        {
            var durationFloat =              shots[i].moves[j].duration;  // implicit type conversion from SFTime
            //  durationFloat = new SFFloat (shots[i].moves[j].duration); // explicit type conversion from SFTime
            //  tracePrint ('durationFloat=' + durationFloat);
            key[k+1]               = key[k] + (durationFloat / totalDuration);
            keyValuePosition[k+1]  = shots[i].moves[j].goalPosition;
            if (!animated)
            {
                 keyValueOrientation[k+1] = shots[i].moves[j].goalOrientation;
            }
            else
            {
                // using constructor SFRotation (SFVec3f fromVector, SFVec3f toVector)
                // see X3D ECMAScript binding Table 7.18 — SFRotation instance creation functions

                // test if difference vector is zero, if so maintain previous rotation
                var shotVector = ViewpointNode.position.subtract(shots[i].moves[j].goalAimPoint).normalize();
                if (shotVector.length() >= 0)
                {
                    // default view direction is along -Z axis
                    shots[i].moves[j].goalOrientation = new SFRotation (new SFVec3f (0, 0, 1), shotVector);
                    keyValueOrientation[k+1] = shots[i].moves[j].goalOrientation;
                }
                else // note (k > 0)
                {
                    keyValueOrientation[k+1] = keyValueOrientation[k];  // no change
                }

                tracePrint ('shots[' + i + '].moves[' + j + '].goalAimPoint=' + shots[i].moves[j].goalAimPoint.toString());
                tracePrint ('        ViewpointNode.position=' + ViewpointNode.position.toString());
                tracePrint ('          shotVector     delta=' + ViewpointNode.position.subtract(shots[i].moves[j].goalAimPoint).toString());
                tracePrint ('          shotVector normalize=' + ViewpointNode.position.subtract(shots[i].moves[j].goalAimPoint).normalize().toString());
                tracePrint ('               goalOrientation=' + shots[i].moves[j].goalOrientation.toString());
                tracePrint ('      keyValueOrientation[k+1]=' + keyValueOrientation[k+1].toString());
            }
            k++; // update index to match latest key, keyValuePosition, keyValueOrientation

            // check animated parameter:  set true if any of moves are tracking moves
            if (!animated)  animated = shots[i].moves[j].tracking; // once true, remains true
         // tracePrint ('shots[' + i + '].moves[' + j + '].tracking=' + shots[i].moves[j].tracking + ', animated=' + animated);

            // intermediate trace
            tracePrint ('                key=' + key);
            tracePrint ('   keyValuePosition=' + keyValuePosition);
            tracePrint ('keyValueOrientation=' + keyValueOrientation);
            tracePrint ('- ' + shots[i].moves[j].description);
        }
    }
    tracePrint ('                key=' + key);
    tracePrint ('   keyValuePosition=' + keyValuePosition);
    tracePrint ('keyValueOrientation=' + keyValueOrientation);
    if (key.length != keyValuePosition.length)
    {
      alwaysPrint ('warning: internal error during array construction, ' +
                  'key.length=' + key.length + ' must equal ' +
                  'keyValuePosition.length=' + keyValuePosition.length);
    }
    if (key.length != keyValueOrientation.length)
    {
      alwaysPrint ('warning: internal error during array construction, ' +
                  'key.length=' + key.length + ' must equal ' +
                  'keyValueOrientation.length=' + keyValueOrientation.length);
    }
    if (key.length != (shotCount + movesCount))
    {
      alwaysPrint ('warning: internal error during array construction, ' +
                  'key.length=' + key.length + ' must equal ' +
                  '(shotCount + movesCount)=' + (shotCount + movesCount));
    }
    tracePrint ('           animated=' + animated);
    // set node values
    CameraPI.key      = key;
    CameraOI.key      = key;
    CameraPI.keyValue = keyValuePosition;
    CameraOI.keyValue = keyValueOrientation;

    if (!animated) // output results
    {
        tracePrint ('<PositionInterpolator    DEF=\'CameraPositionInterpolator\'    key=\'' + stripBrackets(CameraPI.key) + '\' keyValue=\'' + stripBrackets(CameraPI.keyValue) + '\'/>');
        tracePrint ('<OrientationInterpolator DEF=\'CameraOrientationInterpolator\' key=\'' + stripBrackets(CameraOI.key) + '\' keyValue=\'' + stripBrackets(CameraOI.keyValue) + '\'/>');
    }
    tracePrint ('checkShots() complete');
}

function stripBrackets (fieldArray)
{
    // some browsers add brackets to array output strings, this function strips them
    outputString = '';
    for (i = 0; i < fieldArray.length; i++)
    {
       outputString += fieldArray[i].toString();
       if (i < fieldArray.length - 1) outputString += ' ';
    }
    return outputString;
}

function set_fraction (eventValue, timestamp) // input event received for inputOnly field
{
   // traceEnabled = false;  // for testing purposes

   // if Camera is being animated, immediately recompute interpolator settings
   if (animated) checkShots (true);

   // trace progress on console with reduced output frequency
   if (frameCount == 0)
   {
      alwaysPrint ('Animation loop commencing, timestamp=' + timestamp);
      startTime      = timestamp;
      priorTraceTime = timestamp;
      alwaysPrint ('shotClock=' + (timestamp - startTime) + ' seconds, frameCount=' + frameCount + ', fraction=' + eventValue + ', position=' + ViewpointNode.position.toString() + ', orientation=' + ViewpointNode.orientation.toString());

      if (animated) // output results
      {
        // TODO how to report or speed up response?  alwaysPrint ('  aimPoint=' + aimPoint.toString());
        tracePrint ('  <PositionInterpolator    DEF=\'CameraPositionInterpolator\'    key=\'' + stripBrackets(CameraPI.key) + '\' keyValue=\'' + stripBrackets(CameraPI.keyValue) + '\'/>');
        tracePrint ('  <OrientationInterpolator DEF=\'CameraOrientationInterpolator\' key=\'' + stripBrackets(CameraOI.key) + '\' keyValue=\'' + stripBrackets(CameraOI.keyValue) + '\'/>');
      }
   }
   else if ((timestamp - priorTraceTime) >= 1.0) // 1 second trace interval
   {
      alwaysPrint ('shotClock=' + (timestamp - startTime) + ' seconds, frameCount=' + frameCount + ', fraction=' + eventValue + ', position=' + ViewpointNode.position.toString() + ', orientation=' + ViewpointNode.orientation.toString());
      priorTraceTime = timestamp;

      if (animated) // output results
      {
        // TODO how to report or speed up response?  alwaysPrint ('  aimPoint=' + aimPoint.toString());
        tracePrint ('  <PositionInterpolator    DEF=\'CameraPositionInterpolator\'    key=\'' + stripBrackets(CameraPI.key) + '\' keyValue=\'' + stripBrackets(CameraPI.keyValue) + '\'/>');
        alwaysPrint ('  <OrientationInterpolator DEF=\'CameraOrientationInterpolator\' key=\'' + stripBrackets(CameraOI.key) + '\' keyValue=\'' + stripBrackets(CameraOI.keyValue) + '\'/>');
      }
   }
   if (eventValue == 0)
   {
      // note that zero value is not necessarily sent first by TimeSensor, so otherwise ignored
      frameCount++;
   }
   else if (eventValue == 1)
   {
      alwaysPrint ('shotClock=' + (timestamp - startTime) + ', frameCount=' + frameCount + ', fraction=' + eventValue + ', position=' + ViewpointNode.position.toString() + ', orientation=' + ViewpointNode.orientation.toString());
      if (animated) // output results
      {
        // TODO how to report or speed up response?  alwaysPrint ('  aimPoint=' + aimPoint.toString());
      }
      alwaysPrint ('Animation loop complete.');
      // do not unbind the Viewpoint and NavigationInfo nodes, let that be controlled externally
   }
   else
   {
      frameCount++;
   }
}

function set_bind (eventValue) // input event received for inputOnly field
{
   // need to ensure CameraShot nodes are properly initialized
   if (initialized == false)
   {
      checkShots (true);
      initialized = true;
   }
   if (eventValue)
   {
       tracePrint ('Camera has been bound');
   }
   else
   {
       tracePrint ('Camera has been unbound');
   }
}

function set_description (eventValue) // input event received for inputOutput field
{
    description = eventValue;
}

function set_position (eventValue) // input event received for inputOutput field
{
    position = eventValue;
}

function set_orientation (eventValue) // input event received for inputOutput field
{
    orientation = eventValue;
}

function set_fieldOfView (eventValue) // input event received for inputOutput field
{
    fieldOfView = eventValue;
}

function set_nearClipPlane (eventValue) // input event received for inputOutput field
{
    nearClipPlane = eventValue;
}

function set_farClipPlane (eventValue) // input event received for inputOutput field
{
    farClipPlane = eventValue;
}

function set_shots (eventValue) // input event received for inputOutput field
{
    shots = eventValue;
}

function set_filterColor (eventValue) // input event received for inputOutput field
{
    filterColor = eventValue;
}

function set_filterTransparency (eventValue) // input event received for inputOutput field
{
    filterTransparency = eventValue;
}

function set_upVector (eventValue) // input event received for inputOutput field
{
    upVector = eventValue;
}

function set_fStop (eventValue) // input event received for inputOutput field
{
    fStop = eventValue;
}

function set_focusDistance (eventValue) // input event received for inputOutput field
{
    focusDistance = eventValue;
}

function set_offlineRender (eventValue) // input event received for inputOutput field
{
    offlineRender = eventValue;
}

function set_key (eventValue) // input event received for inputOutput field
{
    key = eventValue;
}

function set_keyValuePosition (eventValue) // input event received for inputOutput field
{
    keyValuePosition = eventValue;
}

function set_keyValueOrientation (eventValue) // input event received for inputOutput field
{
    keyValueOrientation = eventValue;
}

function set_animated (eventValue) // input event received for inputOutput field
{
    animated = eventValue;
}

function tracePrint (outputValue)
{
	if (traceEnabled) alwaysPrint (outputValue);
}
function alwaysPrint (outputValue)
{
    // try to ensure outputValue is converted to string despite Browser.println idiosyncracies
    var outputString = outputValue.toString(); // utility function according to spec
    if (outputString == null) outputString = outputValue; // direct cast

    if  (description.length > 0)
         Browser.println ('[Camera: ' + description + '] ' + outputString);
    else
         Browser.println ('[Camera] ' + outputString);
}

        
]]>
</Script>
< ROUTE  fromNode=' CameraScript' fromField='position' toNode=' CameraViewpoint' toField='position'/>
< ROUTE  fromNode=' CameraScript' fromField='orientation' toNode=' CameraViewpoint' toField='orientation'/>
< ROUTE  fromNode=' CameraScript' fromField='isActive' toNode=' CameraViewpoint' toField='set_bind'/>
< ROUTE  fromNode=' CameraScript' fromField='isActive' toNode=' CameraNavInfo' toField='set_bind'/>
< ROUTE  fromNode=' CameraScript' fromField='isActive' toNode=' CameraDirectionalLight' toField='on'/>
</ProtoBody>
</ProtoDeclare>
<!-- =============== CameraShot ============== -->
<ProtoDeclare name='CameraShotappinfo='CameraShot collects a specific set of CameraMovement animations that make up an individual shot.' >
<ProtoInterface>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this CameraShot' />

<field name='enabledtype='SFBoolvalue='trueaccessType='inputOutput'
 appinfo='Whether this CameraShot can be activated' />

<field name='movestype='MFNodeaccessType='inputOutput'
 appinfo='Set of CameraMovement nodes' >
<!-- initializing CameraMovement nodes are inserted here by scene author using ProtoInstance -->
</field>
<field name='initialPositiontype='SFVec3fvalue='0 0 10accessType='inputOutput'
 appinfo='Setup to reinitialize camera position for this shot' />

<field name='initialOrientationtype='SFRotationvalue='0 0 1 0accessType='inputOutput'
 appinfo='Setup to reinitialize camera rotation for this shot' />

<field name='initialAimPointtype='SFVec3fvalue='0 0 0accessType='inputOutput'
 appinfo='Setup to reinitialize aimpoint (relative location for camera direction) for this shot' />

<field name='initialFieldOfViewtype='SFFloatvalue='0.7854accessType='inputOutput'
 appinfo='pi/4' />

<field name='initialFStoptype='SFFloatvalue='5.6accessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='initialFocusDistancetype='SFFloatvalue='10accessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='shotDurationtype='SFTimeaccessType='outputOnly'
 appinfo='Subtotal duration of contained CameraMovement move durations' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />
</ProtoInterface>
<ProtoBody>
<Script DEF='CameraShotScriptdirectOutput='truemustEvaluate='true'>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this CameraShot' />

<field name='enabledtype='SFBoolaccessType='inputOutput'
 appinfo='Whether this CameraShot can be activated' />

<field name='movestype='MFNodeaccessType='inputOutput'
 appinfo='Set of CameraMovement nodes' >
<!-- initialization nodes (if any) go here -->
</field>
<field name='initialPositiontype='SFVec3faccessType='inputOutput'
 appinfo='Setup to reinitialize camera position for this shot' />

<field name='initialOrientationtype='SFRotationaccessType='inputOutput'
 appinfo='Setup to reinitialize camera rotation for this shot' />

<field name='initialAimPointtype='SFVec3faccessType='inputOutput'
 appinfo='Setup to reinitialize aimpoint (relative location for camera direction) for this shot' />

<field name='initialFieldOfViewtype='SFFloataccessType='inputOutput'
 appinfo='pi/4' />

<field name='initialFStoptype='SFFloataccessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='initialFocusDistancetype='SFFloataccessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='shotDurationtype='SFTimeaccessType='outputOnly'
 appinfo='Subtotal duration of contained CameraMovement move durations' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />

<field name='keytype='MFFloataccessType='inputOutput'
 appinfo='key array for interpolators' />

<field name='keyValuePositiontype='MFVec3faccessType='inputOutput'
 appinfo='keyValue array for PositionInterpolator' />

<field name='keyValueOrientationtype='MFRotationaccessType='inputOutput'
 appinfo='keyValue array for OrientationInterpolator' />

<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='enabledprotoField='enabled'/>
<connect nodeField='movesprotoField='moves'/>
<connect nodeField='initialPositionprotoField='initialPosition'/>
<connect nodeField='initialOrientationprotoField='initialOrientation'/>
<connect nodeField='initialAimPointprotoField='initialAimPoint'/>
<connect nodeField='initialFieldOfViewprotoField='initialFieldOfView'/>
<connect nodeField='initialFStopprotoField='initialFStop'/>
<connect nodeField='initialFocusDistanceprotoField='initialFocusDistance'/>
<connect nodeField='shotDurationprotoField='shotDuration'/>
<connect nodeField='isActiveprotoField='isActive'/>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
</IS>
<![CDATA[
          
ecmascript:
function initialize () // CameraShotScript
{
//  tracePrint ('initialize start...');

    // compute shotDuration by summing durations from contained CameraMovement nodes
    shotDuration = 0;
    for (i = 0; i < moves.length; i++)
    {
        shotDuration = shotDuration + moves[i].duration;
    }
    alwaysPrint ('number of contained CameraMove nodes=' + moves.length + ', shotDuration=' + shotDuration + ' seconds');

//  tracePrint ('... initialize() complete');
}

function set_description (eventValue) // input event received for inputOutput field
{
    description = eventValue;
}

function set_enabled (eventValue) // input event received for inputOutput field
{
    enabled = eventValue;
}

function set_moves (eventValue) // input event received for inputOutput field
{
    moves = eventValue;
}

function set_initialPosition (eventValue) // input event received for inputOutput field
{
    initialPosition = eventValue;
}

function set_initialOrientation (eventValue) // input event received for inputOutput field
{
    initialOrientation = eventValue;
}

function set_initialAimPoint (eventValue) // input event received for inputOutput field
{
    initialAimPoint = eventValue;
}

function set_initialFieldOfView (eventValue) // input event received for inputOutput field
{
    initialFieldOfView = eventValue;
}

function set_initialFStop (eventValue) // input event received for inputOutput field
{
    initialFStop = eventValue;
}

function set_initialFocusDistance (eventValue) // input event received for inputOutput field
{
    initialFocusDistance = eventValue;
}

function set_key (eventValue) // input event received for inputOutput field
{
    key = eventValue;
}

function set_keyValuePosition (eventValue) // input event received for inputOutput field
{
    keyValuePosition = eventValue;
}

function set_keyValueOrientation (eventValue) // input event received for inputOutput field
{
    keyValueOrientation = eventValue;
}

// TODO consider method set_active for constructed Camera node BooleanSequencer to send isActive

function tracePrint (outputValue)
{
	if (traceEnabled) alwaysPrint (outputValue);
}
function alwaysPrint (outputValue)
{
	// try to ensure outputValue is converted to string despite browser idiosyncracies
    var outputString = outputValue.toString(); // utility function according to spec
    if (outputString == null) outputString = outputValue; // direct cast

    if  (description.length > 0)
         Browser.println ('[CameraShot: ' + description + '] ' + outputString);
    else
         Browser.println ('[CameraShot] ' + outputString);
}

        
]]>
</Script>
<!-- Add any ROUTEs here, going from Script to other nodes within ProtoBody -->
</ProtoBody>
</ProtoDeclare>
<!-- =============== CameraMovement ============== -->
<ProtoDeclare name='CameraMovementappinfo='CameraMovement node defines a single camera movement animation including goalPosition, goalOrientation, goalAimPoint and goalFieldOfView.' >
<ProtoInterface>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this CameraMovement' />

<field name='enabledtype='SFBoolvalue='trueaccessType='inputOutput'
 appinfo='Whether this CameraMovement can be activated' />

<field name='durationtype='SFFloatvalue='0accessType='inputOutput'
 appinfo='Duration in seconds for this move' />

<field name='goalPositiontype='SFVec3fvalue='0 0 10accessType='inputOutput'
 appinfo='Goal camera position for this move' />

<field name='goalOrientationtype='SFRotationvalue='0 0 1 0accessType='inputOutput'
 appinfo='Goal camera rotation for this move' />

<field name='trackingtype='SFBoolvalue='falseaccessType='inputOutput'
 appinfo='Whether or not camera direction is tracking towards the aimPoint' />

<field name='goalAimPointtype='SFVec3fvalue='0 0 0accessType='inputOutput'
 appinfo='Goal aimPoint for this move, ignored if tracking=false' />

<field name='goalFieldOfViewtype='SFFloatvalue='0.7854accessType='inputOutput'
 appinfo='Goal fieldOfView for this move' />

<field name='goalFStoptype='SFFloatvalue='5.6accessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='goalFocusDistancetype='SFFloatvalue='10accessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />
</ProtoInterface>
<ProtoBody>
<!-- First node determines node type of this prototype -->
<!-- Subsequent nodes do not render, but still must be a valid X3D subgraph -->
<!-- Script holds CameraMovement initialization values for query by parent CameraShot, and also permits changing values via events -->
<Script DEF='CameraMovementScriptdirectOutput='truemustEvaluate='true'>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this CameraMovement' />

<field name='enabledtype='SFBoolaccessType='inputOutput'
 appinfo='Whether this CameraMovement can be activated' />

<field name='durationtype='SFFloataccessType='inputOutput'
 appinfo='Duration in seconds for this move' />

<field name='goalPositiontype='SFVec3faccessType='inputOutput'
 appinfo='Goal camera position for this move' />

<field name='goalOrientationtype='SFRotationaccessType='inputOutput'
 appinfo='Goal camera rotation for this move' />

<field name='trackingtype='SFBoolaccessType='inputOutput'
 appinfo='Whether or not camera direction is tracking towards the aimPoint' />

<field name='goalAimPointtype='SFVec3faccessType='inputOutput'
 appinfo='Goal aimPoint for this move, ignored if tracking=false' />

<field name='goalFieldOfViewtype='SFFloataccessType='inputOutput'
 appinfo='Goal fieldOfView for this move' />

<field name='goalFStoptype='SFFloataccessType='inputOutput'
 appinfo='Focal length divided effective aperture diameter indicating width of focal plane' />

<field name='goalFocusDistancetype='SFFloataccessType='inputOutput'
 appinfo='Distance to focal plane of sharpest focus' />

<field name='isActivetype='SFBoolaccessType='outputOnly'
 appinfo='Mark start/stop with true/false output respectively useful to trigger external animations' />

<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />

<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='enabledprotoField='enabled'/>
<connect nodeField='durationprotoField='duration'/>
<connect nodeField='goalPositionprotoField='goalPosition'/>
<connect nodeField='goalOrientationprotoField='goalOrientation'/>
<connect nodeField='trackingprotoField='tracking'/>
<connect nodeField='goalAimPointprotoField='goalAimPoint'/>
<connect nodeField='goalFieldOfViewprotoField='goalFieldOfView'/>
<connect nodeField='goalFStopprotoField='goalFStop'/>
<connect nodeField='goalFocusDistanceprotoField='goalFocusDistance'/>
<connect nodeField='isActiveprotoField='isActive'/>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
</IS>
<![CDATA[
          
ecmascript:
function initialize () // CameraMovementScript
{
//  tracePrint ('initialize start...');
    alwaysPrint ('initialize goalPosition=' + goalPosition.toString() + ', goalOrientation=' + goalOrientation.toString() +
                           ', goalAimPoint=' + goalAimPoint.toString() // + ', tracking=' + tracking.toString()
                           );
    if (duration < 0)
    {
       alwaysPrint ('error: negative duration=' + duration + ', reset to 0 and ignored');
       duration = 0;
    }
    else if (duration == 0)
    {
       alwaysPrint ('warning: duration=0, nothing to do!');
    }
    tracePrint ('... initialize complete');
}

function set_goalAimPoint (eventValue) // input event received for inputOutput field
{
    goalAimPoint_changed = eventValue;
    tracePrint ('goalAimPoint=' + goalAimPoint.toString());

    // updated goalOrientation tracking is handled by Camera recomputing the OrientationInterpolator
}

function set_description (eventValue) // input event received for inputOutput field
{
    description = eventValue;
}

function set_enabled (eventValue) // input event received for inputOutput field
{
    enabled = eventValue;
}

function set_duration (eventValue) // input event received for inputOutput field
{
    duration = eventValue;
}

function set_goalPosition (eventValue) // input event received for inputOutput field
{
    goalPosition = eventValue;
}

function set_goalOrientation (eventValue) // input event received for inputOutput field
{
    goalOrientation = eventValue;
}

function set_tracking (eventValue) // input event received for inputOutput field
{
    tracking = eventValue;
}

function set_goalFieldOfView (eventValue) // input event received for inputOutput field
{
    goalFieldOfView = eventValue;
}

function set_goalFStop (eventValue) // input event received for inputOutput field
{
    goalFStop = eventValue;
}

function set_goalFocusDistance (eventValue) // input event received for inputOutput field
{
    goalFocusDistance = eventValue;
}

// TODO consider method set_active for constructed Camera node BooleanSequencer to send isActive

function tracePrint (outputValue)
{
	if (traceEnabled) alwaysPrint (outputValue);
}

function alwaysPrint (outputValue)
{
	// try to ensure outputValue is converted to string despite browser idiosyncracies
    var outputString = outputValue.toString(); // utility function according to spec
    if (outputString == null) outputString = outputValue; // direct cast

    if  (description.length > 0)
         Browser.println ('[CameraMovement: ' + description + '] ' + outputString);
    else
         Browser.println ('[CameraMovement] ' + outputString);
}

        
]]>
</Script>
<!-- Add any ROUTEs here, going from Script to other nodes within ProtoBody -->
</ProtoBody>
</ProtoDeclare>
<!-- =============== OfflineRender ============== -->
<ProtoDeclare name='OfflineRenderappinfo='OfflineRender defines a parameters for offline rendering of Camera animation output to a movie file (or possibly a still shot).' >
<ProtoInterface>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this OfflineRender' />

<field name='enabledtype='SFBoolvalue='trueaccessType='inputOutput'
 appinfo='Whether this OfflineRender can be activated' />

<field name='frameRatetype='SFFloatvalue='30accessType='inputOutput'
 appinfo='Frames per second recorded for this rendering' />

<field name='frameSizetype='SFVec2fvalue='640 480accessType='inputOutput'
 appinfo='Size of frame in number of pixels width and height' />

<field name='pixelAspectRatiotype='SFFloatvalue='1.33accessType='inputOutput'
 appinfo='Relative dimensions of pixel height/width typically 1.33 or 1' />

<field name='set_startTimetype='SFTimeaccessType='inputOnly'
 appinfo='Begin render operation' />

<field name='progresstype='SFFloataccessType='outputOnly'
 appinfo='Progress performing render operation (0..1)' />

<field name='renderCompleteTimetype='SFTimeaccessType='outputOnly'
 appinfo='Render operation complete' />

<field name='movieFormattype='MFStringvalue='"mpeg"accessType='initializeOnly'
 appinfo='Format of rendered output movie (mpeg mp4 etc.), use first supported format' />

<field name='imageFormattype='MFStringvalue='"png"accessType='initializeOnly'
 appinfo='Format of rendered output images (png jpeg gif tiff etc.) use first supported format' />

<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />

<!-- TODO non-photorealistic rendering (NPR) parameters -->
</ProtoInterface>
<ProtoBody>
<!-- First node determines node type of this prototype -->
<!-- Subsequent nodes do not render, but still must be a valid X3D subgraph -->
<Script DEF='OfflineRenderScriptmustEvaluate='true'>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='Text description to be displayed for this OfflineRender' />

<field name='enabledtype='SFBoolaccessType='inputOutput'
 appinfo='Whether this OfflineRender can be activated' />

<field name='frameRatetype='SFFloataccessType='inputOutput'
 appinfo='Frames per second recorded for this rendering' />

<field name='frameSizetype='SFVec2faccessType='inputOutput'
 appinfo='Size of frame in number of pixels width and height' />

<field name='pixelAspectRatiotype='SFFloataccessType='inputOutput'
 appinfo='Relative dimensions of pixel height/width typically 1.33 or 1' />

<field name='set_startTimetype='SFTimeaccessType='inputOnly'
 appinfo='Begin render operation' />

<field name='progresstype='SFFloataccessType='outputOnly'
 appinfo='Progress performing render operation (0..1)' />

<field name='renderCompleteTimetype='SFTimeaccessType='outputOnly'
 appinfo='Render operation complete' />

<field name='movieFormattype='MFStringaccessType='initializeOnly'
 appinfo='Format of rendered output movie (mpeg mp4 etc.)' />

<field name='imageFormattype='MFStringaccessType='initializeOnly'
 appinfo='Format of rendered output images (png jpeg gif tiff etc.)' />

<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
 appinfo='enable console output to trace script computations and prototype progress' />

<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='enabledprotoField='enabled'/>
<connect nodeField='frameRateprotoField='frameRate'/>
<connect nodeField='frameSizeprotoField='frameSize'/>
<connect nodeField='pixelAspectRatioprotoField='pixelAspectRatio'/>
<connect nodeField='set_startTimeprotoField='set_startTime'/>
<connect nodeField='progressprotoField='progress'/>
<connect nodeField='renderCompleteTimeprotoField='renderCompleteTime'/>
<connect nodeField='movieFormatprotoField='movieFormat'/>
<connect nodeField='imageFormatprotoField='imageFormat'/>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
</IS>
<![CDATA[
          
ecmascript:
function initialize () // OfflineRenderScript
{
//  tracePrint ('initialize start...');

    tracePrint ('... initialize complete');
}

function set_description (eventValue) // input event received for inputOutput field
{
    description = eventValue;
}

function set_enabled (eventValue) // input event received for inputOutput field
{
    enabled = eventValue;
}

function set_frameRate (eventValue) // input event received for inputOutput field
{
    frameRate = eventValue;
}

function set_frameSize (eventValue) // input event received for inputOutput field
{
    frameSize = eventValue;
}

function set_pixelAspectRatio (eventValue) // input event received for inputOutput field
{
    pixelAspectRatio = eventValue;
}

function set_startTime (eventValue) // input event received for inputOnly field
{
   // do something with input eventValue;
}

function tracePrint (outputValue)
{
	if (traceEnabled) alwaysPrint (outputValue);
}

function alwaysPrint (outputValue)
{
	// try to ensure outputValue is converted to string despite browser idiosyncracies
    var outputString = outputValue.toString(); // utility function according to spec
    if (outputString == null) outputString = outputValue; // direct cast

    if  (description.length > 0)
         Browser.println ('[OfflineRender: ' + description + '] ' + outputString);
    else
         Browser.println ('[OfflineRender] ' + outputString);
}

        
]]>
</Script>
<!-- Add any ROUTEs here, going from Script to other nodes within ProtoBody -->
</ProtoBody>
</ProtoDeclare>
<!-- =============== Launch Prototype Example ============== -->
<Background skyColor='0.282353 0.380392 0.470588'/>
<Anchor description='launch CameraExample scene'
  url=' CameraExamples.x3d"https://www.web3d.org/x3d/content/examples/Basic/development/CameraExamples.x3d" "CameraExamples.wrl" "https://www.web3d.org/x3d/content/examples/Basic/development/CameraExamples.wrl" ' >
<Transform>
<Shape>
<Text string='"CameraPrototypes.x3d" "defines multiple prototype nodes" "" "Click on this text to see" "CameraExamples.x3d scene"'>
<FontStyle justify='"MIDDLE" "MIDDLE"'/>
</Text>
<Appearance>
<Material diffuseColor='1 1 0.2'/>
</Appearance>
</Shape>
</Transform>
</Anchor>
</Scene>
</X3D>
<!--

to top <!-- Event Graph ROUTE Table shows event connections -->
 
<!-- Index for DEF nodes: CameraDirectionalLight, CameraMovementScript, CameraNavInfo, CameraOrientationInterpolator, CameraPositionInterpolator, CameraScript, CameraShotScript, CameraViewpoint, OfflineRenderScript

Index for Viewpoint nodes: Viewpoint_1, CameraViewpoint

Index for ProtoDeclare definitions: Camera, CameraMovement, CameraShot, OfflineRender
-->

Event Graph ROUTE Table entries with 7 ROUTE connections total, showing X3D event-model relationships for this scene.

Each row shows an event cascade that may occur during a single timestamp interval between frame renderings, as part of the X3D execution model.

CameraMovementScript
Script
No ROUTE connection found for output from this node.
 


CameraScript
Script
position
SFVec3f

ROUTE
event to
(1)
CameraViewpoint
Viewpoint
position
SFVec3f
CameraScript
Script
orientation
SFRotation

ROUTE
event to
(1)
CameraViewpoint
Viewpoint
orientation
SFRotation
CameraScript
Script
isActive
SFBool

ROUTE
event to
(1)
CameraViewpoint
Viewpoint
set_bind
SFBool
CameraScript
Script
isActive
SFBool

ROUTE
event to
(1)
CameraNavInfo
NavigationInfo
set_bind
SFBool
CameraScript
Script
isActive
SFBool

ROUTE
event to
(1)
CameraDirectionalLight
DirectionalLight
on
SFBool


CameraShotScript
Script
No ROUTE connection found for output from this node.
 


OfflineRenderScript
Script
No ROUTE connection found for output from this node.
 


-->

<!-- Online at
https://www.web3d.org/x3d/content/examples/Basic/development/CameraPrototypesIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/development/CameraPrototypes.x3d -->

<!-- Color legend: X3D terminology <X3dNode DEF='idName' field='value'/> matches XML terminology <XmlElement DEF='idName' attribute='value'/>
(Light-blue background: event-based behavior node or statement) (Grey background inside box: inserted documentation) (Magenta background: X3D Extensibility)
    <ProtoDeclare name='ProtoName'> <field name='fieldName'/> </ProtoDeclare> -->

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