ShapeWaterTutorial, version = 0

Tube Water Tutorial

This tutorial will step through generating a spot using the TubeWater function.
You can cut and paste the 3DML code into a text editor. Also, all the tutorial spots are located in the directory labeled /TutorialSpots/.


The TubeWater function creates a tube of water whose center axis is parellel to the Z axis. The center of the initial radius is the block's (0,0,0) coordinate, and may be offset by the parameters Xoffset, Yoffset and Zstart. The tube extends along the positive Z axis. The length of the tube is specified by the difference between the parameters Zend and Zstart. Tube_Length = Zend - Zstart. The parameters Rinit and Rfinal specify the initial and final radii. The parameter Nvertices tells the function the number of vertices on one side of a water.bset or ShapeWater.bset block. The parameters Xoffset, Yoffset, Zstart, Zend, Rinit, Rfinal are specified in pixels.
Refer to Figure 1 and 2.

Note: Use the TubeNxN.block from the ShapeWater blockset in the CREATE tag for any block being modified by the TubeWater( ) function. The TubeNxN.block's have extra polygons to fill the interior of the tube to help prevent Rover from rendering missing surfaces when the block is viewed from certain directions.

The RIPPLE tag propagates Waves from the Initial radius end to the Final radius end.

Function Prototype:
TubeWater( blockReference, Nvertices, Xoffset, Yoffset, Zstart, Zend, Rinit, Rfinal )

Scale Factor: Figure 1. Tube Water 3D
Scale Factor: Figure 2. Tube Water 2D

TubeWaterSpot1.3dml

Create a spot that places a tube of water at the (0,100,0) coordinates of a block. The initial radius will be 50 pixels and the final radius will be 50 pixels. The length should be 200 pixels. The tube will be made with the Tube15x15 block from from the ShapeWater blockset.
<spot>
<head>
   <title name="Tube Water Spot 1"/>
   <blockset href="http://blocksets.flatland.com/flatsets/basic.bset"/>

   <!-- get the ShapeWater Blockset -->
   <blockset href="http://www.mikejost.com/3dml/Blocksets/ShapeWater/ShapeWater.bset"/>

   <debug/>
   <map style="double" dimensions="(5,5,1)" /> 
   <sky brightness="90%"/>
   <ambient_light brightness="100%"/>
   <ground texture="@basic:cement.gif"/>

</head>
<body>

<!--   Import ShapeWater Functions   -->
<import href="http://www.mikejost.com/3dml/Blocksets/ShapeWater/ShapeWater.3dml"/>

<entrance name="default" location="(4,2,1)" angle="270,0" />

<!--  Create the Tube water block -->
<create symbol="tw" block="Tube15x15">
   <param movable="yes" origin="(0.0, 0.0, 0.0)"/> <!-- make block Movable and set origin to lower south-west corner -->
   <part name="water" texture="@ShapeWater:bluewater.jpg" style="tiled" translucency="60%" faces="2"/>
   <part name="interior" texture="@ShapeWater:bluewater.jpg" style="tiled" translucency="90%" faces="2"/>
   <action trigger="start">
      <ripple style="waves" force="4.0" droprate="60%" damp="94%"/>
   </action>
</create>

<define>

   <!-- Start Function -->
   <function name="start">
      // Initialize the vertices of the water block for an initial radius of 50
      // and a final radius of 50 with center at (0,100,0), and a length of 200.    
      waterBlock = map.get_block("tw");
      // TubeWater( block, Nvertices, Xoffset, Yoffset, Zstart, Zend, Rinit, Rfinal )
      TubeWater( waterBlock, 15, 0, 100, 0, 200, 50.0, 50.0);
   </function>

</define>

<!--
 1  2  3  4  5  -->
<level number="1">
.. .. .. .. ..  <!--  1 -->
.. .. tw .. ..  <!--  2 -->
.. .. .. .. ..  <!--  3 -->
.. .. .. .. ..  <!--  4 -->
.. .. .. .. ..  <!--  5 -->
</level>


</body>
</spot>


The spot should look like Figure 1 with both the initial and final radii the same. The wave should propagate from the left (Rinner) to the right (Router).

Make the final radius very small to create a Cone of Water.

Change Rfinal to 1.0 in the TubeWater( ) function. Also rotate the block around the X axis by -90 degrees to put the base of the cone on the ground.
The changed start code would be:

   TubeWater( waterBlock, 15, 0, 100, 0, 200, 50.0, 1.0 );
   waterBlock.rotate_x(-90);

The modified spot should look like Figure 3.

Figure 3

Use the Circle15x15 block instead of the Tube15x15 block.

Change the CREATE tag to use the Circle15x15 block.
The changed CREATE code's 1st line would be:

   <create symbol="tw" block="Circle15x15">

The modified spot should look like Figure 4.

Not very pretty. The CircleNxN blocks have no extra polygons like the TubeNxN and ElbowNxN blocks to help fill in the interior of the tubes and elbows. Rover doesn't render surfaces that are tilted away from the current viewpoint. Note, this occurs where the tubes surfaces are joined at the vertices, creating annoying imaginary circles of missing surfaces.

Figure 4

Experimentation:

  • Try using the "RAINDROPS" effect of the RIPPLE tag.
  • Try changing the translucency of the "water" and "interior" parts of the TubeNxN.block.
  • Try making Rinit positive and Rfinal negative.


    Notes:

  • The origin of the block is the center of rotations.
  • The TubeWater() center coordinates are absolute block coordinates and are not based on the origin of the block.


    TubeFireSpot2.3dml

    Create a spot that simulates a torch fire. The inner flame will be made from 3 tube blocks placed in a triangular pattern on the ground. The outer flame will be a tube block with a diameter which surrounds the 3 inner tube blocks. The tubes will be made with the Tube15x15 block from the ShapeWater blockset.

    
    <spot>
    <head>
       <title name="Tube Fire Spot 2"/>
       <blockset href="http://blocksets.flatland.com/flatsets/basic.bset"/>
    
       <!-- get the ShapeWater Blockset -->
       <blockset href="http://www.mikejost.com/3dml/Blocksets/ShapeWater/ShapeWater.bset"/>
    
       <debug/>
       <map style="double" dimensions="(5,5,1)" /> 
       <sky brightness="90%"/>
       <ambient_light brightness="100%"/>
       <ground texture="@basic:cement.gif"/>
    
    </head>
    <body>
    
    <!--   Import ShapeWater Functions   -->
    <import href="http://www.mikejost.com/3dml/Blocksets/ShapeWater/ShapeWater.3dml"/>
    
    <entrance name="default" location="(3,4,1)" angle="0,0" />
    
    <!--  Inner Fire Tubes  -->
    <create symbol="f0" block="Tube15x15">
    <param movable="yes" origin="(0.0,0.0,0.0)"/>
    <part name="*" texture="@ShapeWater:torchfireyellowred.jpg" style="scaled" translucency="50%" faces="2"/>
    <action trigger="start">
       <ripple style="waves" force="9.0" droprate="60%" damp="97%"/>
    </action>
    </create>
    
    <create symbol="f1" block="Tube15x15">
    <param movable="yes" origin="(0.0,0.0,0.0)"/>
    <part name="*" texture="@ShapeWater:torchfireyellowred.jpg" style="scaled" translucency="50%" faces="2"/>
    <action trigger="start">
       <ripple style="waves" force="9.0" droprate="60%" damp="97%"/>
    </action>
    </create>
    
    <create symbol="f2" block="Tube15x15">
    <param movable="yes" origin="(0.0,0.0,0.0)"/>
    <part name="*" texture="@ShapeWater:torchfireyellowred.jpg" style="scaled" translucency="50%" faces="2"/>
    <action trigger="start">
       <ripple style="waves" force="9.0" droprate="60%" damp="97%"/>
    </action>
    </create>
    
    <!--  Outer Fire Tube  -->
    <create symbol="f3" block="Tube15x15">
    <param movable="yes" origin="(0.0,0.0,0.0)"/>
    <part name="*" texture="@ShapeWater:torchfireredbrown.jpg" style="scaled" translucency="50%" faces="2"/>
    <part name="interior" texture="@ShapeWater:torchfireyellowred.jpg" style="scaled" translucency="60%" faces="2"/>
    <action trigger="start">
       <ripple style="waves" force="9.0" droprate="60%" damp="98%"/>
    </action>
    </create>
    
    <!-- Floor block -->
    <create symbol="bb" block="floor">
    <part name="*" texture="@basic:cement.gif" />
    </create>
    
    <define>
    
       <!-- Start Function -->
       <function name="start">
    
          // Initialize the inner Fire tube block's
          map.set_block(1,1,1,"f0"); // put inner fire tube f0 on the map     
          fireBlock = map.get_block("f0");
          // TubeWater( block, Nvertices, Xoffset, Yoffset, Zstart, Zend, Rinit, Rfinal )
          TubeWater( fireBlock, 15, 0, 0, 0, 50, 14.0, 2.0); // Height=50, Rinner=14, Router=2     
          fireBlock.rotate_x(-90);
          TranslateBlockAbsolute(fireBlock, (2*256)+128+8, 256+30, (2*256)+128+8); // move to center of (3,3,1) and offset by X=+8, Z=+8     
    
          map.set_block(1,1,1,"f1"); // put inner fire tube f1 on the map     
          fireBlock = map.get_block("f1");
          TubeWater( fireBlock, 15, 0, 0, 0, 50, 14.0, 2.0); // Height=50, Rinner=14, Router=2     
          fireBlock.rotate_x(-90);
          TranslateBlockAbsolute(fireBlock, (2*256)+128-8, 256+30, (2*256)+128+8); // move to center of (3,3,1) and offset by X=-8, Z=+8     
    
          map.set_block(1,1,1,"f2"); // put inner fire tube f2 on the map     
          fireBlock = map.get_block("f2");
          TubeWater( fireBlock, 15, 0, 0, 0, 50, 14.0, 2.0); // Height=50, Rinner=14, Router=2     
          fireBlock.rotate_x(-90);
          TranslateBlockAbsolute(fireBlock, (2*256)+128, 256+30, (2*256)+128-8); // move to center of (3,3,1) and offset by X=0, Z=-8     
    
          // Initialize the Outer Fire tube block
          map.set_block(1,1,1,"f3");  // put outer fire tube f3 on the map     
          fireBlock = map.get_block("f3");
          TubeWater( fireBlock, 15, 0, 0, 0, 20, 27.0, 16.0); // Height=20, Rinner=27, Router=16     
          fireBlock.rotate_x(-90);
          TranslateBlockAbsolute(fireBlock, (2*256)+128, 256+30, (2*256)+128);  // move to center of (3,3,1)     
     
    
       </function>
    
    </define>
    
    <!--
     1  2  3  4  5  -->
    <level number="1">
    .. .. .. .. ..  <!--  1 -->
    .. .. .. .. ..  <!--  2 -->
    .. .. bb .. ..  <!--  3 -->
    .. .. .. .. ..  <!--  4 -->
    .. .. .. .. ..  <!--  5 -->
    </level>
    
    </body>
    </spot>
    


    End of TubeWater Tutorial

    Go to the ElbowWater Tutorial Next.