| 1 |
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
|
| 3 | <X3D profile='Immersive' version='3.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.0.xsd'> |
| 4 | <head> |
| 5 | <meta name='title' content=' BathymetryGeneratorViaExtrusionPrototype.x3d '/> |
| 6 | <meta name='description' content='This prototype generates bathymetry based on the input data, and uses Extrusion as the output geometry (with some problems as a result).'/> |
| 7 | <meta name='creator' content='Jane Wu'/> |
| 8 | <meta name='created' content='8 January 2002'/> |
| 9 | <meta name='modified' content='28 November 2019'/> |
| 10 | <meta name='subject' content='bathymetry'/> |
| 11 | <meta name='reference' content='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#Extrusion'/> |
| 12 | <meta name='identifier' content=' https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/BathymetryGeneratorViaExtrusionPrototype.x3d '/> |
| 13 | <meta name='generator' content='X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit'/> |
| 14 | <meta name='license' content='../../license.html'/> |
| 15 | </head> |
| 16 | <Scene> |
| 17 | <WorldInfo title='BathymetryGeneratorViaExtrusionPrototype.x3d'/> |
| 18 | <ProtoDeclare name='BathymetryGenerator'> |
| 19 | <ProtoInterface> |
| 20 | <field name='positionArray' type='MFVec3f' value='0 0 0 10 -4 0 25 -6 0 30 -8 5 38 -15 5 45 -18 5 55 -22 5 60 -25 15 60 -27 22 55 -30 35 48 -35 35 35 -35 35 25 -45 35 20 -55 35 15 -70 35 3 -70 35 -5 -72 40 -5 -75 50 0 -80 55 15 -75 55 30 -70 55 35 -60 55 40 -50 55 50 -34 55 65 -23 70' accessType='initializeOnly'/> |
| 21 |
<field name='timeArray' type='MFTime' value='1 3 6 8 10 12 14 15 17 18 23 28 35 37 39 43 45 47 48 53 58 60 61 65 70' accessType='initializeOnly'
appinfo='for future development'/> |
| 22 | <field name='colorSchemeDepthRangeArray' type='MFVec2f' value='0 -10 -10 -20 -20 -30 -30 -40 -40 -50 -50 -60 -60 -70 -70 -999999' accessType='initializeOnly'/> |
| 23 | <field name='colorSchemeColorArray' type='MFColor' value='1 1 0.2 0.6 1 1 0 1 1 0.2 0.6 0.2 1 0 1 0.56 0 0.32 0.2 0.3 0.7 0 0 1' accessType='initializeOnly'/> |
| 24 | <field name='beamWidth' type='SFFloat' value='2' accessType='initializeOnly'/> |
| 25 | <field name='surfaceTransparency' type='SFFloat' value='0.25' accessType='initializeOnly'/> |
| 26 | <field name='traceEnabled' type='SFBool' value='false' accessType='initializeOnly'/> |
| 27 | </ProtoInterface> |
| 28 | <ProtoBody> |
| 29 | <Group> |
| 30 |
<!-- ROUTE information for Bathymetry node:
[from BathymetryScript.bathyNodes to addChildren
]
-->
<Transform DEF='Bathymetry'/> |
| 31 |
<!-- ROUTE information for BathymetryScript node:
[from bathyNodes to Bathymetry.addChildren
]
-->
<Script DEF='BathymetryScript' directOutput='true'> |
| 32 | <field name='positionArray' type='MFVec3f' accessType='initializeOnly'/> |
| 33 | <field name='timeArray' type='MFTime' accessType='initializeOnly'/> |
| 34 | <field name='colorSchemeDepthRangeArray' type='MFVec2f' accessType='initializeOnly'/> |
| 35 | <field name='colorSchemeColorArray' type='MFColor' accessType='initializeOnly'/> |
| 36 | <field name='beamWidth' type='SFFloat' accessType='initializeOnly'/> |
| 37 | <field name='transparency' type='SFFloat' accessType='initializeOnly'/> |
| 38 | <field name='spine' type='MFVec3f' value='0 0 0 0 1 0' accessType='initializeOnly'/> |
| 39 | <field name='scale' type='MFVec2f' value='1 1' accessType='initializeOnly'/> |
| 40 | <field name='orientation' type='MFRotation' value='0 0 1 0' accessType='initializeOnly'/> |
| 41 | <field name='bathyColor' type='SFColor' value='1 1 1' accessType='initializeOnly'/> |
| 42 | <field name='bathyNodes' type='MFNode' accessType='outputOnly'/> |
| 43 | <field name='traceEnabled' type='SFBool' accessType='initializeOnly'/> |
| 44 | <field name='coordinate' type='SFVec3f' value='0 0 0' accessType='initializeOnly'/> |
| 45 | <field name='previousPosition' type='SFVec3f' value='0 0 0' accessType='initializeOnly'/> |
| 46 | <field name='position' type='SFVec3f' value='0 0 0' accessType='initializeOnly'/> |
| 47 | <field name='bathyNodeIndex' type='SFInt32' value='0' accessType='initializeOnly'/> |
| 48 | <IS> |
| 49 | <connect nodeField='positionArray' protoField='positionArray'/> |
| 50 | <connect nodeField='timeArray' protoField='timeArray'/> |
| 51 | <connect nodeField='colorSchemeDepthRangeArray' protoField='colorSchemeDepthRangeArray'/> |
| 52 | <connect nodeField='colorSchemeColorArray' protoField='colorSchemeColorArray'/> |
| 53 | <connect nodeField='beamWidth' protoField='beamWidth'/> |
| 54 | <connect nodeField='transparency' protoField='surfaceTransparency'/> |
| 55 | <connect nodeField='traceEnabled' protoField='traceEnabled'/> |
| 56 | </IS> |
<![CDATA[
ecmascript:
function initialize()
{
bathyNodeIndex = 0;
spineIndex = 0;
position = positionArray[0];
spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
spineIndex++;
previousPosition = new SFVec3f(position.x, position.y, position.z);
//Determine the initial depth range
for (j = 0; j < colorSchemeDepthRangeArray.length; j++)
{
if (position.y >= colorSchemeDepthRangeArray[j].y)
break;
}
currentDepthRangeIndex = j;
for (i = 1; i < positionArray.length; i++)
{
if (previousPosition.y == colorSchemeDepthRangeArray[currentDepthRangeIndex].y &&
positionArray[i].y != colorSchemeDepthRangeArray[currentDepthRangeIndex].y)
terminateExtrusionSegmentWithCurrentPosition(currentDepthRangeIndex);
//Update new position
position = positionArray[i];
//Determine the correct depth range
if (position.y <= previousPosition.y)
{
for (j = currentDepthRangeIndex; j < colorSchemeDepthRangeArray.length; j++)
{
if (position.y >= colorSchemeDepthRangeArray[j].y)
break;
if (previousPosition.y != colorSchemeDepthRangeArray[currentDepthRangeIndex].y)
terminateExtrusionSegmentWithDepthRangeBoundary(currentDepthRangeIndex);
}
currentDepthRangeIndex = j;
}
else
{
for (j = currentDepthRangeIndex; j > -1; j--)
{
if (position.y < colorSchemeDepthRangeArray[j-1].y)
break;
if (position.y > colorSchemeDepthRangeArray[j-1].y)
terminateExtrusionSegmentWithDepthRangeBoundary(j-1);
}
currentDepthRangeIndex = j;
}
spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
spineIndex++;
previousPosition = new SFVec3f(position.x, position.y, position.z);
}
terminateExtrusionSegmentWithCurrentPosition(currentDepthRangeIndex);
}
function terminateExtrusionSegmentWithDepthRangeBoundary(index)
{
depthRange = colorSchemeDepthRangeArray[index];
findCoordinate(previousPosition.x, position.x, previousPosition.y, position.y, depthRange.y);
xPrime = coordinate;
findCoordinate(previousPosition.z, position.z, previousPosition.y, position.y, depthRange.y);
zPrime = coordinate;
spine[spineIndex] = new SFVec3f(xPrime, 0, zPrime);
scale[spineIndex] = new SFVec2f(1, Math.abs(depthRange.y));
if (scale[scale.length-2].y > scale[scale.length-1].y)
color = colorSchemeColorArray[index+1];
else
color = colorSchemeColorArray[index];
createExtrusionShape(spine, scale, color);
//Reset values to start the next extrustion segment
spineIndex = 0;
resetSpine();
resetScale();
//Update the current segment end as the start of the next segment
spine[spineIndex] = new SFVec3f(xPrime, 0, zPrime);
scale[spineIndex] = new SFVec2f(1, Math.abs(depthRange.y));
spineIndex++;
}
function terminateExtrusionSegmentWithCurrentPosition(index)
{
if (scale[scale.length-1].y != Math.abs(colorSchemeDepthRangeArray[index].y))
index--;
if (scale[scale.length-2].y > scale[scale.length-1].y)
color = colorSchemeColorArray[index+1];
else
color = colorSchemeColorArray[index];
createExtrusionShape(spine, scale, color);
//Reset values to start the next extrustion segment
spineIndex = 0;
resetSpine();
resetScale();
//Update the current segment end as the start of the next segment
spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
spineIndex++;
//Update the previousPosition
previousPosition = new SFVec3f(position.x, position.y, position.z);
}
function findCoordinate(x1, x2, y1, y2, yPrime)
{
coordinate = ((x1 - x2) / (y1 - y2)) * yPrime + ((x2*y1 - x1*y2) / (y1 - y2));
}
function createExtrusionShape(spine, scale, color)
{
determineOrientation(spine);
tracePrint('An extrusion is created whose spine is: ' + spine);
tracePrint('and scale is: ' + scale);
tracePrint('orientation is: ' + orientation);
tracePrint('color is: ' + color);
alwaysPrint('number of spine points is: ' + spine.length);
alwaysPrint('orientation is: ' + orientation);
//Build the VRML string
extrusionSyntax = 'Shape {\n';
extrusionSyntax += ' appearance Appearance {' + '\n';
extrusionSyntax += ' material Material {' + '\n';
extrusionSyntax += ' diffuseColor ' + color + '\n';
extrusionSyntax += ' transparency ' + transparency + '\n';
extrusionSyntax += ' }' + '\n';
extrusionSyntax += ' }' + '\n';
extrusionSyntax += ' geometry Extrusion {' + '\n';
extrusionSyntax += ' crossSection [' + (beamWidth/(-2)) + ', 1, ' + (beamWidth/2) + ', 1, ' + (beamWidth/(-2)) + ', 1]' + '\n';
extrusionSyntax += ' scale ' + scale + '\n';
extrusionSyntax += ' spine ' + spine + '\n';
extrusionSyntax += ' orientation ' + orientation + '\n';
extrusionSyntax += ' creaseAngle 1.57' + '\n';
extrusionSyntax += ' }' + '\n';
extrusionSyntax += '}';
//Create Extrusion shape
tracePrint (extrusionSyntax);
bathySegment = new SFNode(extrusionSyntax);
bathyNodes[bathyNodeIndex] = bathySegment;
bathyNodeIndex++;
}
function determineOrientation(spine)
{
previousZAxis = null;
orientation = new MFRotation();
//Special cases
if (spine.length == 2)
{
if (spine[0].z == spine[1].z)
{
if (spine[0].x <= spine[1].x) //positive x direction
orientation[0] = orientation[1] = new SFRotation(0, 1, 0, 1.57);
else //negative x direction
orientation[0] = orientation[1] = new SFRotation(0, 1, 0, -1.57);
}
else
{
if (spine[0].x == spine[1].x) //parallet to the z axis
orientation[0] = orientation[1] = new SFRotation(0, 1, 0, 0);
else
{
angleRadian = Math.atan((spine[0].x- spine[1].x) / (spine[0].z - spine[1].z));
// angleRadian = Math.atan2((spine[0].x- spine[1].x), (spine[0].z - spine[1].z));
orientation[0] = orientation[1] = new SFRotation(0, 1, 0, angleRadian);
}
}
return;
}
for (n = 0; n < spine.length; n++)
{
//If spine is not closed, the Z axis used for the first spine point is the same as the Z axis for spine[1].
//The Z axis used for the last spine point is the same as the Z axis for spine[spine.length - 2].
if (n == 0)
si = 1;
else if (n == (spine.length - 1))
si = spine.length - 2;
else
si = n;
zAxis = (spine[si+1].subtract(spine[si])).cross((spine[si-1].subtract(spine[si])));
while (zAxis.x == 0 && zAxis.y == 0 && zAxis.z == 0)
{
if (previousZAxis == null)
{
++si;
if (si == (spine.length - 1)) //The entire spine is collinear
{
zAxis = new SFVec3f(1, 0, 0);
break;
}
zAxis = (spine[si+1].subtract(spine[si])).cross((spine[si-1].subtract(spine[si])));
}
else
zAxis = new SFVec3f(previousZAxis.x, previousZAxis.y, previousZAxis.z);
}
adjustedZAxis = zAxis;
if (n == 0)
previousZAxis = zAxis;
else
{
dotProduct = zAxis.dot(previousZAxis);
if (dotProduct < 0)
adjustedZAxis = new SFVec3f(zAxis.multiply(-1).x, zAxis.multiply(-1).y, zAxis.multiply(-1).z);
previousZAxis = adjustedZAxis;
}
zAxisNormalized = adjustedZAxis.normalize();
theta = Math.acos(zAxisNormalized.dot(new SFVec3f(0, -1, 0)));
if (spine[1].x < spine[0].x)
orientation[n] = new SFRotation(0, -1, 0, theta);
else
orientation[n] = new SFRotation(0, 1, 0, theta);
}
if (theta == 0)
Browser.println ('rotation angle = ' + theta);
else if (theta > 1.57 && theta < 3.14)
Browser.println ('rotation angle = ' + theta);
else if (theta > 3.14)
Browser.println ('rotation angle = ' + theta);
}
function resetSpine()
{
spine = new MFVec3f();
}
function resetScale()
{
scale = new MFVec2f();
}
function tracePrint(string)
{
if (traceEnabled)
Browser.println ('[BathymetryGenerator] ' + string);
}
function alwaysPrint(string)
{
Browser.println ('[BathymetryGenerator] ' + string);
}
]]>
|
|
| 58 | </Script> |
| 59 | < ROUTE fromNode='BathymetryScript' fromField='bathyNodes' toNode='Bathymetry' toField='addChildren'/> |
| 60 | <Shape> |
| 61 | <Extrusion/> |
| 62 | </Shape> |
| 63 | </Group> |
| 64 | </ProtoBody> |
| 65 | </ProtoDeclare> |
| 66 | <Viewpoint description='MainView' position='0 -50 200'/> |
| 67 | <ProtoInstance name='BathymetryGenerator'> |
| 68 | <fieldValue name='positionArray' value='0 0 0 10 -4 0 25 -6 0 30 -8 5 38 -15 5 45 -18 5 55 -22 5 60 -25 15 60 -27 22 55 -30 35 48 -35 35 35 -35 35 25 -45 35 20 -55 35 15 -70 35 3 -70 35 -5 -72 40 -5 -75 50 0 -80 55 15 -75 55 30 -70 55 35 -60 55 40 -50 55 50 -34 55 65 -23 70'/> |
| 69 | <fieldValue name='surfaceTransparency' value='0.25'/> |
| 70 | <fieldValue name='traceEnabled' value='true'/> |
| 71 | </ProtoInstance> |
| 72 | </Scene> |
| 73 | </X3D> |
Event Graph ROUTE Table with 1 ROUTE connection 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.
|
BathymetryScript
Script bathyNodes MFNode |
Bathymetry
Transform addChildren MFNode |
| line 67
ProtoInstance BathymetryGenerator |
No direct ROUTE connection found for events to/from this node. This ProtoInstance contains SFNode/MFNode fieldValue declarations with direct access to other nodes, and thus has potential to produce run-time animation. |
<!--
Color-coding legend: X3D terminology
<X3dNode
DEF='idName' field='value'/>
matches XML terminology
<XmlElement
DEF='idName' attribute='value'/>
(Light-blue background: event-based behavior node or statement)
(Grey background inside box: inserted documentation)
(Magenta background: X3D Extensibility)
<ProtoInstance name='ProtoName'>
<field
name='fieldName'/> </ProtoInstance>
-->
<!--
For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints.
-->