#VRML V2.0 utf8

PROTO SuperEllipsoid
#
# works at least with SGI Cosmo Player 2.1.5, cc3dglut 4.3
#
# A VRML Proto to account the data of a SuperEllipsoid shape with scripting
# (slow)
# Copyright (C) 2003 J. "MUFTI" Scheurich
#
# exampe use
#
# EXTERNPROTO SuperEllipsoid
#   [
#   exposedField SFFloat n1 
#   exposedField SFFloat n2 
#   exposedField SFFloat border
#   field SFFloat creaseAngle
#   exposedField SFNode texCoord
#   exposedField SFInt32 uTessellation 
#   exposedField SFInt32 vTessellation 
#   ]
# [
# "SuperEllipsoidPROTO.wrl"
# ]
# Shape 
#   {
#   appearance Appearance 
#      {
#      material Material 
#	  {
#	  }
#      }
#   geometry SuperEllipsoid 
#     {
#     }
#   }
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program (see the file "COPYING" for details); if 
# not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
# Cambridge, MA 02139, USA.
#
   [
   exposedField SFFloat n1 1
   exposedField SFFloat n2 1
   exposedField SFFloat border 1.57079632679489661923
   field SFFloat creaseAngle 0.78539816339744830962
   exposedField SFNode texCoord NULL
   exposedField SFInt32 uTessellation 0
   exposedField SFInt32 vTessellation 0
   ]
{
    DEF IndexedFaceSet1 IndexedFaceSet 
      {
      coord 	DEF Coordinate1 Coordinate 
        {
        }
      creaseAngle IS creaseAngle
      texCoord IS texCoord
      }
    
    Switch 
      {
      choice 
        [
        Shape 
          {
          appearance       Appearance 
            {
            textureTransform DEF N1_CONTAINER TextureTransform 
              {
              rotation IS n1
              }
            }
          }
        ]
      }
    
    Switch 
      {
      choice 
        [
        Shape 
          {
          appearance       Appearance 
            {
            textureTransform DEF N2_CONTAINER  TextureTransform 
              {
              rotation IS n2
              }
            }
          }
        ]
      }

    Switch 
      {
      choice 
        [
        Shape 
          {
          appearance       Appearance 
            {
            textureTransform DEF BORDER_CONTAINER TextureTransform 
              {
              rotation IS border
              }
            }
          }
        ]
      }
    
    DEF UTESSELLATION_CONTAINER Switch 
      {
      whichChoice IS uTessellation
      }
    
    DEF VTESSELLATION_CONTAINER Switch 
      {
      whichChoice IS vTessellation
      }
    
    DEF Script1 Script 
      {
      eventOut MFInt32 coordindex_out
      eventOut MFVec3f vertices_out
      eventIn SFFloat n1_in 
      field SFFloat n1 1
      eventIn SFFloat n2_in 
      field SFFloat n2 1
      eventIn SFInt32 uTessellation_in 
      field SFInt32 uTessellation 0
      eventIn SFInt32 vTessellation_in 
      field SFInt32 vTessellation 0
      field SFFloat border 1.57079632679489661923
      eventIn SFFloat border_in
      field MFFloat s1xy []
      field MFFloat s1z []
      field MFFloat s2x []
      field MFFloat s2y []
      field MFInt32 ci []
      field MFVec3f vert []
      field SFNode n1Container USE N1_CONTAINER
      field SFNode n2Container USE N2_CONTAINER
      field SFNode uTessContainer USE UTESSELLATION_CONTAINER
      field SFNode vTessContainer USE VTESSELLATION_CONTAINER
      field SFFloat EPSILON 1e-6
      url 
        [
        "javascript:
    
     // field SFInt32 uTessellation //
     // field SFInt32 vTessellation //
    
     // field SFFloat n1 //
     // field SFFloat n2 //
    
     // eventOut MFInt32 coordindex_out //
     // eventOut MFVec3f vertices_out //
    

     function cossign(f)
        {
        // range -PI to PI
        if ((f < Math.PI/2.0 + EPSILON) && (f > Math.PI/2.0 - EPSILON))
            return 0;
        if (f > Math.PI/2.0)
            return -1;
        if ((f < -Math.PI/2.0 + EPSILON) && (f > -Math.PI/2.0 - EPSILON))
            return 0;
        if (f > -Math.PI/2.0)
            return 1;
        // -PI < x < -PI/2
        return -1;
        }

     function sinsign(f)
        {
        // range -PI to PI
        if ((f < Math.PI + EPSILON) && (f > Math.PI - EPSILON))
            return 0;
        if (f > Math.PI)
            return -1;
        if ((f < 0 + EPSILON) && (f > 0 - EPSILON))
            return 0;
        if (f > 0)
            return 1;
        if ((f < -Math.PI + EPSILON) && (f > -Math.PI - EPSILON))
            return 0;
        if (f < -Math.PI)
            return 1;
        // -PI < x < 0
        return -1;
        }
    
     function superellipse1xy(angle1)
        {
        var c1 = Math.cos(angle1);
        return cossign(angle1)*Math.pow(Math.abs(c1),n2);
        }
    
     function superellipse1z(angle1)
        {
        var s1 = Math.sin(angle1);
        return sinsign(angle1)*Math.pow(Math.abs(s1),n2);
        }
    
     function superellipse2x(angle2)
        {
        var c2 = Math.cos(angle2);
        var n = n1;
        if (Math.abs(n) < 1e-5)
            n = 1e-5;
        return cossign(angle2)*Math.pow(Math.abs(c2),n);
        }
    
     function superellipse2y(angle2)
        {
        var s2 = Math.sin(angle2);
        var n = n1;
        if (Math.abs(n) < 1e-5)
            n = 1e-5;
        return sinsign(angle2)*Math.pow(Math.abs(s2),n);
        }
    
     function account()
        {
        var uTess=(uTessellation==0)?33:uTessellation+1;
        var vTess=(vTessellation==0)?33:vTessellation+1;
        var inc1=(border+Math.PI/2.0)/(vTess-1);
        var inc2=Math.PI/(vTess-1)*2.0;
        ci=new MFInt32();
        vert=new MFVec3f();
        var index=0;
        var cindex=0;
        var angle1=-Math.PI/2.0;
        var angle2=-Math.PI;
        var i;
        var a1=0;
        var a2=0;
        for (a1=0;a1<uTess;a1++)
           {
           s1xy[a1]=superellipse1xy(angle1);
           s1z[a1]=superellipse1z(angle1);
           angle1+=inc1;
           }
        for (a2=0;a2<vTess;a2++)
           {
           s2x[a2]=superellipse2x(angle2);
           s2y[a2]=superellipse2y(angle2);
           angle2+=inc2;
           }
        for (a1=0;a1<uTess;a1++)
           for (a2=0;a2<vTess;a2++)
              {
              vert[index].z = s1xy[a1]*s2x[a2];
              vert[index].x = s1xy[a1]*s2y[a2];
              vert[index].y = s1z[a1];
              index++;
              }
        for (a1=0;a1<uTess;a1++)
           for (a2=0;a2<vTess;a2++)
              {
              var c1=a1+1;
              if (a1==uTess-1)
                 continue;
              var c2=a2+1;
              if (a2==vTess-1)
                 continue;
              ci[cindex++]=a1*vTess+a2;
              ci[cindex++]=a1*vTess+c2;
              ci[cindex++]=c1*vTess+c2;
              ci[cindex++]=c1*vTess+a2;
              ci[cindex++]=-1;
              }
        vertices_out=vert;
        coordindex_out=ci;
        }
    
     function initialize()
        {
        n1=n1Container.rotation;
        n2=n2Container.rotation;
        uTessellation=uTessContainer.whichChoice;
        vTessellation=vTessContainer.whichChoice;
        account();
        }
    
     function n1_in(value)
        {
        n1 = value;
        account();
        }
    
     function n2_in(value)
        {
        n2 = value;
        account();
        }
    
     function border_in(value)
        {
        border = value;
        account();
        }

     function uTessellation_in(value)
        {
        uTessellation = value;
        account();
        }
    
     function vTessellation_in(value)
        {
        vTessellation = value;
        account();
        }
    "
        ]
      }

ROUTE N1_CONTAINER.rotation TO Script1.n1_in
ROUTE N2_CONTAINER.rotation TO Script1.n2_in
    
ROUTE UTESSELLATION_CONTAINER.whichChoice TO Script1.uTessellation_in
ROUTE VTESSELLATION_CONTAINER.whichChoice TO Script1.vTessellation_in
    
ROUTE Script1.vertices_out TO Coordinate1.set_point
ROUTE Script1.coordindex_out TO IndexedFaceSet1.set_coordIndex
}
    
    
  
