#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 }