<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:#000000;"><div>Hello everybody,<br><br>I need to render a volume (of scalar values)  that have some regions fully transparent. To avoid the problem that arise from trilinear interpolation of the scalars (that show wrong boundary scalars), I have to use the software volume rendering mapper (vtkVolumeRayCastMapper) where you can customize the composite function. In more details, you can invoke the very useful method <span style="font-weight: bold;">SetCompositeMethodToClassifyFirst</span>() of the vtkVolumeRayCastCompositeFunction to obtain the correct result. Unfortunately the software version is slow compared to the hardware one (vtkOpenGLGPUVolumeRayCastMapper). So I have extended the hardware version, rewriting a GLSL shader (starting from vtkGPUVolumeRayCastMapper_CompositeFS.glsl) in order to
 emulate the behaviour of the vtkVolumeRayCastMapper when you invoke the SetCompositeMethodToClassifyFirst() method. The shader is the following (vtkGPUVolumeRayCastMapper_CompositeFS2.glsl) and you have to add it to the vtkOpenGLGPUVolumeRayCastMapper class:<br><font size="2"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">/*=========================================================================</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  Program:   Visualization Toolkit</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;"> 
 Module:    vtkGPUVolumeRayCastMapper_CompositeFS2.glsl</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  All rights reserved.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span>  See Copyright.txt or <a target="_blank" href="http://www.kitware.com/Copyright.htm">http://www.kitware.com/Copyright.htm</a> for details.</span></span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family:
 Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">     This software is distributed WITHOUT ANY WARRANTY; without even</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">     PURPOSE.  See the above copyright notice for more information.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">=========================================================================*/</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">// Fragment program part with ray cast and composite method.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">#version 110</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform sampler3D dataSetTexture;</span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform sampler1D opacityTexture;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform vec3 lowBounds;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform vec3 highBounds;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureWidth;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureHeight;</span><br
 style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureDepth;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">// Entry position (global scope)</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">vec3 pos;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">// Incremental vector in texture space (global scope)</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">vec3 rayDir;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">float tMax;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">// from cropping vs no cropping</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">vec4 initialColor();</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">// from 1 vs 4 component shader.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">float scalarFromValue(vec4 value);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">vec4 colorFromValue(vec4 value);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">// from noshade vs shade.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">void initShade();</span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">vec4 shade(vec4 value);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">void trace(void)</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">{</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  vec4 destColor=initialColor();</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  float remainOpacity=1.0-destColor.a;</span><br
 style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  bool inside=true;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  </span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  vec3 color;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  vec4 opacity;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">  initShade();</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  </span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  float t=0.0;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  </span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  // We NEED two nested while loops. It is trick to work around hardware</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  //
 limitation about the maximum number of loops.</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  vec3 textureSize = vec3(textureWidth, textureHeight, textureDepth);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  vec3 texelSize = vec3(1.0, 1.0, 1.0) / textureSize;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  while(inside)</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">    {  </span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">    while(inside)</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      {<br></span><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      vec3 texelpos=textureSize*pos;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      vec3 lerps = fract(texelpos);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      vec4 sourcevals[8]; </span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[0] = texture3D(dataSetTexture, pos + vec3(0,           0,           0));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[1] = texture3D(dataSetTexture, pos + vec3(texelSize.x, 0,           0));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[2] = texture3D(dataSetTexture, pos + vec3(0,          
 texelSize.y, 0));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[3] = texture3D(dataSetTexture, pos + vec3(texelSize.x, texelSize.y, 0));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[4] = texture3D(dataSetTexture, pos + vec3(0,           0,           texelSize.z));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[5] = texture3D(dataSetTexture, pos + vec3(texelSize.x,
 0,           texelSize.z));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[6] = texture3D(dataSetTexture, pos + vec3(0,           texelSize.y, texelSize.z));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      sourcevals[7] = texture3D(dataSetTexture, pos + vec3(texelSize.x, texelSize.y, texelSize.z));</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      vec3 m = vec3(1, 1, 1) - lerps;</span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      float weights[8];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[0] = m.x * m.y * m.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[1] = lerps.x * m.y * m.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[2] = m.x * lerps.y * m.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">      weights[3] = lerps.x * lerps.y * m.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[4] = m.x * m.y * lerps.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[5] = lerps.x * m.y * lerps.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      weights[6] = m.x * lerps.y * lerps.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">      weights[7] = lerps.x * lerps.y * lerps.z;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      float weight, totalOpacity;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity  = weight = texture1D(opacityTexture,scalarFromValue(sourcevals[0])).a*weights[0];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color  = shade(sourcevals[0]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[1])).a*weights[1];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[1]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[2])).a*weights[2];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[2]).xyz*weight;</span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[3])).a*weights[3];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[3]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[4])).a*weights[4];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color +=
 shade(sourcevals[4]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[5])).a*weights[5];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[5]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[6])).a*weights[6];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[6]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[7])).a*weights[7];</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      color += shade(sourcevals[7]).xyz*weight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      destColor.xyz += remainOpacity*color;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">      remainOpacity *= (1.0 - totalOpacity);</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      pos=pos+rayDir;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      t+=1.0;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      inside=t<tMax && all(greaterThanEqual(pos,lowBounds))</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">       
 && all(lessThanEqual(pos,highBounds))</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">        && (remainOpacity>=0.0039); // 1/255=0.0039</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">      }</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">    }</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">  gl_FragColor = destColor;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family:
 Courier New,courier,monaco,monospace,sans-serif;">  gl_FragColor.a = 1.0-remainOpacity;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">}</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">;</span></font><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;">The algorithm performs trilinear interpolation manually so you have to call <span style="font-weight: bold;">SetInterpolationTypeToNearest()</span> when you use this shader. In addition you have 3 new uniform variables:<br><br><font size="2"><span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureWidth;</span><br style="font-family: Courier
 New,courier,monaco,monospace,sans-serif;">
  <span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureHeight;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;">
  <span style="font-family: Courier New,courier,monaco,monospace,sans-serif;">uniform int textureDepth;</span><br style="font-family: Courier New,courier,monaco,monospace,sans-serif;"><br></font>that maintains the dimensions of the 3D texture. You have to modify the class vtkOpenGLGPUVolumeRayCastMapper to provide these additional informations to the shader.<br><br>I hope that this could be helpful for other guys and that (one day) this feature will be added to the VTK library :)<font size="2"><br><br></font>Bye,<br><br>Gianluca Arcidiacono (AGPX)<font size="2"><br></font><br><br></div>
</div><br>



      </body></html>