Add source.

This commit is contained in:
kovacsv 2014-10-11 13:53:39 +02:00
parent 0bbef59f40
commit 887fd0e703
26 changed files with 2503 additions and 0 deletions

522
src/frameworks/jsmodeler.js Normal file
View File

@ -0,0 +1,522 @@
/* JSModeler 0.32.177 - http://www.github.com/kovacsv/JSModeler */ 'use strict';var JSM={mainVersion:0,subVersion:32,Eps:1E-8,Inf:9999999999,RadDeg:57.29577951308232,DegRad:0.017453292519943,IsZero:function(a){return Math.abs(a)<JSM.Eps},IsPositive:function(a){return a>JSM.Eps},IsNegative:function(a){return a<-JSM.Eps},IsLower:function(a,b){return b-a>JSM.Eps},IsGreater:function(a,b){return a-b>JSM.Eps},IsEqual:function(a,b){return Math.abs(b-a)<JSM.Eps},IsEqualWithEps:function(a,b,c){return Math.abs(b-a)<c},IsLowerOrEqual:function(a,b){return JSM.IsLower(a,b)||
JSM.IsEqual(a,b)},IsGreaterOrEqual:function(a,b){return JSM.IsGreater(a,b)||JSM.IsEqual(a,b)},Minimum:function(a,b){return JSM.IsLower(a,b)?a:b},Maximum:function(a,b){return JSM.IsGreater(a,b)?a:b},ArcSin:function(a){return JSM.IsGreaterOrEqual(a,1)?Math.PI/2:JSM.IsLowerOrEqual(a,-1)?-Math.PI/2:Math.asin(a)},ArcCos:function(a){return JSM.IsGreaterOrEqual(a,1)?0:JSM.IsLowerOrEqual(a,-1)?Math.PI:Math.acos(a)},RandomNumber:function(a,b){return Math.random()*(b-a)+a},RandomInt:function(a,b){return Math.floor(Math.random()*
(b-a+1)+a)},SeededRandomInt:function(a,b,c){return Math.floor((9301*c+49297)%233280/233280*(b-a+1)+a)},ValueOrDefault:function(a,b){return void 0===a||null===a?b:a},Assert:function(a,b){if(!a){var c="Assertion failed.";void 0!==b&&null!==b&&(c+=" "+b);alert(c)}},Timer:function(){this.stop=this.start=0}};JSM.Timer.prototype.Start=function(){this.start=(new Date).getTime()};JSM.Timer.prototype.Stop=function(){this.end=(new Date).getTime()};JSM.Timer.prototype.Result=function(){return this.end-this.start};
JSM.FPSCounter=function(){this.current=this.frames=this.start=null};JSM.FPSCounter.prototype.Get=function(a){var b=(new Date).getTime();null===this.start&&(this.start=b,this.current=this.frames=0);if(null===a||void 0===a)a=1E3;this.frames+=1;var c=b-this.start;c>=a&&(this.current=1E3*(this.frames/c),this.start=b,this.frames=0);return parseInt(this.current,10)};
JSM.BubbleSort=function(a,b){if(!(2>a.length||void 0===b||null===b)){var c,d;for(c=0;c<a.length-1;c++)for(d=0;d<a.length-c-1;d++)if(!b(a[d],a[d+1])){var e=a,f=d+1,g=e[d];e[d]=e[f];e[f]=g}}};JSM.AsyncEnvironment=function(a){this.parameters=a};JSM.AsyncEnvironment.prototype.OnStart=function(a,b){if(void 0!==this.parameters&&void 0!==this.parameters.onStart)this.parameters.onStart(a,b)};
JSM.AsyncEnvironment.prototype.OnProcess=function(a,b){if(void 0!==this.parameters&&void 0!==this.parameters.onProcess)this.parameters.onProcess(a,b)};JSM.AsyncEnvironment.prototype.OnFinish=function(a){if(void 0!==this.parameters&&void 0!==this.parameters.onFinish)this.parameters.onFinish(a)};
JSM.AsyncRunTask=function(a,b,c,d,e){function f(g){var h=a();b.OnProcess(g,e);h&&g<c-1?setTimeout(function(){f(g+1)},d):setTimeout(function(){b.OnFinish(e)},d)}if(void 0===b||null===b){var g,h;for(g=0;g<c&&!(h=a(),!h);g++);}else b.OnStart(c,e),f(0)};JSM.Coord2D=function(a,b){this.x=a;this.y=b};JSM.Coord2D.prototype.Set=function(a,b){this.x=a;this.y=b};JSM.Coord2D.prototype.ToString=function(){return"("+this.x+", "+this.y+")"};JSM.Coord2D.prototype.Clone=function(){return new JSM.Coord2D(this.x,this.y)};
JSM.PolarCoord=function(a,b){this.radius=a;this.angle=b};JSM.PolarCoord.prototype.Set=function(a,b){this.radius=a;this.angle=b};JSM.PolarCoord.prototype.ToString=function(){return"("+this.radius+", "+this.angle+")"};JSM.PolarCoord.prototype.Clone=function(){return new JSM.PolarCoord(this.radius,this.angle)};JSM.Coord=function(a,b,c){this.x=a;this.y=b;this.z=c};JSM.Coord.prototype.Set=function(a,b,c){this.x=a;this.y=b;this.z=c};
JSM.Coord.prototype.ToString=function(){return"("+this.x+", "+this.y+", "+this.z+")"};JSM.Coord.prototype.Clone=function(){return new JSM.Coord(this.x,this.y,this.z)};JSM.SphericalCoord=function(a,b,c){this.radius=a;this.theta=b;this.phi=c};JSM.SphericalCoord.prototype.Set=function(a,b,c){this.radius=a;this.theta=b;this.phi=c};JSM.SphericalCoord.prototype.ToString=function(){return"("+this.radius+", "+this.theta+", "+this.phi+")"};
JSM.SphericalCoord.prototype.Clone=function(){return new JSM.SphericalCoord(this.radius,this.theta,this.phi)};JSM.Vector2D=JSM.Coord2D;JSM.Vector=JSM.Coord;JSM.MatrixDeterminant2x2=function(a,b,c,d){return a*d-b*c};JSM.MatrixDeterminant3x3=function(a,b,c,d,e,f,g,h,l){var k=JSM.MatrixDeterminant2x2(e,f,h,l);f=JSM.MatrixDeterminant2x2(d,f,g,l);d=JSM.MatrixDeterminant2x2(d,e,g,h);return a*k-b*f+c*d};
JSM.MatrixDeterminant4x4=function(a,b,c,d,e,f,g,h,l,k,m,n,p,q,r,s){var x=JSM.MatrixDeterminant3x3(f,g,h,k,m,n,q,r,s),v=JSM.MatrixDeterminant3x3(e,g,h,l,m,n,p,r,s);h=JSM.MatrixDeterminant3x3(e,f,h,l,k,n,p,q,s);e=JSM.MatrixDeterminant3x3(e,f,g,l,k,m,p,q,r);return x*a-v*b+h*c-e*d};JSM.CoordFromArray2D=function(a){return new JSM.Coord2D(a[0],a[1])};JSM.CoordFromArray=function(a){return new JSM.Coord(a[0],a[1],a[2])};JSM.CoordIsEqual2D=function(a,b){return JSM.IsEqual(a.x,b.x)&&JSM.IsEqual(a.y,b.y)};
JSM.CoordIsEqual2DWithEps=function(a,b,c){return JSM.IsEqualWithEps(a.x,b.x,c)&&JSM.IsEqualWithEps(a.y,b.y,c)};JSM.CoordDistance2D=function(a,b){var c=a.x,d=a.y,e=b.x,f=b.y;return Math.sqrt((e-c)*(e-c)+(f-d)*(f-d))};JSM.MidCoord2D=function(a,b){return new JSM.Coord2D((a.x+b.x)/2,(a.y+b.y)/2)};JSM.PolarToCartesian=function(a,b){var c=new JSM.Coord2D(0,0);c.x=a*Math.cos(b);c.y=a*Math.sin(b);return c};JSM.GetArcLengthFromAngle=function(a,b){return b*a};
JSM.GetAngleFromArcLength=function(a,b){return JSM.IsEqual(a,0)?0:b/a};JSM.CoordTurnType2D=function(a,b,c){a=JSM.MatrixDeterminant3x3(a.x,a.y,1,b.x,b.y,1,c.x,c.y,1);return JSM.IsPositive(a)?"CounterClockwise":JSM.IsNegative(a)?"Clockwise":"Collinear"};JSM.CoordIsEqual=function(a,b){return JSM.IsEqual(a.x,b.x)&&JSM.IsEqual(a.y,b.y)&&JSM.IsEqual(a.z,b.z)};JSM.CoordIsEqualWithEps=function(a,b,c){return JSM.IsEqualWithEps(a.x,b.x,c)&&JSM.IsEqualWithEps(a.y,b.y,c)&&JSM.IsEqualWithEps(a.z,b.z,c)};
JSM.SphericalCoordIsEqual=function(a,b){return JSM.IsEqual(a.radius,b.radius)&&JSM.IsEqual(a.phi,b.phi)&&JSM.IsEqual(a.theta,b.theta)};JSM.CoordDistance=function(a,b){var c=a.x,d=a.y,e=a.z,f=b.x,g=b.y,h=b.z;return Math.sqrt((f-c)*(f-c)+(g-d)*(g-d)+(h-e)*(h-e))};JSM.CoordSignedDistance=function(a,b,c){var d=JSM.CoordSub(b,a);a=JSM.CoordDistance(a,b);c=JSM.GetVectorsAngle(d,c);JSM.IsPositive(c)&&(a=-a);return a};JSM.MidCoord=function(a,b){return new JSM.Coord((a.x+b.x)/2,(a.y+b.y)/2,(a.z+b.z)/2)};
JSM.VectorMultiply=function(a,b){var c=new JSM.Vector(0,0,0);c.x=a.x*b;c.y=a.y*b;c.z=a.z*b;return c};JSM.VectorDot=function(a,b){return a.x*b.x+a.y*b.y+a.z*b.z};JSM.VectorCross=function(a,b){var c=new JSM.Vector(0,0,0);c.x=a.y*b.z-a.z*b.y;c.y=a.z*b.x-a.x*b.z;c.z=a.x*b.y-a.y*b.x;return c};JSM.VectorLength=function(a){var b=a.x,c=a.y;a=a.z;return Math.sqrt(b*b+c*c+a*a)};
JSM.VectorNormalize=function(a){var b=JSM.VectorLength(a),c=new JSM.Vector(0,0,0);JSM.IsGreater(b,0)&&(c=JSM.VectorMultiply(a,1/b));return c};JSM.VectorSetLength=function(a,b){var c=b/JSM.VectorLength(a);return JSM.VectorMultiply(a,c)};JSM.GetVectorsAngle=function(a,b){var c=JSM.VectorNormalize(a),d=JSM.VectorNormalize(b);if(JSM.CoordIsEqual(c,d))return 0;c=JSM.VectorDot(c,d);return JSM.ArcCos(c)};
JSM.GetVectorsFullAngle=function(a,b,c){var d=JSM.GetVectorsAngle(a,b),e=new JSM.Coord(0,0,0);"Clockwise"==JSM.CoordTurnType(a,e,b,c)&&(d=2*Math.PI-d);return d};JSM.VectorsAreCollinear=function(a,b){var c=JSM.GetVectorsAngle(a,b);return JSM.IsEqual(c,0)||JSM.IsEqual(c,Math.PI)};JSM.CoordAdd=function(a,b){return new JSM.Vector(a.x+b.x,a.y+b.y,a.z+b.z)};JSM.CoordSub=function(a,b){return new JSM.Vector(a.x-b.x,a.y-b.y,a.z-b.z)};
JSM.CoordOffset=function(a,b,c){b=JSM.VectorNormalize(b);var d=new JSM.Coord(0,0,0);d.x=a.x+b.x*c;d.y=a.y+b.y*c;d.z=a.z+b.z*c;return d};
JSM.CoordRotate=function(a,b,c,d){var e=JSM.CoordSub(a,d),f=JSM.VectorNormalize(b);b=f.x;a=f.y;var f=f.z,g=e.x,h=e.y,e=e.z,l=new JSM.Coord(0,0,0);l.x=-b*(-b*g-a*h-f*e)*(1-Math.cos(c))+g*Math.cos(c)+(-f*h+a*e)*Math.sin(c);l.y=-a*(-b*g-a*h-f*e)*(1-Math.cos(c))+h*Math.cos(c)+(f*g-b*e)*Math.sin(c);l.z=-f*(-b*g-a*h-f*e)*(1-Math.cos(c))+e*Math.cos(c)+(-a*g+b*h)*Math.sin(c);return l=JSM.CoordAdd(l,d)};
JSM.GetCoord2DFromCoord=function(a,b,c){var d=new JSM.Vector(0,0,1),e=JSM.VectorCross(c,d);c=JSM.GetVectorsAngle(c,d);a=JSM.CoordRotate(a,e,c,b);return new JSM.Coord2D(a.x,a.y)};
JSM.CoordTurnType=function(a,b,c,d){var e=new JSM.Coord(0,0,0);a=JSM.GetCoord2DFromCoord(a,e,d);b=JSM.GetCoord2DFromCoord(b,e,d);c=JSM.GetCoord2DFromCoord(c,e,d);c=JSM.CoordTurnType2D(a,b,c);e=new JSM.Vector(0,0,1);d=JSM.GetVectorsAngle(d,e);JSM.IsEqual(d,Math.PI)&&("CounterClockwise"===c?c="Clockwise":"Clockwise"===c&&(c="CounterClockwise"));return c};
JSM.CalculateCentroid=function(a){var b=a.length,c=new JSM.Coord(0,0,0);if(1<=b){var d;for(d=0;d<b;d++)c=JSM.CoordAdd(c,a[d]);c=JSM.VectorMultiply(c,1/b)}return c};JSM.CalculateTriangleNormal=function(a,b,c){b=JSM.CoordSub(b,a);a=JSM.CoordSub(c,a);c=new JSM.Vector(0,0,0);c.x=b.y*a.z-b.z*a.y;c.y=b.z*a.x-b.x*a.z;c.z=b.x*a.y-b.y*a.x;return JSM.VectorNormalize(c)};
JSM.CalculateNormal=function(a){var b=a.length,c=new JSM.Vector(0,0,0);if(3<=b){var d,e,f;for(d=0;d<b;d++)e=d%b,f=(d+1)%b,e=a[e],f=a[f],c.x+=(e.y-f.y)*(e.z+f.z),c.y+=(e.z-f.z)*(e.x+f.x),c.z+=(e.x-f.x)*(e.y+f.y)}return JSM.VectorNormalize(c)};JSM.SphericalToCartesian=function(a,b,c){var d=new JSM.Coord(0,0,0);d.x=a*Math.sin(b)*Math.cos(c);d.y=a*Math.sin(b)*Math.sin(c);d.z=a*Math.cos(b);return d};
JSM.CartesianToSpherical=function(a,b,c){var d=new JSM.SphericalCoord(0,0,0);d.radius=Math.sqrt(a*a+b*b+c*c);if(JSM.IsZero(d.radius))return d;d.theta=Math.acos(c/d.radius);d.phi=Math.atan2(b,a);return d};JSM.SphericalToCartesianWithOrigo=function(a,b){var c=JSM.SphericalToCartesian(a.radius,a.theta,a.phi);return JSM.CoordAdd(c,b)};JSM.CartesianToSphericalWithOrigo=function(a,b){var c=JSM.CoordSub(a,b);return JSM.CartesianToSpherical(c.x,c.y,c.z)};
JSM.MoveCoordOnSphere=function(a,b,c,d){a=JSM.CartesianToSphericalWithOrigo(a,b);a.theta+=c;a.phi+=d;return JSM.SphericalToCartesianWithOrigo(a,b)};JSM.CylindricalToCartesian=function(a,b,c){var d=new JSM.Coord(0,0,0);d.x=a*Math.cos(c);d.y=a*Math.sin(c);d.z=b;return d};JSM.GetArcLength=function(a,b,c){return JSM.GetVectorsAngle(a,b)*c};JSM.GetFullArcLength=function(a,b,c,d){return JSM.GetVectorsFullAngle(a,b,d)*c};JSM.MatrixIdentity=function(){return[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]};
JSM.MatrixClone=function(a){var b=[];b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};JSM.MatrixTranspose=function(a){var b=[];b[0]=a[0];b[1]=a[4];b[2]=a[8];b[3]=a[12];b[4]=a[1];b[5]=a[5];b[6]=a[9];b[7]=a[13];b[8]=a[2];b[9]=a[6];b[10]=a[10];b[11]=a[14];b[12]=a[3];b[13]=a[7];b[14]=a[11];b[15]=a[15];return b};
JSM.MatrixVectorMultiply=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=a[1],h=a[2],l=a[3],k=a[5],m=a[6],n=a[7],p=a[9],q=a[10],r=a[11],s=a[13],x=a[14],v=a[15],t=[];t[0]=c*a[0]+d*a[4]+e*a[8]+f*a[12];t[1]=c*g+d*k+e*p+f*s;t[2]=c*h+d*m+e*q+f*x;t[3]=c*l+d*n+e*r+f*v;return t};
JSM.MatrixMultiply=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],l=a[6],k=a[7],m=a[8],n=a[9],p=a[10],q=a[11],r=a[12],s=a[13],x=a[14],v=a[15],t=b[0],y=b[1],F=b[2],C=b[3],u=b[4],H=b[5],z=b[6],I=b[7],J=b[8],D=b[9],A=b[10],B=b[11],K=b[12],L=b[13],M=b[14],w=b[15],G=[];G[0]=c*t+d*u+e*J+f*K;G[1]=c*y+d*H+e*D+f*L;G[2]=c*F+d*z+e*A+f*M;G[3]=c*C+d*I+e*B+f*w;G[4]=g*t+h*u+l*J+k*K;G[5]=g*y+h*H+l*D+k*L;G[6]=g*F+h*z+l*A+k*M;G[7]=g*C+h*I+l*B+k*w;G[8]=m*t+n*u+p*J+q*K;G[9]=m*y+n*H+p*D+q*L;G[10]=m*F+n*z+
p*A+q*M;G[11]=m*C+n*I+p*B+q*w;G[12]=r*t+s*u+x*J+v*K;G[13]=r*y+s*H+x*D+v*L;G[14]=r*F+s*z+x*A+v*M;G[15]=r*C+s*I+x*B+v*w;return G};JSM.MatrixDeterminant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],l=a[7],k=a[8],m=a[9],n=a[10],p=a[11],q=a[12],r=a[13],s=a[14];a=a[15];return(b*g-c*f)*(n*a-p*s)-(b*h-d*f)*(m*a-p*r)+(b*l-e*f)*(m*s-n*r)+(c*h-d*g)*(k*a-p*q)-(c*l-e*g)*(k*s-n*q)+(d*l-e*h)*(k*r-m*q)};
JSM.MatrixInvert=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],l=a[7],k=a[8],m=a[9],n=a[10],p=a[11],q=a[12],r=a[13],s=a[14];a=a[15];var x=b*g-c*f,v=b*h-d*f,t=b*l-e*f,y=c*h-d*g,F=c*l-e*g,C=d*l-e*h,u=k*r-m*q,H=k*s-n*q,z=k*a-p*q,I=m*s-n*r,J=m*a-p*r,D=n*a-p*s,A=x*D-v*J+t*I+y*z-F*H+C*u;if(JSM.IsZero(A))return null;var B=[];B[0]=(g*D-h*J+l*I)/A;B[1]=(d*J-c*D-e*I)/A;B[2]=(r*C-s*F+a*y)/A;B[3]=(n*F-m*C-p*y)/A;B[4]=(h*z-f*D-l*H)/A;B[5]=(b*D-d*z+e*H)/A;B[6]=(s*t-q*C-a*v)/A;B[7]=(k*C-n*t+p*
v)/A;B[8]=(f*J-g*z+l*u)/A;B[9]=(c*z-b*J-e*u)/A;B[10]=(q*F-r*t+a*x)/A;B[11]=(m*t-k*F-p*x)/A;B[12]=(g*H-f*I-h*u)/A;B[13]=(b*I-c*H+d*u)/A;B[14]=(r*v-q*y-s*x)/A;B[15]=(k*y-m*v+n*x)/A;return B};JSM.MatrixTranslation=function(a,b,c){var d=[1,0,0,0,0,1,0,0,0,0,1,0];d[12]=a;d[13]=b;d[14]=c;d[15]=1;return d};
JSM.MatrixRotation=function(a,b,c){var d=JSM.VectorNormalize(a);a=d.x;var e=d.y,d=d.z,f=a*a,g=e*e,h=d*d,l=Math.sin(b);b=Math.cos(b);var k=[];if(void 0===c||null===c)k[0]=f+(g+h)*b,k[1]=a*e*(1-b)+d*l,k[2]=a*d*(1-b)-e*l,k[3]=0,k[4]=a*e*(1-b)-d*l,k[5]=g+(f+h)*b,k[6]=e*d*(1-b)+a*l,k[7]=0,k[8]=a*d*(1-b)+e*l,k[9]=e*d*(1-b)-a*l,k[10]=h+(f+g)*b,k[11]=0,k[12]=0,k[13]=0,k[14]=0;else{var m=c.x,n=c.y;c=c.z;k[0]=f+(g+h)*b;k[1]=a*e*(1-b)+d*l;k[2]=a*d*(1-b)-e*l;k[3]=0;k[4]=a*e*(1-b)-d*l;k[5]=g+(f+h)*b;k[6]=e*d*
(1-b)+a*l;k[7]=0;k[8]=a*d*(1-b)+e*l;k[9]=e*d*(1-b)-a*l;k[10]=h+(f+g)*b;k[11]=0;k[12]=(m*(g+h)-a*(n*e+c*d))*(1-b)+(n*d-c*e)*l;k[13]=(n*(f+h)-e*(m*a+c*d))*(1-b)+(c*a-m*d)*l;k[14]=(c*(f+g)-d*(m*a+n*e))*(1-b)+(m*e-n*a)*l}k[15]=1;return k};
JSM.MatrixRotationQuaternion=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=b+b,g=c+c,h=d+d;a=b*f;var l=b*g,b=b*h,k=c*g,c=c*h,d=d*h,f=e*f,g=e*g,e=e*h,h=[];h[0]=1-(k+d);h[1]=l+e;h[2]=b-g;h[3]=0;h[4]=l-e;h[5]=1-(a+d);h[6]=c+f;h[7]=0;h[8]=b+g;h[9]=c-f;h[10]=1-(a+k);h[11]=0;h[12]=0;h[13]=0;h[14]=0;h[15]=1;return h};JSM.MatrixRotationX=function(a){var b=Math.sin(a);a=Math.cos(a);var c=[1,0,0,0,0];c[5]=a;c[6]=b;c[7]=0;c[8]=0;c[9]=-b;c[10]=a;c[11]=0;c[12]=0;c[13]=0;c[14]=0;c[15]=1;return c};
JSM.MatrixRotationY=function(a){var b=Math.sin(a);a=Math.cos(a);var c=[];c[0]=a;c[1]=0;c[2]=-b;c[3]=0;c[4]=0;c[5]=1;c[6]=0;c[7]=0;c[8]=b;c[9]=0;c[10]=a;c[11]=0;c[12]=0;c[13]=0;c[14]=0;c[15]=1;return c};JSM.MatrixRotationZ=function(a){var b=Math.sin(a);a=Math.cos(a);var c=[];c[0]=a;c[1]=b;c[2]=0;c[3]=0;c[4]=-b;c[5]=a;c[6]=0;c[7]=0;c[8]=0;c[9]=0;c[10]=1;c[11]=0;c[12]=0;c[13]=0;c[14]=0;c[15]=1;return c};
JSM.MatrixView=function(a,b,c){if(JSM.CoordIsEqual(a,b))return JSM.MatrixIdentity();var d=[];b=JSM.VectorNormalize(JSM.CoordSub(a,b));c=JSM.VectorNormalize(JSM.VectorCross(c,b));var e=JSM.VectorNormalize(JSM.VectorCross(b,c));d[0]=c.x;d[1]=e.x;d[2]=b.x;d[3]=0;d[4]=c.y;d[5]=e.y;d[6]=b.y;d[7]=0;d[8]=c.z;d[9]=e.z;d[10]=b.z;d[11]=0;d[12]=-JSM.VectorDot(c,a);d[13]=-JSM.VectorDot(e,a);d[14]=-JSM.VectorDot(b,a);d[15]=1;return d};
JSM.MatrixPerspective=function(a,b,c,d){var e=[];a=1/Math.tan(a/2);var f=1/(c-d);e[0]=a/b;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=a;e[6]=0;e[7]=0;e[8]=0;e[9]=0;e[10]=(d+c)*f;e[11]=-1;e[12]=0;e[13]=0;e[14]=2*d*c*f;e[15]=0;return e};JSM.ApplyTransformation=function(a,b){var c=[];c[0]=b.x;c[1]=b.y;c[2]=b.z;c[3]=1;c=JSM.MatrixVectorMultiply(a,c);return new JSM.Coord(c[0],c[1],c[2])};JSM.CoordSystem=function(a,b,c,d){this.origo=a;this.e1=b;this.e2=c;this.e3=d};
JSM.CoordSystem.prototype.Set=function(a,b,c,d){this.origo=a;this.e1=b;this.e2=c;this.e3=d};JSM.CoordSystem.prototype.Clone=function(){return new JSM.CoordSystem(this.origo.Clone(),this.e1.Clone(),this.e2.Clone(),this.e3.Clone())};JSM.CoordSystemToDirectionVectors=function(a){return new JSM.CoordSystem(a.origo,JSM.CoordSub(a.e1,a.origo),JSM.CoordSub(a.e2,a.origo),JSM.CoordSub(a.e3,a.origo))};
JSM.CoordSystemToAbsoluteCoords=function(a){return new JSM.CoordSystem(a.origo,JSM.CoordAdd(a.e1,a.origo),JSM.CoordAdd(a.e2,a.origo),JSM.CoordAdd(a.e3,a.origo))};
JSM.ChangeCoordSystem=function(a,b,c){var d=JSM.VectorNormalize(b.e1),e=JSM.VectorNormalize(b.e2),f=JSM.VectorNormalize(b.e3),g=JSM.VectorNormalize(c.e1),h=JSM.VectorNormalize(c.e2),l=JSM.VectorNormalize(c.e3);a=JSM.CoordSub(a,b.origo);b=new JSM.Coord(0,0,0);b.x=JSM.VectorDot(g,d)*a.x+JSM.VectorDot(g,e)*a.y+JSM.VectorDot(g,f)*a.z;b.y=JSM.VectorDot(h,d)*a.x+JSM.VectorDot(h,e)*a.y+JSM.VectorDot(h,f)*a.z;b.z=JSM.VectorDot(l,d)*a.x+JSM.VectorDot(l,e)*a.y+JSM.VectorDot(l,f)*a.z;return b=JSM.CoordAdd(b,
c.origo)};JSM.Sector2D=function(a,b){this.beg=a;this.end=b};JSM.Sector2D.prototype.Set=function(a,b){this.beg=a;this.end=b};JSM.Sector2D.prototype.Clone=function(){return new JSM.Sector2D(this.beg.Clone(),this.end.Clone())};JSM.Sector=function(a,b){this.beg=a;this.end=b};JSM.Sector.prototype.Set=function(a,b){this.beg=a;this.end=b};JSM.Sector.prototype.Clone=function(){return new JSM.Sector(this.beg.Clone(),this.end.Clone())};
JSM.CoordSectorPosition2D=function(a,b){var c=a.x,d=a.y,e=b.beg.x,f=b.beg.y,g=b.end.x,h=b.end.y,l=Math.pow(g-e,2)+Math.pow(h-f,2);if(JSM.IsZero(l))return JSM.CoordIsEqual2D(a,b.beg)?"CoordOnSectorEndCoord":"CoordOutsideOfSector";l=((c-e)*(g-e)+(d-f)*(h-f))/l;if(JSM.IsLower(l,0)||JSM.IsGreater(l,1))return"CoordOutsideOfSector";f+=l*(h-f);return!JSM.IsEqual(e+l*(g-e),c)||!JSM.IsEqual(f,d)?"CoordOutsideOfSector":JSM.IsEqual(l,0)||JSM.IsEqual(l,1)?"CoordOnSectorEndCoord":"CoordInsideOfSector"};
JSM.SectorSectorPosition2D=function(a,b,c){var d=a.beg.x,e=a.beg.y,f=a.end.x,g=a.end.y,h=b.beg.x,l=b.beg.y,k=b.end.x,m=b.end.y,n=(k-h)*(e-l)-(m-l)*(d-h),p=(f-d)*(e-l)-(g-e)*(d-h);if(JSM.IsZero(n)&&JSM.IsZero(p))return c=JSM.CoordSectorPosition2D(a.beg,b),d=JSM.CoordSectorPosition2D(a.end,b),e=JSM.CoordSectorPosition2D(b.beg,a),a=JSM.CoordSectorPosition2D(b.end,a),"CoordInsideOfSector"===c||("CoordInsideOfSector"===d||"CoordInsideOfSector"===e||"CoordInsideOfSector"===a)||"CoordOnSectorEndCoord"===
c&&"CoordOnSectorEndCoord"===d&&"CoordOnSectorEndCoord"===e&&"CoordOnSectorEndCoord"===a?"SectorsIntersectsCoincident":"CoordOnSectorEndCoord"===c||"CoordOnSectorEndCoord"===d||"CoordOnSectorEndCoord"===e||"CoordOnSectorEndCoord"===a?"SectorsIntersectsEndPoint":"SectorsDontIntersects";a=(m-l)*(f-d)-(k-h)*(g-e);if(JSM.IsZero(a))return"SectorsDontIntersects";n/=a;p/=a;if(JSM.IsLower(n,0)||JSM.IsGreater(n,1)||JSM.IsLower(p,0)||JSM.IsGreater(p,1))return"SectorsDontIntersects";void 0!==c&&(c.x=d+n*(f-
d),c.y=e+n*(g-e));return JSM.IsEqual(n,0)||JSM.IsEqual(n,1)||JSM.IsEqual(p,0)||JSM.IsEqual(p,1)?"SectorsIntersectsEndPoint":"SectorsIntersectsOnePoint"};JSM.GetSectorSegmentation=function(a,b,c){var d=JSM.CoordSub(a.end,a.beg),e=JSM.CoordDistance(a.beg,a.end)/b,f=0,g;for(g=0;g<=b;g++)c.push(JSM.CoordOffset(a.beg,d,f)),f+=e};JSM.Line2D=function(a,b){this.start=a;this.direction=b};JSM.Line2D.prototype.Set=function(a,b){this.start=a;this.direction=b};
JSM.Line2D.prototype.Clone=function(){return new JSM.Line2D(this.start.Clone(),this.direction.Clone())};JSM.Line=function(a,b){this.start=a;this.direction=b};JSM.Line.prototype.Set=function(a,b){this.start=a;this.direction=b};JSM.Line.prototype.Clone=function(){return new JSM.Line(this.start.Clone(),this.direction.Clone())};
JSM.CoordLinePosition2D=function(a,b){var c=b.start,d=b.direction,c=d.x*(a.y-c.y)-d.y*(a.x-c.x);return JSM.IsPositive(c)?"CoordAtLineLeft":JSM.IsNegative(c)?"CoordAtLineRight":"CoordOnLine"};
JSM.CoordLinePosition=function(a,b,c){var d=a.x,e=a.y,f=a.z,g=b.start;b=b.direction;var h=g.x,l=g.y,k=g.z,m=g.x+b.x,n=g.y+b.y,p=g.z+b.z,q=(m-h)*(m-h)+(n-l)*(n-l)+(p-k)*(p-k);if(JSM.IsZero(q))return void 0!==c&&c.Set(g.x,g.y,g.z),JSM.CoordIsEqual(g,a)?"CoordOnLine":"CoordOutsideOfLine";d=JSM.CoordAdd(g,JSM.VectorMultiply(b,((m-h)*(d-h)+(n-l)*(e-l)+(p-k)*(f-k))/q));void 0!==c&&c.Set(d.x,d.y,d.z);a=JSM.CoordDistance(a,d);return JSM.IsZero(a)?"CoordOnLine":"CoordOutsideOfLine"};
JSM.ProjectCoordToLine=function(a,b){var c=new JSM.Coord(0,0,0),d=a.x,e=a.y,f=a.z,g=b.start,h=b.direction,l=g.x,k=g.y,m=g.z,n=g.x+h.x,p=g.y+h.y,q=g.z+h.z,r=(n-l)*(n-l)+(p-k)*(p-k)+(q-m)*(q-m);if(JSM.IsZero(r))return c.Set(g.x,g.y,g.z),c;d=JSM.CoordAdd(g,JSM.VectorMultiply(h,((n-l)*(d-l)+(p-k)*(e-k)+(q-m)*(f-m))/r));c.Set(d.x,d.y,d.z);return c};
JSM.LineLineClosestPoint=function(a,b,c,d){function e(a,b,c,d,e){return(a[b].x-a[c].x)*(a[d].x-a[e].x)+(a[b].y-a[c].y)*(a[d].y-a[e].y)+(a[b].z-a[c].z)*(a[d].z-a[e].z)}var f=JSM.VectorNormalize(a.direction),g=a.start,f=JSM.CoordAdd(g,f);a=JSM.VectorNormalize(b.direction);b=b.start;var h=JSM.CoordAdd(b,a),l=[g,f,b,h],k=e(l,1,0,1,0),m=e(l,0,2,1,0),h=e(l,0,2,3,2),n=e(l,3,2,1,0),l=e(l,3,2,3,2),k=k*l-n*n;if(JSM.IsEqual(k,0))return!1;m=(h*n-m*l)/k;h=(h+m*n)/l;void 0!==c&&(f=JSM.VectorNormalize(JSM.CoordSub(f,
g)),g=JSM.CoordAdd(g,JSM.VectorMultiply(f,m)),c.Set(g.x,g.y,g.z));void 0!==d&&(c=JSM.CoordAdd(b,JSM.VectorMultiply(a,h)),d.Set(c.x,c.y,c.z));return!0};JSM.LineLinePosition=function(a,b,c){var d=new JSM.Coord(0,0,0),e=new JSM.Coord(0,0,0);return!JSM.LineLineClosestPoint(a,b,d,e)?"LinesIntersectsCoincident":JSM.CoordIsEqual(d,e)?(void 0!==c&&c.Set(d.x,d.y,d.z),"LinesIntersectsOnePoint"):"LinesDontIntersects"};JSM.Transformation=function(){this.matrix=JSM.MatrixIdentity()};
JSM.Transformation.prototype.GetMatrix=function(){return this.matrix};JSM.Transformation.prototype.SetMatrix=function(a){this.matrix=a};JSM.Transformation.prototype.Append=function(a){this.matrix=JSM.MatrixMultiply(this.matrix,a.matrix)};JSM.Transformation.prototype.Apply=function(a){return JSM.ApplyTransformation(this.matrix,a)};JSM.Transformation.prototype.Clone=function(){var a=new JSM.Transformation;a.matrix=JSM.MatrixClone(this.matrix);return a};
JSM.IdentityTransformation=function(){var a=new JSM.Transformation;a.matrix=JSM.MatrixIdentity();return a};JSM.TranslationTransformation=function(a){var b=new JSM.Transformation;b.matrix=JSM.MatrixTranslation(a.x,a.y,a.z);return b};JSM.OffsetTransformation=function(a,b){var c=JSM.VectorNormalize(a),c=JSM.VectorMultiply(c,b);return JSM.TranslationTransformation(c)};JSM.RotationTransformation=function(a,b,c){var d=new JSM.Transformation;d.matrix=JSM.MatrixRotation(a,b,c);return d};
JSM.RotationXTransformation=function(a,b){var c=new JSM.Transformation;void 0===b||null===b?c.matrix=JSM.MatrixRotationX(a):(c.Append(JSM.TranslationTransformation(new JSM.Vector(-b.x,-b.y,-b.z))),c.Append(JSM.RotationXTransformation(a)),c.Append(JSM.TranslationTransformation(new JSM.Vector(b.x,b.y,b.z))));return c};
JSM.RotationYTransformation=function(a,b){var c=new JSM.Transformation;void 0===b||null===b?c.matrix=JSM.MatrixRotationY(a):(c.Append(JSM.TranslationTransformation(new JSM.Vector(-b.x,-b.y,-b.z))),c.Append(JSM.RotationYTransformation(a)),c.Append(JSM.TranslationTransformation(new JSM.Vector(b.x,b.y,b.z))));return c};
JSM.RotationZTransformation=function(a,b){var c=new JSM.Transformation;void 0===b||null===b?c.matrix=JSM.MatrixRotationZ(a):(c.Append(JSM.TranslationTransformation(new JSM.Vector(-b.x,-b.y,-b.z))),c.Append(JSM.RotationZTransformation(a)),c.Append(JSM.TranslationTransformation(new JSM.Vector(b.x,b.y,b.z))));return c};
JSM.RotationXYZTransformation=function(a,b,c,d){var e=new JSM.Transformation;e.Append(JSM.RotationXTransformation(a,d));e.Append(JSM.RotationYTransformation(b,d));e.Append(JSM.RotationZTransformation(c,d));return e};JSM.Plane=function(a,b,c,d){this.a=a;this.b=b;this.c=c;this.d=d};JSM.Plane.prototype.Set=function(a,b,c,d){this.a=a;this.b=b;this.c=c;this.d=d};JSM.Plane.prototype.GetNormal=function(){return new JSM.Vector(this.a,this.b,this.c)};
JSM.Plane.prototype.Clone=function(){return new JSM.Plane(this.a,this.b,this.c,this.d)};JSM.GetPlaneFromCoordAndDirection=function(a,b){var c=new JSM.Plane,d=JSM.VectorNormalize(b),e=d.x,f=d.y,d=d.z;c.Set(e,f,d,-(e*a.x+f*a.y+d*a.z));return c};JSM.GetPlaneFromThreeCoords=function(a,b,c){var d=new JSM.Plane,e=(b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z),f=(b.z-a.z)*(c.x-a.x)-(c.z-a.z)*(b.x-a.x);b=(b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);d.Set(e,f,b,-(e*a.x+f*a.y+b*a.z));return d};
JSM.CoordPlanePosition=function(a,b){var c=b.a*a.x+b.b*a.y+b.c*a.z+b.d;return JSM.IsPositive(c)?"CoordInFrontOfPlane":JSM.IsNegative(c)?"CoordAtBackOfPlane":"CoordOnPlane"};
JSM.LinePlanePosition=function(a,b,c){var d=JSM.VectorNormalize(a.direction),e=a.start.x,f=a.start.y,g=a.start.z,h=b.a,l=b.b,k=b.c;b=b.d;var m=h*(e-(a.start.x+d.x))+l*(f-(a.start.y+d.y))+k*(g-(a.start.z+d.z));if(JSM.IsZero(m))return"LineParallelToPlane";void 0!==c&&(a=JSM.CoordAdd(a.start,JSM.VectorMultiply(d,(h*e+l*f+k*g+b)/m)),c.Set(a.x,a.y,a.z));return"LineIntersectsPlane"};
JSM.LinePlaneIntersection=function(a,b){var c=JSM.VectorNormalize(a.direction),d=a.start.x,e=a.start.y,f=a.start.z,g=a.start.x+c.x,h=a.start.y+c.y,l=a.start.z+c.z,k=b.a,m=b.b,n=b.c,p=b.d,q=new JSM.Coord(0,0,0),g=k*(d-g)+m*(e-h)+n*(f-l);return JSM.IsZero(g)?q:q=JSM.CoordAdd(a.start,JSM.VectorMultiply(c,(k*d+m*e+n*f+p)/g))};JSM.CoordPlaneSignedDistance=function(a,b){var c=b.a,d=b.b,e=b.c;return(c*a.x+d*a.y+e*a.z+b.d)/Math.sqrt(c*c+d*d+e*e)};
JSM.CoordPlaneDistance=function(a,b){return Math.abs(JSM.CoordPlaneSignedDistance(a,b))};JSM.CoordPlaneSignedDirectionalDistance=function(a,b,c){var d=JSM.VectorNormalize(b);b=a.x;var e=a.y,f=a.z,g=c.a,h=c.b,l=c.c;c=c.d;var k=g*(b-(a.x+d.x))+h*(e-(a.y+d.y))+l*(f-(a.z+d.z));if(JSM.IsZero(k))return 0;d=JSM.CoordAdd(a,JSM.VectorMultiply(d,(g*b+h*e+l*f+c)/k));a=JSM.CoordDistance(a,d);JSM.IsNegative(g*b+h*e+l*f+c)&&(a=-a);return a};
JSM.CoordPlaneDirectionalDistance=function(a,b,c){return Math.abs(JSM.CoordPlaneSignedDirectionalDistance(a,b,c))};JSM.ProjectCoordToPlane=function(a,b){var c=a.x,d=a.y,e=a.z,f=b.a,g=b.b,h=b.c,l=b.d,k=JSM.CoordPlaneDistance(a,b);JSM.IsGreater(f*c+g*d+h*e+l,0)&&(k=-k);c=JSM.VectorNormalize(new JSM.Coord(f,g,h));return JSM.CoordOffset(a,c,k)};
JSM.Project=function(a,b,c,d,e,f,g,h,l){b=JSM.MatrixView(b,c,d);g=JSM.MatrixPerspective(e,f,g,h);e=new JSM.Coord(0,0,0);h=[];f=[];h[0]=a.x;h[1]=a.y;h[2]=a.z;h[3]=1;f=JSM.MatrixVectorMultiply(g,JSM.MatrixVectorMultiply(b,h));a=f[3];JSM.IsZero(a)?l=null:(f[0]=0.5*(f[0]/a)+0.5,f[1]=0.5*(f[1]/a)+0.5,f[2]=0.5*(f[2]/a)+0.5,f[0]=f[0]*l[2]+l[0],f[1]=f[1]*l[3]+l[1],e.x=f[0],e.y=f[1],e.z=f[2],l=e);return l};
JSM.ConvexHull2D=function(a){function b(a,b){var c=a.length,d=0,e;for(e=1;e<c;e++)b==d?d=e:"Clockwise"==JSM.CoordTurnType2D(a[b],a[d],a[e])&&(d=e);return d}var c=[];if(3>a.length)return c;var d=function(a){var b=a.length,c=JSM.Inf,d=-1,e,f;for(e=0;e<b;e++)f=a[e].x,JSM.IsLower(f,c)&&(c=f,d=e);return d}(a),e=d,f;do c.push(e),e=f=b(a,e);while(f!=d);return c};
JSM.ConvexHull3D=function(a){function b(){this.position=null}function c(){this.tri2=this.tri1=this.vert2=this.vert1=null}function d(){this.valid=this.edges=this.vertices=null}function e(a,c){var d=new b;d.position=c;a.vertices.push(d);return a.vertices.length-1}function f(a,b,d,e){var f=-1,g,h;for(g=0;g<a.edges.length;g++)if(h=a.edges[g],h.vert1==d&&h.vert2==e||h.vert1==e&&h.vert2==d){f=g;break}-1==f&&(f=new c,f.vert1=d,f.vert2=e,f.tri1=-1,f.tri2=-1,a.edges.push(f),f=a.edges.length-1);a=a.edges[f];
a.tri1!=b&&a.tri2!=b&&(-1==a.tri1?a.tri1=b:-1==a.tri2&&(a.tri2=b));return f}function g(a,b,c,e){var g=a.triangles.length,h=f(a,g,b,c),k=f(a,g,c,e),g=f(a,g,e,b),l=new d;l.vertices=[b,c,e];l.edges=[h,k,g];l.valid=!0;a.triangles.push(l);return a.triangles.length-1}function h(a,b,c){a=a.edges[c];a.tri1==b?a.tri1=-1:a.tri2==b&&(a.tri2=-1)}function l(a,b,c,d,e){c=a.vertices[c].position;d=a.vertices[d].position;e=a.vertices[e].position;a=JSM.CoordSub(a.vertices[b].position,e);b=JSM.CoordSub(c,e);c=JSM.CoordSub(d,
e);return JSM.VectorDot(a,JSM.VectorCross(b,c))/6}function k(a,b){var c=[],d,e;for(d=0;d<a.triangles.length;d++)e=a.triangles[d],e.valid?!JSM.IsLower(l(a,e.vertices[0],e.vertices[2],e.vertices[1],b),0)?c.push(!0):c.push(!1):c.push(!1);var f,k,m,n=[];for(d=0;d<c.length;d++)c[d]&&(e=a.triangles[d],e.valid&&(f=a.edges[e.edges[0]],k=a.edges[e.edges[1]],m=a.edges[e.edges[2]],f=-1==f.tri1||-1==f.tri2||c[f.tri1]!=c[f.tri2],k=-1==k.tri1||-1==k.tri2||c[k.tri1]!=c[k.tri2],m=-1==m.tri1||-1==m.tri2||c[m.tri1]!=
c[m.tri2],f&&n.push([e.vertices[0],e.vertices[1],b]),k&&n.push([e.vertices[1],e.vertices[2],b]),m&&n.push([e.vertices[2],e.vertices[0],b])));for(d=0;d<c.length;d++)c[d]&&(e=a.triangles[d],e.valid&&(e=a,m=d,f=e.triangles[m],f.valid&&(h(e,m,f.edges[0]),h(e,m,f.edges[1]),h(e,m,f.edges[2]),f.valid=!1)));for(d=0;d<n.length;d++)c=n[d],g(a,c[0],c[1],c[2])}var m=[],n=a.length;if(4>n)return m;var p=new function(){this.vertices=[];this.edges=[];this.triangles=[]},q;for(q=0;q<n;q++)e(p,a[q]);(function(a){var b=
-1,b=!JSM.IsLower(l(a,0,1,2,3),0)?g(a,0,1,2):g(a,0,2,1),b=a.triangles[b];g(a,b.vertices[0],b.vertices[2],3);g(a,b.vertices[2],b.vertices[1],3);g(a,b.vertices[1],b.vertices[0],3)})(p);for(q=4;q<n;q++)k(p,q);for(q=0;q<p.triangles.length;q++)a=p.triangles[q],a.valid&&m.push(a.vertices);return m};JSM.Polygon2D=function(){this.vertices=[]};JSM.Polygon2D.prototype.AddVertex=function(a,b){this.vertices.push(new JSM.Coord2D(a,b))};JSM.Polygon2D.prototype.GetVertex=function(a){return this.vertices[a]};
JSM.Polygon2D.prototype.SetVertex=function(a,b,c){this.vertices[a].Set(b,c)};JSM.Polygon2D.prototype.VertexCount=function(){return this.vertices.length};JSM.Polygon2D.prototype.Clear=function(){this.vertices=[]};JSM.Polygon2D.prototype.Clone=function(){var a=new JSM.Polygon2D,b;for(b=0;b<this.vertices.length;b++)a.vertices.push(this.vertices[b].Clone());return a};JSM.ContourPolygon2D=function(){this.polygons=[]};
JSM.ContourPolygon2D.prototype.AddVertex=function(a,b,c){void 0===this.polygons[a]&&(this.polygons[a]=new JSM.Polygon2D);this.polygons[a].AddVertex(b,c)};JSM.ContourPolygon2D.prototype.VertexCount=function(a){return void 0===this.polygons[a]?0:this.polygons[a].VertexCount()};JSM.ContourPolygon2D.prototype.GetVertex=function(a,b){return this.polygons[a].GetVertex(b)};JSM.ContourPolygon2D.prototype.SetVertex=function(a,b,c,d){this.polygons[a].SetVertex(b,c,d)};
JSM.ContourPolygon2D.prototype.AddContour=function(){this.polygons.push(new JSM.Polygon2D)};JSM.ContourPolygon2D.prototype.ContourCount=function(){return this.polygons.length};JSM.ContourPolygon2D.prototype.GetContour=function(a){return this.polygons[a]};JSM.ContourPolygon2D.prototype.Clear=function(){this.polygons=[]};JSM.ContourPolygon2D.prototype.Clone=function(){var a=new JSM.ContourPolygon2D,b;for(b=0;b<this.polygons.length;b++)a.polygons.push(this.polygons[b].Clone());return a};
JSM.Polygon=function(){this.vertices=[]};JSM.Polygon.prototype.AddVertex=function(a,b,c){this.vertices.push(new JSM.Coord(a,b,c))};JSM.Polygon.prototype.GetVertex=function(a){return this.vertices[a]};JSM.Polygon.prototype.SetVertex=function(a,b,c,d){this.vertices[a].Set(b,c,d)};JSM.Polygon.prototype.VertexCount=function(){return this.vertices.length};JSM.Polygon.prototype.Clear=function(){this.vertices=[]};
JSM.Polygon.prototype.Clone=function(){var a=new JSM.Polygon,b;for(b=0;b<this.vertices.length;b++)a.vertices.push(this.vertices[b].Clone());return a};JSM.CreatePolygonFromVertices=function(a){var b=new JSM.Polygon2D,c,d;for(c=0;c<a.length;c++)d=a[c],b.AddVertex(d.x,d.y);return b};JSM.PolygonSignedArea2D=function(a){var b=a.VertexCount(),c=0,d,e,f;for(d=0;d<b;d++)e=a.GetVertex(d),f=a.GetVertex((d+1)%b),c+=e.x*f.y-f.x*e.y;return c/2};JSM.PolygonArea2D=function(a){return Math.abs(JSM.PolygonSignedArea2D(a))};
JSM.PolygonOrientation2D=function(a){a=JSM.PolygonSignedArea2D(a);return JSM.IsPositive(a)?"CounterClockwise":JSM.IsNegative(a)?"Clockwise":"Invalid"};JSM.ChangePolygonOrientation2D=function(a){var b=a.Clone();a.Clear();var c,d;for(c=b.VertexCount()-1;0<=c;c--)d=b.GetVertex(c),a.AddVertex(d.x,d.y)};JSM.CreateCCWPolygonFromVertices=function(a){a=JSM.CreatePolygonFromVertices(a);"CounterClockwise"!=JSM.PolygonOrientation2D(a)&&JSM.ChangePolygonOrientation2D(a);return a};
JSM.PolygonComplexity2D=function(a){var b=!1,c=!1,d=a.VertexCount(),e,f,g,h;for(e=0;e<d;e++)if(f=0===e?d-1:e-1,g=e,h=e===d-1?0:e+1,f=a.GetVertex(f),g=a.GetVertex(g),h=a.GetVertex(h),h=JSM.CoordTurnType2D(f,g,h),"CounterClockwise"===h?b=!0:"Clockwise"===h&&(c=!0),b&&c)return"Concave";return!b&&!c?"Invalid":"Convex"};
JSM.CoordPolygonPosition2D=function(a,b){var c=b.VertexCount(),d,e,f;for(d=0;d<c;d++)if(e=b.GetVertex(d),f=b.GetVertex((d+1)%c),e=new JSM.Sector2D(e,f),"CoordOutsideOfSector"!==JSM.CoordSectorPosition2D(a,e))return"CoordOnPolygonEdge";var g=0,h;for(d=0;d<c;d++)h=Math.abs(b.GetVertex(d).x-a.x),JSM.IsGreater(h,g)&&(g=h);g=new JSM.Sector2D(a,new JSM.Coord2D(a.x+2*g,a.y));h=0;var l;for(d=0;d<c;d++)e=b.GetVertex(d),f=b.GetVertex((d+1)%c),e=new JSM.Sector2D(e,f),f=new JSM.Coord2D(0,0),l=JSM.SectorSectorPosition2D(g,
e,f),"SectorsDontIntersects"!==l&&("SectorsIntersectsOnePoint"===l?h++:"SectorsIntersectsEndPoint"===l&&(JSM.CoordIsEqual2D(f,e.beg)?JSM.IsGreater(e.beg.y,e.end.y)&&h++:JSM.CoordIsEqual2D(f,e.end)&&JSM.IsLower(e.beg.y,e.end.y)&&h++));return 0===h%2?"CoordOutsideOfPolygon":"CoordInsideOfPolygon"};
JSM.SectorIntersectsPolygon2D=function(a,b,c,d){var e=a.VertexCount(),f,g,h;for(f=0;f<e;f++)if(g=f,h=(f+1)%e,!(g==c||h==c||g==d||h==d))if(g=new JSM.Sector2D(a.GetVertex(g),a.GetVertex(h)),g=JSM.SectorSectorPosition2D(b,g),"SectorsDontIntersects"!==g)return!0;return!1};
JSM.IsPolygonVertexVisible2D=function(a,b,c){if(b===c)return!1;var d=a.VertexCount();if(c===(0<b?b-1:d-1)||c===(b<d-1?b+1:0))return!1;d=new JSM.Sector2D(a.GetVertex(b),a.GetVertex(c));if(JSM.SectorIntersectsPolygon2D(a,d,b,c))return!1;b=JSM.MidCoord2D(d.beg,d.end);return"CoordInsideOfPolygon"!==JSM.CoordPolygonPosition2D(b,a)?!1:!0};
JSM.CreatePolygonWithHole2D=function(a){var b=[],c=[],d=0,e;c.push(-1);for(e=0;e<a.length;e++)null===a[e]&&(c.push(e),d+=1);c.push(e);d+=1;for(e=0;e<d;e++){var f=e,g=c[f]+1,h=c[f+1];if(0===f){f=void 0;for(f=g;f<h;f++)b.push(f)}else{for(var g=void 0,g=new JSM.Polygon2D,h=new JSM.Polygon2D,l=void 0,k=void 0,k=void 0,l=0;l<b.length;l++)k=a[b[l]],g.AddVertex(k.x,k.y);for(var m=c[f]+1,n=c[f+1],l=m;l<n;l++)k=a[l],h.AddVertex(k.x,k.y);for(var p=null,q=void 0,r=void 0,s=void 0,l=0;l<g.VertexCount();l++){r=
b[l];for(k=m;k<n;k++)if(s=k-m,q=new JSM.Sector(a[r],a[k]),!JSM.SectorIntersectsPolygon2D(g,q,l,-1)&&!JSM.SectorIntersectsPolygon2D(h,q,-1,s)){p=[r,k];break}if(null!==p)break}g=p;h=c[f]+1;f=c[f+1];l=[];n=m=void 0;for(m=0;m<b.length;m++)l[m]=b[m];b=[];p=k=void 0;for(m=0;m<l.length;m++)if(b.push(l[m]),l[m]==g[0]){n=g[1];k=!0;for(p=!1;!p;)b.push(n),!k&&n==g[1]&&(p=!0),k&&(k=!1),n=n<f-1?n+1:h;b.push(l[m])}}}return b};
JSM.PolygonTriangulate2D=function(a){function b(){var a=[],b,c,d,e;for(b=0;b<g.length;b++)if(d=g[b],3===d.length)if("CounterClockwise"===k)a.push(d);else{e=[];for(c=d.length-1;0<=c;c--)e.push(f-d[c]-1);a.push(e)}return a}function c(a,b,c){if(b===c)return!1;var d=a.VertexCount(),e;if(!(e=(b<d-1?b+1:0)===c))e=(0<b?b-1:d-1)===c;return e?!1:JSM.IsPolygonVertexVisible2D(a,b,c)}function d(a,b,c){var d=a.length;if(3>=d)return!0;var e,f,h,k;for(e=0;2>e;e++){h=f=-1;0===e?(f=b,h=c):1===e&&(f=c,h=b);k=[];for(k.push(a[h]);f!==
h;f=f<d-1?f+1:0)k.push(a[f]);g.push(k)}return!0}var e=a.Clone(),f=e.VertexCount();if(3>f)return[];var g=[],h=[],l;for(a=0;a<f;a++)h.push(a);g.push(h);if(3===f)return b();var h=JSM.PolygonComplexity2D(e),k=JSM.PolygonOrientation2D(e);if("Invalid"===h||"Invalid"===k)return[];if("CounterClockwise"!==k){var m,n,p;for(a=0;a<f/2;a++)m=a,n=f-a-1,p=e.vertices[m],e.vertices[m]=e.vertices[n],e.vertices[n]=p}if("Convex"===h){for(a=0;a<f-2;a++)e=[],e.push(0),e.push((a+1)%f),e.push((a+2)%f),g.push(e);return b()}var q;
for(a=0;a<g.length;a++)if(m=g[a],n=m.length,3!==n){p=new JSM.Polygon2D;for(h=0;h<n;h++)l=e.GetVertex(m[h]),p.AddVertex(l.x,l.y);q=!1;for(h=0;h<n;h++){for(l=0;l<n;l++)if(c(p,h,l)){d(m,h,l);q=!0;break}if(q)break}}return b()};
JSM.CheckTriangulation2D=function(a,b){var c=JSM.PolygonSignedArea2D(a),d=0,e,f,g,h,l;for(e=0;e<b.length;e++){g=b[e];if(3!==g.length)return!1;h=new JSM.Polygon2D;for(f=0;f<g.length;f++)l=a.GetVertex(g[f]),h.AddVertex(l.x,l.y);d+=JSM.PolygonSignedArea2D(h)}return!JSM.IsEqual(c,d)?!1:!0};
JSM.CreatePolygonWithHole=function(a){var b=[],c;for(c=0;c<a.length;c++)null!==a[c]&&b.push(a[c]);var b=JSM.CalculateNormal(b),d=new JSM.Coord(0,0,0),e=[],f;for(c=0;c<a.length;c++)null!==a[c]?(f=JSM.GetCoord2DFromCoord(a[c],d,b),e.push(f)):e.push(null);return JSM.CreatePolygonWithHole2D(e)};
JSM.PolygonTriangulate=function(a){var b=new JSM.Polygon2D,c=JSM.CalculateNormal(a.vertices),d=new JSM.Coord(0,0,0),e=a.VertexCount(),f,g;for(f=0;f<e;f++)g=JSM.GetCoord2DFromCoord(a.GetVertex(f),d,c),b.AddVertex(g.x,g.y);return JSM.PolygonTriangulate2D(b)};
JSM.OffsetPolygonContour=function(a,b){var c=a.VertexCount(),d=JSM.CalculateNormal(a.vertices),e,f,g,h,l,k=new JSM.Polygon,m;for(m=0;m<c;m++)e=0===m?c-1:m-1,f=m,g=m===c-1?0:m+1,e=a.GetVertex(e),f=a.GetVertex(f),h=a.GetVertex(g),l=JSM.CoordSub(e,f),g=JSM.CoordSub(h,f),l=JSM.GetVectorsAngle(l,g)/2,"Clockwise"===JSM.CoordTurnType(e,f,h,d)&&(l=Math.PI-l),e=b/Math.sin(l),e=JSM.CoordOffset(f,g,e),e=JSM.CoordRotate(e,d,l,f),k.AddVertex(e.x,e.y,e.z);return k};
JSM.CutPolygonWithPlane=function(a,b,c,d,e){function f(a,b,c,d,e){1==b?c.push(a):-1==b?d.push(a):e.push(a)}function g(a,b,c,d){function e(a,b){if(!(2>b.length)){for(var c=a.GetVertex(b[0]),d=a.GetVertex(b[1]),d=JSM.CoordSub(d,c),f=JSM.GetPlaneFromCoordAndDirection(c,d),g,d=[],c=0;c<b.length;c++)g=a.GetVertex(b[c]),d.push(JSM.CoordPlaneSignedDistance(g,f));for(c=0;c<b.length-1;c++)for(f=0;f<b.length-c-1;f++)if(JSM.IsGreater(d[f],d[f+1])){g=d;var h=f+1,k=g[f];g[f]=g[h];g[h]=k;g=b;h=f+1;k=g[f];g[f]=
g[h];g[h]=k}}}function f(a,b,c,d,e,g){function h(a,b){a[a[b]]=-1;a[b]=-1}var k=[];(function(a,b,c){var d;for(d=0;d<a.VertexCount();d++)c.push(-1);for(d=0;d<b.length;d+=2){a=c;var e=b,f=d;a[e[f]]=e[f+1];a[e[f+1]]=e[f]}})(a,b,k);var l=0;g&&(l=b.length-1);for(var m=b[l],n=m,p=!1,q=0,r=new JSM.Polygon,s;;){p||(q=c[n],0!==q&&(p=!0));if(0<r.VertexCount()&&n==m)if(1==q?d.push(r):-1==q&&e.push(r),r=new JSM.Polygon,0<l&&l<b.length){n=m=b[l];continue}else break;s=a.GetVertex(n);r.AddVertex(s.x,s.y,s.z);-1!=
k[n]?(l=g?l-2:l+2,n=k[n],h(k,n)):n=n<a.VertexCount()-1?n+1:0}}var g=[];(function(a,b){var c,d,e,f;for(c=0;c<a.length;c++)if(d=a[c],0===d){d=0<c?c-1:a.length-1;e=c<a.length-1?c+1:0;f=a[d];e=a[e];if(0!==e&&0===f){for(;0===a[d];)d=0<d?d-1:a.length-1;f=a[d]}(-1==f&&1==e||1==f&&-1==e)&&b.push(c)}})(b,g);0===g.length||0!==g.length%2||(e(a,g),f(a,g,b,c,d,!1),f(a,g,b,c,d,!0))}var h=new JSM.Polygon,l=[];b=function(a,b,c,d){function e(a,c,d,f,g){function h(a,c,d,e,f,g){var k=d[d.length-1];0!==k&&(0!==g&&k!=
g)&&(e=a.GetVertex(e),a=a.GetVertex(f),a=new JSM.Line(a,JSM.CoordSub(a,e)),f=new JSM.Coord(0,0,0),"LineIntersectsPlane"==JSM.LinePlanePosition(a,b,f)&&(c.AddVertex(f.x,f.y,f.z),d.push(0)))}function k(a,b,c,d,e){a=a.GetVertex(d);b.AddVertex(a.x,a.y,a.z);c.push(e)}var l=0===c,n=c===a.VertexCount(),p;n?(c=0,p=a.VertexCount()-1):p=c-1;f=f[c];l||h(a,d,g,p,c,f);n||k(a,d,g,c,f);return f}var f=[],g=!1,h=!1,l,t,y;for(l=0;l<a.VertexCount();l++)t=a.GetVertex(l),t=JSM.CoordPlanePosition(t,b),y=0,"CoordInFrontOfPlane"==
t?(y=1,h=!0):"CoordAtBackOfPlane"==t&&(y=-1,g=!0),f.push(y);if(g&&h)for(l=0;l<=a.VertexCount();l++)e(a,l,c,f,d);else{if(g)return-1;if(h)return 1}return 0}(a,b,h,l);0===h.VertexCount()&&0===l.length?f(a,b,c,d,e):g(h,l,c,d);return 0===c.length+d.length+e.length?!1:!0};JSM.BSPNode=function(){this.outside=this.inside=this.parent=this.plane=this.userData=this.polygon=null};JSM.BSPNode.prototype.IsLeaf=function(){return null===this.inside&&null===this.outside};JSM.BSPTree=function(){this.root=null};
JSM.BSPTree.prototype.AddPolygon=function(a,b){null===this.root&&(this.root=this.GetNewNode());return this.AddPolygonToNode(this.root,a,b)};JSM.BSPTree.prototype.Traverse=function(a){this.TraverseNode(this.root,a)};JSM.BSPTree.prototype.TraverseNode=function(a,b){null!==a&&(b(a),this.TraverseNode(a.inside,b),this.TraverseNode(a.outside,b))};JSM.BSPTree.prototype.GetNodes=function(){var a=[];this.Traverse(function(b){a.push(b)});return a};
JSM.BSPTree.prototype.NodeCount=function(){var a=0;this.Traverse(function(){a+=1});return a};
JSM.BSPTree.prototype.AddPolygonToNode=function(a,b,c){if(3>b.VertexCount())return!1;var d;if(null===a.polygon){d=JSM.CalculateNormal(b.vertices);var e=JSM.GetPlaneFromCoordAndDirection(b.GetVertex(0),d);a.polygon=b;void 0!==c&&(a.userData=c);a.plane=e}else{d=[];var f=[],e=[];JSM.CutPolygonWithPlane(b,a.plane,f,d,e)&&(0<d.length&&this.AddInsidePolygonsToNode(a,d,c),0<f.length&&this.AddOutsidePolygonsToNode(a,f,c),0<e.length&&(d=JSM.CalculateNormal(b.vertices),0<JSM.VectorDot(d,a.plane.GetNormal())?
this.AddInsidePolygonsToNode(a,e,c):this.AddOutsidePolygonsToNode(a,e,c)))}return!0};JSM.BSPTree.prototype.AddInsidePolygonsToNode=function(a,b,c){null===a.inside&&(a.inside=this.GetNewNode(),a.inside.parent=a);var d;for(d=0;d<b.length;d++)this.AddPolygonToNode(a.inside,b[d],c)};JSM.BSPTree.prototype.AddOutsidePolygonsToNode=function(a,b,c){null===a.outside&&(a.outside=this.GetNewNode(),a.outside.parent=a);var d;for(d=0;d<b.length;d++)this.AddPolygonToNode(a.outside,b[d],c)};
JSM.BSPTree.prototype.GetNewNode=function(){return new JSM.BSPNode};
JSM.ClipPolygonWithBSPTree=function(a,b,c,d,e,f){function g(a,b,c){if(null!==b){var d=[],e=[],f=[];JSM.CutPolygonWithPlane(a,b.plane,e,d,f)&&(0<d.length&&l(b,d,c),0<e.length&&k(b,e,c),0<f.length&&(a=JSM.CalculateNormal(a.vertices),0<JSM.VectorDot(a,b.plane.GetNormal())?l(b,f,!0):k(b,f,!0)))}}function h(a,b){var c;for(c=0;c<a.length;c++)b.push(a[c])}function l(a,b,c){if(null!==a.inside){a=a.inside;var e;for(e=0;e<b.length;e++)g(b[e],a,c)}else h(b,c?f:d)}function k(a,b,d){if(null!==a.outside){a=a.outside;
var f;for(f=0;f<b.length;f++)g(b[f],a,d)}else h(b,d?e:c)}g(a,b.root,!1);return!0};JSM.GetGaussianCParameter=function(a,b,c,d){return Math.sqrt(-(Math.pow(a-c,2)/(2*Math.log(d/Math.abs(b)))))};JSM.GetGaussianValue=function(a,b,c,d){return b*Math.exp(-(Math.pow(a-c,2)/(2*Math.pow(d,2))))};JSM.GenerateCirclePoints=function(a,b,c){var d=[],e=2*Math.PI,f=2*Math.PI/b,g,h;for(g=0;g<b;g++)h=JSM.CylindricalToCartesian(a,0,e),void 0!==c&&null!==c&&(h=JSM.CoordAdd(h,c)),d.push(h),e+=f;return d};
JSM.GetRuledMesh=function(a,b,c,d,e){if(a.length===b.length){var f=a.length-1,g=[],h=[],l;for(l=0;l<=f;l++)g.push(JSM.CoordSub(b[l],a[l])),h.push(JSM.CoordDistance(a[l],b[l]));var k,m;for(l=0;l<=f;l++){k=h[l]/c;for(b=0;b<=c;b++)m=JSM.CoordOffset(a[l],g[l],k*b),d.push(m)}for(l=0;l<f;l++)for(b=0;b<c;b++)a=l*(c+1)+b,d=a+1,g=a+c+1,h=g+1,a=[a,g,h,d],e.push(a)}};JSM.BodyVertex=function(a){this.position=a};JSM.BodyVertex.prototype.GetPosition=function(){return this.position};
JSM.BodyVertex.prototype.SetPosition=function(a){this.position=a};JSM.BodyVertex.prototype.Clone=function(){return new JSM.BodyVertex(this.position.Clone())};JSM.BodyPolygon=function(a){this.vertices=a;this.curved=this.material=-1};JSM.BodyPolygon.prototype.AddVertexIndex=function(a){this.vertices.push(a)};JSM.BodyPolygon.prototype.GetVertexIndex=function(a){return this.vertices[a]};JSM.BodyPolygon.prototype.VertexIndexCount=function(){return this.vertices.length};
JSM.BodyPolygon.prototype.HasMaterialIndex=function(){return-1!==this.material};JSM.BodyPolygon.prototype.GetMaterialIndex=function(){return this.material};JSM.BodyPolygon.prototype.SetMaterialIndex=function(a){this.material=a};JSM.BodyPolygon.prototype.HasCurveGroup=function(){return-1!==this.curved};JSM.BodyPolygon.prototype.GetCurveGroup=function(){return this.curved};JSM.BodyPolygon.prototype.SetCurveGroup=function(a){this.curved=a};
JSM.BodyPolygon.prototype.InheritAttributes=function(a){this.material=a.material;this.curved=a.curved};JSM.BodyPolygon.prototype.Clone=function(){var a=new JSM.BodyPolygon([]),b;for(b=0;b<this.vertices.length;b++)a.vertices.push(this.vertices[b]);a.material=this.material;a.curved=this.curved;return a};JSM.Body=function(){this.vertices=[];this.polygons=[];this.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1))};
JSM.Body.prototype.AddVertex=function(a){this.vertices.push(a);return this.vertices.length-1};JSM.Body.prototype.AddPolygon=function(a){this.polygons.push(a);return this.polygons.length-1};JSM.Body.prototype.GetVertex=function(a){return this.vertices[a]};JSM.Body.prototype.GetVertexPosition=function(a){return this.vertices[a].position};JSM.Body.prototype.SetVertexPosition=function(a,b){this.vertices[a].position=b};JSM.Body.prototype.VertexCount=function(){return this.vertices.length};
JSM.Body.prototype.GetPolygon=function(a){return this.polygons[a]};JSM.Body.prototype.PolygonCount=function(){return this.polygons.length};JSM.Body.prototype.SetPolygonsMaterialIndex=function(a){var b;for(b=0;b<this.polygons.length;b++)this.polygons[b].SetMaterialIndex(a)};JSM.Body.prototype.SetPolygonsCurveGroup=function(a){var b;for(b=0;b<this.polygons.length;b++)this.polygons[b].SetCurveGroup(a)};JSM.Body.prototype.GetTextureProjectionType=function(){return this.projection};
JSM.Body.prototype.SetTextureProjectionType=function(a){this.projection=a};JSM.Body.prototype.GetTextureProjectionCoords=function(){return this.coords};JSM.Body.prototype.SetTextureProjectionCoords=function(a){this.coords=a};JSM.Body.prototype.SetPlanarTextureProjection=function(a,b,c){this.SetTextureProjectionType("Planar");this.SetTextureProjectionCoords(new JSM.CoordSystem(a,b,JSM.VectorCross(b,c),new JSM.Coord(0,0,0)))};
JSM.Body.prototype.SetCubicTextureProjection=function(a,b,c,d){this.SetTextureProjectionType("Cubic");this.SetTextureProjectionCoords(new JSM.CoordSystem(a,b,c,d))};JSM.Body.prototype.SetCylindricalTextureProjection=function(a,b,c,d){this.SetTextureProjectionType("Cylindrical");this.SetTextureProjectionCoords(new JSM.CoordSystem(a,JSM.VectorSetLength(c,b),JSM.VectorSetLength(JSM.VectorCross(d,c),b),d))};
JSM.Body.prototype.Transform=function(a){var b;for(b=0;b<this.vertices.length;b++)this.vertices[b].position=a.Apply(this.vertices[b].position);null!==this.coords&&(b=JSM.CoordSystemToAbsoluteCoords(this.coords),b.origo=a.Apply(b.origo),b.e1=a.Apply(b.e1),b.e2=a.Apply(b.e2),b.e3=a.Apply(b.e3),this.coords=JSM.CoordSystemToDirectionVectors(b))};
JSM.Body.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d;for(c=0;c<this.vertices.length;c++)d=this.vertices[c].position,a.x=JSM.Minimum(a.x,d.x),a.y=JSM.Minimum(a.y,d.y),a.z=JSM.Minimum(a.z,d.z),b.x=JSM.Maximum(b.x,d.x),b.y=JSM.Maximum(b.y,d.y),b.z=JSM.Maximum(b.z,d.z);return[a,b]};JSM.Body.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.Body.prototype.GetBoundingSphereRadius=function(){var a=this.GetCenter(),b=0,c,d;for(c=0;c<this.vertices.length;c++)d=JSM.CoordDistance(a,this.vertices[c].position),JSM.IsGreater(d,b)&&(b=d);return b};JSM.Body.prototype.OffsetToOrigo=function(){var a=this.GetCenter(),a=JSM.VectorMultiply(a,-1),b;for(b=0;b<this.vertices.length;b++)this.vertices[b].position=JSM.CoordAdd(this.vertices[b].position,a)};
JSM.Body.prototype.Merge=function(a){var b=this.vertices.length,c,d;for(c=0;c<a.VertexCount();c++)this.vertices.push(a.GetVertex(c).Clone());var e;for(c=0;c<a.PolygonCount();c++){e=a.GetPolygon(c).Clone();for(d=0;d<e.VertexIndexCount();d++)e.vertices[d]+=b;this.polygons.push(e)}};JSM.Body.prototype.Clear=function(){this.vertices=[];this.polygons=[];this.coords=this.projection=null};JSM.Model=function(){this.bodies=[]};
JSM.Model.prototype.AddBody=function(a){this.bodies.push(a);return this.bodies.length-1};JSM.Model.prototype.GetBody=function(a){return this.bodies[a]};JSM.Model.prototype.BodyCount=function(){return this.bodies.length};JSM.Model.prototype.VertexCount=function(){var a=0,b;for(b=0;b<this.bodies.length;b++)a+=this.bodies[b].VertexCount();return a};JSM.Model.prototype.PolygonCount=function(){var a=0,b;for(b=0;b<this.bodies.length;b++)a+=this.bodies[b].PolygonCount();return a};
JSM.HexColorToRGBComponents=function(a){for(var b=a.toString(16);6>b.length;)b="0"+b;a=parseInt(b.substr(0,2),16);var c=parseInt(b.substr(2,2),16),b=parseInt(b.substr(4,2),16);return[a,c,b]};JSM.HexColorToNormalizedRGBComponents=function(a){a=JSM.HexColorToRGBComponents(a);return[a[0]/255,a[1]/255,a[2]/255]};JSM.HexColorToRGBColor=function(a){return parseInt("0x"+a,16)};
JSM.RGBComponentsToHexColor=function(a,b,c){function d(a){for(a=parseInt(a,10).toString(16);2>a.length;)a="0"+a;return a}a=d(a);b=d(b);c=d(c);return parseInt("0x"+a+b+c,16)};JSM.Light=function(a){var b=8355711,c=8355711,d=0,e=new JSM.Vector(1,0,0);void 0!==a&&null!==a&&(b=JSM.ValueOrDefault(a.ambient,b),c=JSM.ValueOrDefault(a.diffuse,c),d=JSM.ValueOrDefault(a.specular,d),e=JSM.ValueOrDefault(a.direction,e));this.ambient=b;this.diffuse=c;this.specular=d;this.direction=e};
JSM.Material=function(a){var b=52224,c=52224,d=0,e=0,f=1,g=null,h=1,l=1;void 0!==a&&null!==a&&(b=JSM.ValueOrDefault(a.ambient,b),c=JSM.ValueOrDefault(a.diffuse,c),d=JSM.ValueOrDefault(a.specular,d),e=JSM.ValueOrDefault(a.shininess,e),f=JSM.ValueOrDefault(a.opacity,f),g=JSM.ValueOrDefault(a.texture,g),h=JSM.ValueOrDefault(a.textureWidth,h),l=JSM.ValueOrDefault(a.textureHeight,l));this.ambient=b;this.diffuse=c;this.specular=d;this.shininess=e;this.opacity=f;this.texture=g;this.textureWidth=h;this.textureHeight=
l};JSM.Materials=function(){this.materials=[];this.defaultMaterial=new JSM.Material};JSM.Materials.prototype.GetMaterial=function(a){return 0>a||a>=this.materials.length?this.defaultMaterial:this.materials[a]};JSM.Materials.prototype.AddMaterial=function(a){this.materials.push(a)};JSM.Materials.prototype.GetDefaultMaterial=function(){return this.defaultMaterial};JSM.Materials.prototype.Count=function(){return this.materials.length};
JSM.AddVertexToBody=function(a,b,c,d){a.AddVertex(new JSM.BodyVertex(new JSM.Coord(b,c,d)))};JSM.AddPolygonToBody=function(a,b){a.AddPolygon(new JSM.BodyPolygon(b))};JSM.CalculateBodyVertexToPolygon=function(a){var b=[],c,d;for(c=0;c<a.VertexCount();c++)b.push([]);var e;for(c=0;c<a.PolygonCount();c++){e=a.GetPolygon(c);for(d=0;d<e.VertexIndexCount();d++)b[e.GetVertexIndex(d)].push(c)}return b};
JSM.CalculateBodyPolygonNormal=function(a,b){var c=a.GetPolygon(b),d=c.VertexIndexCount(),e=new JSM.Vector(0,0,0);if(3<=d){var f,g,h;for(f=0;f<d;f++)g=f,h=(f+1)%d,g=a.GetVertexPosition(c.GetVertexIndex(g)),h=a.GetVertexPosition(c.GetVertexIndex(h)),e.x+=(g.y-h.y)*(g.z+h.z),e.y+=(g.z-h.z)*(g.x+h.x),e.z+=(g.x-h.x)*(g.y+h.y)}return JSM.VectorNormalize(e)};JSM.CalculateBodyPolygonNormals=function(a){var b=[],c;for(c=0;c<a.PolygonCount();c++)b.push(JSM.CalculateBodyPolygonNormal(a,c));return b};
JSM.CalculateBodyVertexNormals=function(a){var b=[],c=JSM.CalculateBodyPolygonNormals(a),d=null,e,f,g,h,l,k,m,n;for(e=0;e<a.PolygonCount();e++)if(h=a.GetPolygon(e),b[e]=[],h.HasCurveGroup()){null===d&&(d=JSM.CalculateBodyVertexToPolygon(a));for(f=0;f<h.VertexIndexCount();f++){l=new JSM.Vector(0,0,0);k=0;m=d[h.GetVertexIndex(f)];for(g=0;g<m.length;g++)n=a.GetPolygon(m[g]),n.GetCurveGroup()===h.GetCurveGroup()&&(l=JSM.CoordAdd(l,c[m[g]]),k++);l=JSM.VectorMultiply(l,1/k);l=JSM.VectorNormalize(l);b[e].push(l)}}else{g=
c[e];for(f=0;f<h.VertexIndexCount();f++)b[e].push(new JSM.Vector(g.x,g.y,g.z))}return b};JSM.MakeBodyInsideOut=function(a){var b,c,d,e,f;for(b=0;b<a.PolygonCount();b++){d=a.GetPolygon(b);f=d.vertices.slice(0);e=f.length;d.vertices=[];for(c=0;c<e;c++)d.vertices.push(f[e-c-1])}};
JSM.SoftMoveBodyVertex=function(a,b,c,d,e){b=a.GetVertex(b).position;var f=JSM.GetGaussianCParameter(c,e,0,1E-5),g,h,l;for(g=0;g<a.VertexCount();g++)h=JSM.CoordDistance(b,a.GetVertex(g).position),JSM.IsGreater(h,c)||(h=JSM.GetGaussianValue(h,e,0,f),l=a.GetVertex(g).position,a.GetVertex(g).position=JSM.CoordOffset(l,d,h))};
JSM.CalculatePolygonCentroid=function(a,b){var c=a.GetPolygon(b),d=c.VertexIndexCount(),e=new JSM.Coord(0,0,0),f;for(f=0;f<d;f++)e=JSM.CoordAdd(e,a.GetVertexPosition(c.GetVertexIndex(f)));return e=JSM.VectorMultiply(e,1/d)};
JSM.TriangulateWithCentroids=function(a){var b=new JSM.Body,c,d;for(c=0;c<a.VertexCount();c++)d=a.GetVertex(c).position,b.AddVertex(new JSM.BodyVertex(new JSM.Coord(d.x,d.y,d.z)));var e,f,g,h,l;for(c=0;c<a.PolygonCount();c++){d=JSM.CalculatePolygonCentroid(a,c);l=b.VertexCount();b.AddVertex(new JSM.BodyVertex(new JSM.Coord(d.x,d.y,d.z)));f=a.GetPolygon(c);g=f.VertexIndexCount();for(d=0;d<g;d++)e=f.GetVertexIndex(d),h=f.GetVertexIndex(d<g-1?d+1:0),e=new JSM.BodyPolygon([e,h,l]),e.material=f.material,
e.curved=f.curved,b.AddPolygon(e)}return b};
JSM.TriangulatePolygons=function(a){var b=new JSM.Body,c,d,e;for(c=0;c<a.VertexCount();c++)e=a.GetVertexPosition(c),b.AddVertex(new JSM.BodyVertex(new JSM.Coord(e.x,e.y,e.z)));var f,g;for(c=0;c<a.PolygonCount();c++){f=new JSM.Polygon;g=a.GetPolygon(c);for(d=0;d<g.VertexIndexCount();d++)e=a.GetVertexPosition(g.GetVertexIndex(d)),f.AddVertex(e.x,e.y,e.z);e=JSM.PolygonTriangulate(f);for(d=0;d<e.length;d++)f=e[d],f=new JSM.BodyPolygon([g.GetVertexIndex(f[0]),g.GetVertexIndex(f[1]),g.GetVertexIndex(f[2])]),
f.InheritAttributes(g),b.AddPolygon(f)}return b};JSM.GenerateRandomMaterials=function(a,b,c){var d,e;for(d=0;d<a.PolygonCount();d++)e=void 0!==c&&c?JSM.SeededRandomInt(0,16777215,d+1):JSM.RandomInt(0,16777215),b.AddMaterial(new JSM.Material({ambient:e,diffuse:e})),e=b.Count()-1,a.GetPolygon(d).SetMaterialIndex(e)};JSM.VertInfo=function(){this.edges=[];this.pgons=[]};JSM.EdgeInfo=function(){this.pgon2=this.pgon1=this.vert2=this.vert1=-1};JSM.PolyEdgeInfo=function(){this.index=-1;this.reverse=!1};
JSM.PgonInfo=function(){this.verts=[];this.pedges=[]};JSM.AdjacencyInfo=function(){this.verts=[];this.edges=[];this.pgons=[]};JSM.GetPolyEdgeStartVertex=function(a,b){return a.reverse?b.edges[a.index].vert2:b.edges[a.index].vert1};JSM.GetPolyEdgeEndVertex=function(a,b){return a.reverse?b.edges[a.index].vert1:b.edges[a.index].vert2};
JSM.CalculateAdjacencyInfo=function(a){var b=new JSM.AdjacencyInfo,c,d,e;for(c=0;c<a.VertexCount();c++)d=new JSM.VertInfo,b.verts.push(d);var f,g,h,l,k;for(c=0;c<a.PolygonCount();c++){f=a.GetPolygon(c);e=new JSM.PgonInfo;g=f.VertexIndexCount();for(d=0;d<g;d++){h=f.GetVertexIndex(d);l=f.GetVertexIndex(d<g-1?d+1:0);k=h;var m=l;l=c;for(var n=new JSM.PolyEdgeInfo,p=void 0,q=void 0,p=0;p<b.edges.length;p++)q=b.edges[p],q.vert1===k&&q.vert2===m?(n.index=p,n.reverse=!1):q.vert1===m&&q.vert2===k&&(n.index=
p,n.reverse=!0);-1===n.index?(p=new JSM.EdgeInfo,p.vert1=k,p.vert2=m,p.pgon1=l,p.pgon2=-1,b.edges.push(p),n.index=b.edges.length-1,n.reverse=!1):(k=b.edges[n.index],-1===k.pgon1?k.pgon1=l:k.pgon1!==l&&-1===k.pgon2&&(k.pgon2=l));k=n;e.verts.push(h);e.pedges.push(k);b.verts[h].edges.push(k.index);b.verts[h].pgons.push(c)}b.pgons.push(e)}return b};JSM.IsSolidBody=function(a){a=JSM.CalculateAdjacencyInfo(a);var b,c;for(b=0;b<a.edges.length;b++)if(c=a.edges[b],-1===c.pgon1||-1===c.pgon2)return!1;return!0};
JSM.CheckSolidBody=function(a){a=JSM.CalculateAdjacencyInfo(a);var b,c,d,e,f,g,h,l;for(b=0;b<a.edges.length;b++){d=a.edges[b];if(-1===d.pgon1||-1===d.pgon2)return!1;g=a.pgons[d.pgon1];f=!1;for(c=0;c<g.pedges.length;c++)if(e=g.pedges[c],e.index==b){h=e.reverse;f=!0;break}if(!f)return!1;d=a.pgons[d.pgon2];f=!1;for(c=0;c<d.pedges.length;c++)if(e=d.pedges[c],e.index==b){l=e.reverse;f=!0;break}if(!f||h==l)return!1}return!0};
JSM.CalculatePlanarTextureCoord=function(a,b){var c=new JSM.Coord2D(0,0),d=JSM.VectorNormalize(b.e1),e=JSM.VectorNormalize(b.e2),f=JSM.VectorCross(b.e1,b.e2),f=JSM.GetPlaneFromCoordAndDirection(b.origo,f),e=JSM.GetPlaneFromCoordAndDirection(b.origo,e),d=JSM.GetPlaneFromCoordAndDirection(b.origo,d),f=JSM.ProjectCoordToPlane(a,f);c.x=JSM.CoordPlaneSignedDistance(f,d);c.y=JSM.CoordPlaneSignedDistance(f,e);return c};
JSM.CalculateCubicTextureCoord=function(a,b,c){var d=new JSM.Coord2D(0,0),e=JSM.VectorNormalize(c.e1),f=JSM.VectorNormalize(c.e2),g=JSM.VectorNormalize(c.e3),h=-1,l=0,k,m,n;for(k=0;3>k;k++)0===k?m=e:1===k?m=f:2===k&&(m=g),n=Math.abs(JSM.VectorDot(b,m)),JSM.IsGreater(n,l)&&(h=k,l=n);if(-1===h)return d;b=null;0===h?b=new JSM.CoordSystem(c.origo,f,g,new JSM.Coord(0,0,0)):1===h?b=new JSM.CoordSystem(c.origo,e,g,new JSM.Coord(0,0,0)):2===h&&(b=new JSM.CoordSystem(c.origo,e,f,new JSM.Coord(0,0,0)));return null===
b?d:JSM.CalculatePlanarTextureCoord(a,b)};JSM.CalculateCylindricalTextureCoord=function(a,b,c){var d=new JSM.Coord2D(0,0),e=JSM.VectorNormalize(c.e3);if(JSM.VectorsAreCollinear(e,b))return d=JSM.CalculateCubicTextureCoord(a,b,c),[d,0];b=new JSM.Line(c.origo,e);var f=JSM.ProjectCoordToLine(a,b);b=JSM.CoordSignedDistance(c.origo,f,e);var g=JSM.VectorNormalize(c.e1);a=JSM.CoordSub(a,f);e=JSM.GetVectorsFullAngle(a,g,e);c=JSM.VectorLength(c.e1);d.x=e*c;d.y=b;return[d,e]};
JSM.CalculatePolygonPlanarTextureCoords=function(a,b){var c=[],d=a.GetPolygon(b),e=a.GetTextureProjectionCoords(),f,g;for(f=0;f<d.VertexIndexCount();f++)g=a.GetVertexPosition(d.GetVertexIndex(f)),c.push(JSM.CalculatePlanarTextureCoord(g,e));return c};JSM.CalculatePolygonCubicTextureCoords=function(a,b,c){var d=[];b=a.GetPolygon(b);var e=a.GetTextureProjectionCoords(),f,g;for(f=0;f<b.VertexIndexCount();f++)g=a.GetVertexPosition(b.GetVertexIndex(f)),d.push(JSM.CalculateCubicTextureCoord(g,c,e));return d};
JSM.CalculatePolygonCylindricalTextureCoords=function(a,b,c){var d=[],e=[],f=a.GetPolygon(b);b=a.GetTextureProjectionCoords();var g,h;for(g=0;g<f.VertexIndexCount();g++)h=a.GetVertexPosition(f.GetVertexIndex(g)),h=JSM.CalculateCylindricalTextureCoord(h,c,b),d.push(h[0]),e.push(h[1]);g=JSM.VectorNormalize(b.e3);if(JSM.VectorsAreCollinear(g,c))return d;a=!1;for(g=0;g<e.length;g++){for(c=g+1;c<e.length;c++)if(JSM.IsGreater(Math.abs(e[g]-e[c]),Math.PI)){a=!0;break}if(a)break}if(a){b=JSM.VectorLength(b.e1);
for(g=0;g<e.length;g++)JSM.IsLower(e[g],Math.PI)&&(d[g].x=b*(e[g]+2*Math.PI))}return d};JSM.CalculateBodyPlanarTextureCoords=function(a){var b=[],c;for(c=0;c<a.PolygonCount();c++)b.push(JSM.CalculatePolygonPlanarTextureCoords(a,c));return b};JSM.CalculateBodyCubicTextureCoords=function(a){var b=[],c=JSM.CalculateBodyPolygonNormals(a),d,e;for(d=0;d<a.PolygonCount();d++)e=c[d],b.push(JSM.CalculatePolygonCubicTextureCoords(a,d,e));return b};
JSM.CalculateBodyCylindricalTextureCoords=function(a){var b=[],c=JSM.CalculateBodyPolygonNormals(a),d,e;for(d=0;d<a.PolygonCount();d++)e=c[d],b.push(JSM.CalculatePolygonCylindricalTextureCoords(a,d,e));return b};JSM.CalculateBodyTextureCoords=function(a){var b=[],c=a.GetTextureProjectionType();"Planar"===c?b=JSM.CalculateBodyPlanarTextureCoords(a):"Cubic"===c?b=JSM.CalculateBodyCubicTextureCoords(a):"Cylindrical"===c&&(b=JSM.CalculateBodyCylindricalTextureCoords(a));return b};
JSM.CutBodyByPlane=function(a,b){function c(a,b,c){function d(a){q.push(new JSM.Coord(p.x,p.y,p.z));r.push(a)}function e(c,d){s=JSM.VectorNormalize(JSM.CoordSub(a[d],a[c]));M=new JSM.Line(a[c],s);w=JSM.LinePlaneIntersection(M,b);q.push(new JSM.Coord(w.x,w.y,w.z));r.push(-1)}var f=void 0!==c&&null!==c,g=a.length,h=[],k=[],l=!1,m,n,p;for(m=0;m<g;m++)p=a[m],n=JSM.CoordPlanePosition(p,b),k.push("CoordAtBackOfPlane"!==n),0<m&&k[m-1]!==k[m]&&(l=!0);if(!l){if(!1===k[0])return h;for(m=0;m<g;m++)p=a[m],h.push(new JSM.Coord(p.x,
p.y,p.z)),f&&c.push(m);return h}var q=[],r=[],s,M,w;for(m=0;m<g;m++)l=m-1,n=m,0===m&&(l=g-1),p=a[n],k[n]?(k[l]||e(l,n),d(n)):k[l]&&e(l,n);for(m=0;m<q.length;m++)g=q[m],k=h[h.length-1],0===m||!JSM.CoordIsEqual(k,g)?(h.push(new JSM.Coord(g.x,g.y,g.z)),f&&(g=r[m],c.push(g))):f&&(g=r[m],k=r[m-1],-1!==g?c[c.length-1]=g:-1!==k&&(c[c.length-1]=k));return h}function d(a){var b=-1,c;for(c=s;c<e.VertexCount();c++)if(JSM.CoordIsEqual(e.GetVertexPosition(c),a)){b=c;break}-1===b&&(b=e.AddVertex(new JSM.BodyVertex(new JSM.Coord(a.x,
a.y,a.z))));return b}var e=new JSM.Body,f=[],g=[],h=[],l=[],k,m,n,p,q;for(k=0;k<a.PolygonCount();k++){n=a.GetPolygon(k);p=[];for(m=0;m<n.VertexIndexCount();m++)q=a.GetVertexPosition(n.GetVertexIndex(m)),p.push(new JSM.Coord(q.x,q.y,q.z));q=[];p=c(p,b,q);for(m=0;m<q.length;m++)-1!==q[m]&&(h[n.GetVertexIndex(q[m])]=!0);f.push(p);g.push(q)}var r;for(k=0;k<a.VertexCount();k++)h[k]&&(r=a.GetVertexPosition(k),l[k]=e.AddVertex(new JSM.BodyVertex(new JSM.Coord(r.x,r.y,r.z))));var s=e.VertexCount();for(k=
0;k<a.PolygonCount();k++)if(n=a.GetPolygon(k),p=f[k],q=g[k],0!==q.length){h=[];for(m=0;m<q.length;m++)-1!==q[m]?h.push(l[n.GetVertexIndex(q[m])]):(r=p[m],h.push(d(r)));m=new JSM.BodyPolygon(h);m.InheritAttributes(n);e.AddPolygon(m)}return e};
JSM.GenerateRectangle=function(a,b){var c=new JSM.Body,d=a/2,e=b/2;c.AddVertex(new JSM.BodyVertex(new JSM.Coord(-d,-e,0)));c.AddVertex(new JSM.BodyVertex(new JSM.Coord(d,-e,0)));c.AddVertex(new JSM.BodyVertex(new JSM.Coord(d,e,0)));c.AddVertex(new JSM.BodyVertex(new JSM.Coord(-d,e,0)));c.AddPolygon(new JSM.BodyPolygon([0,1,2,3]));c.SetCubicTextureProjection(new JSM.Coord(-d,-e,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return c};
JSM.GenerateCuboid=function(a,b,c){var d=new JSM.Body;a/=2;b/=2;c/=2;d.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,-b,-c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,-b,-c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,-b,c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,-b,c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,b,-c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,b,-c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,b,c)));d.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,
b,c)));d.AddPolygon(new JSM.BodyPolygon([0,1,2,3]));d.AddPolygon(new JSM.BodyPolygon([1,5,6,2]));d.AddPolygon(new JSM.BodyPolygon([5,4,7,6]));d.AddPolygon(new JSM.BodyPolygon([4,0,3,7]));d.AddPolygon(new JSM.BodyPolygon([0,4,5,1]));d.AddPolygon(new JSM.BodyPolygon([3,2,6,7]));d.SetCubicTextureProjection(new JSM.Coord(-a,-b,-c),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return d};
JSM.GenerateCuboidSides=function(a,b,c,d){var e=new JSM.Body;a/=2;b/=2;c/=2;e.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,-b,-c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,-b,-c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,-b,c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,-b,c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,b,-c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,b,-c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(a,b,c)));e.AddVertex(new JSM.BodyVertex(new JSM.Coord(-a,
b,c)));d[0]&&e.AddPolygon(new JSM.BodyPolygon([0,1,2,3]));d[1]&&e.AddPolygon(new JSM.BodyPolygon([1,5,6,2]));d[2]&&e.AddPolygon(new JSM.BodyPolygon([5,4,7,6]));d[3]&&e.AddPolygon(new JSM.BodyPolygon([4,0,3,7]));d[4]&&e.AddPolygon(new JSM.BodyPolygon([0,4,5,1]));d[5]&&e.AddPolygon(new JSM.BodyPolygon([3,2,6,7]));e.SetCubicTextureProjection(new JSM.Coord(-a,-b,-c),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return e};
JSM.GenerateSegmentedRectangle=function(a,b,c,d){var e=new JSM.Body,f=a/2,g=b/2,h=a/c,l=b/d;(function(){var a,b,n;for(a=0;a<=d;a++)for(b=0;b<=c;b++)n=new JSM.Coord(b*h-f,a*l-g,0),e.AddVertex(new JSM.BodyVertex(n))})();(function(){var a,b,f,g,h,l;for(b=0;b<d;b++)for(a=0;a<c;a++)f=b*(c+1)+a,g=f+1,h=f+c+1,l=h+1,e.AddPolygon(new JSM.BodyPolygon([f,g,l,h]))})();return e};
JSM.GenerateSegmentedCuboid=function(a,b,c,d){function e(a){var b=0;0<a&&a<=d&&(b=(d+1)*(d+1)+(a-1)*4*d);return b}function f(a){var b=[],c=e(a);if(0===a||a===d){for(a=0;a<=d;a++)b.push(c+a);for(a=1;a<=d;a++)b.push(c+(a+1)*d+a);for(a=d-1;0<=a;a--)b.push(c+(d+1)*d+a);for(a=d-1;0<a;a--)b.push(c+a*(d+1))}else if(0<a&&a<d){for(a=0;a<=d;a++)b.push(c+a);for(a=1;a<d;a++)b.push(c+d+2*a);for(a=d;0<=a;a--)b.push(c+3*d+a-1);for(a=d-1;0<a;a--)b.push(c+d+2*a-1)}return b}function g(a){var b,c,e=a*r;if(0===a||a===
d)for(a=0;a<=d;a++)for(b=0;b<=d;b++)c=new JSM.Coord(b*p-k,a*q-m,e-n),l.AddVertex(new JSM.BodyVertex(c));else if(0<a&&a<d)for(a=0;a<=d;a++)for(b=0;b<=d;b++)if(0===a||a===d||0===b||b===d)c=new JSM.Coord(b*p-k,a*q-m,e-n),l.AddVertex(new JSM.BodyVertex(c))}function h(a){var b,c,f,g,h,k;if(0===a||a===d){var m=e(a);for(b=0;b<d;b++)for(c=0;c<d;c++)f=m+b*(d+1)+c,g=f+1,h=f+d+1,k=h+1,0===a?l.AddPolygon(new JSM.BodyPolygon([f,h,k,g])):l.AddPolygon(new JSM.BodyPolygon([f,g,k,h]))}if(0<a&&a<=d){c=s[a-1];a=s[a];
for(b=0;b<4*d;b++)f=c[b],h=a[b],b<4*d-1?(g=c[b+1],k=a[b+1]):(g=c[0],k=a[0]),l.AddPolygon(new JSM.BodyPolygon([f,g,k,h]))}}var l=new JSM.Body,k=a/2,m=b/2,n=c/2,p=a/d,q=b/d,r=c/d;for(a=0;a<=d;a++)g(a);var s=[];for(a=0;a<=d;a++)s.push(f(a));for(a=0;a<=d;a++)h(a);return l};
JSM.GenerateCircle=function(a,b){var c=new JSM.Body,d=JSM.GenerateCirclePoints(a,b),e;for(e=0;e<d.length;e++)c.AddVertex(new JSM.BodyVertex(d[e]));d=new JSM.BodyPolygon([]);for(e=0;e<b;e++)d.AddVertexIndex(e);c.AddPolygon(d);c.SetCylindricalTextureProjection(new JSM.Coord(0,0,0),a,new JSM.Coord(1,0,0),new JSM.Coord(0,0,1));return c};
JSM.GenerateSphere=function(a,b,c){var d=new JSM.Body,e=2*b,f=d.AddVertex(new JSM.BodyVertex(JSM.SphericalToCartesian(a,0,0))),g=Math.PI/b,h=g,l,k,m;for(l=1;l<b;l++){for(k=m=0;k<e;k++)d.AddVertex(new JSM.BodyVertex(JSM.SphericalToCartesian(a,h,m))),m+=g;h+=g}a=d.AddVertex(new JSM.BodyVertex(JSM.SphericalToCartesian(-a,0,0)));var n,p;for(l=1;l<=b;l++)if(1===l){g=1;for(k=0;k<e;k++)h=g+k,m=h+1,k===e-1&&(m=g),h=new JSM.BodyPolygon([h,m,f]),c&&h.SetCurveGroup(0),d.AddPolygon(h)}else if(l<b){g=(l-1)*e+
1;for(k=0;k<e;k++)h=g+k,m=h+1,n=h-e,p=n+1,k===e-1&&(m=g,p=g-e),h=new JSM.BodyPolygon([h,m,p,n]),c&&h.SetCurveGroup(0),d.AddPolygon(h)}else if(l===b){g=(l-2)*e+1;for(k=0;k<e;k++)h=g+k,m=h+1,k===e-1&&(m=g),h=new JSM.BodyPolygon([h,a,m]),c&&h.SetCurveGroup(0),d.AddPolygon(h)}d.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return d};
JSM.GenerateTriangulatedSphere=function(a,b,c){var d;d=new JSM.Body;var e=(1+Math.sqrt(5))/2;JSM.AddVertexToBody(d,0,1,+e);JSM.AddVertexToBody(d,0,1,-e);JSM.AddVertexToBody(d,0,-1,+e);JSM.AddVertexToBody(d,0,-1,-e);JSM.AddVertexToBody(d,1,+e,0);JSM.AddVertexToBody(d,1,-e,0);JSM.AddVertexToBody(d,-1,+e,0);JSM.AddVertexToBody(d,-1,-e,0);JSM.AddVertexToBody(d,+e,0,1);JSM.AddVertexToBody(d,-e,0,1);JSM.AddVertexToBody(d,+e,0,-1);JSM.AddVertexToBody(d,-e,0,-1);JSM.AddPolygonToBody(d,[0,2,8]);JSM.AddPolygonToBody(d,
[0,4,6]);JSM.AddPolygonToBody(d,[0,6,9]);JSM.AddPolygonToBody(d,[0,8,4]);JSM.AddPolygonToBody(d,[0,9,2]);JSM.AddPolygonToBody(d,[1,3,11]);JSM.AddPolygonToBody(d,[1,4,10]);JSM.AddPolygonToBody(d,[1,6,4]);JSM.AddPolygonToBody(d,[1,10,3]);JSM.AddPolygonToBody(d,[1,11,6]);JSM.AddPolygonToBody(d,[2,5,8]);JSM.AddPolygonToBody(d,[2,7,5]);JSM.AddPolygonToBody(d,[2,9,7]);JSM.AddPolygonToBody(d,[3,5,7]);JSM.AddPolygonToBody(d,[3,7,11]);JSM.AddPolygonToBody(d,[3,10,5]);JSM.AddPolygonToBody(d,[4,8,10]);JSM.AddPolygonToBody(d,
[6,11,9]);JSM.AddPolygonToBody(d,[5,10,8]);JSM.AddPolygonToBody(d,[7,9,11]);for(var e=JSM.VectorLength(d.GetVertexPosition(0)),f=a/e,g,h,e=0;e<d.VertexCount();e++)h=d.GetVertex(e),h.SetPosition(JSM.VectorMultiply(h.GetPosition(),f));for(var l,k,m,n,f=0;f<b;f++){g=d;d=new JSM.Body;h=JSM.CalculateAdjacencyInfo(g);for(e=0;e<h.verts.length;e++)l=g.GetVertexPosition(e),JSM.AddVertexToBody(d,l.x,l.y,l.z);l=[];for(e=0;e<h.edges.length;e++)k=h.edges[e],k=JSM.MidCoord(g.GetVertexPosition(k.vert1),g.GetVertexPosition(k.vert2)),
k=JSM.VectorMultiply(JSM.VectorNormalize(k),a),l.push(d.AddVertex(new JSM.BodyVertex(k)));for(e=0;e<h.pgons.length;e++){k=h.pgons[e];m=[];for(g=0;g<k.pedges.length;g++)n=k.pedges[g],m.push(JSM.GetPolyEdgeStartVertex(n,h)),m.push(l[n.index]);JSM.AddPolygonToBody(d,[m[0],m[1],m[5]]);JSM.AddPolygonToBody(d,[m[1],m[2],m[3]]);JSM.AddPolygonToBody(d,[m[3],m[4],m[5]]);JSM.AddPolygonToBody(d,[m[1],m[3],m[5]])}}if(c)for(e=0;e<d.PolygonCount();e++)d.GetPolygon(e).SetCurveGroup(0);d.SetCubicTextureProjection(new JSM.Coord(0,
0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return d};
JSM.GenerateCylinder=function(a,b,c,d,e){var f=new JSM.Body,g=2*Math.PI,h=2*Math.PI/c,l;for(l=0;l<c;l++)f.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(a,b/2,g))),f.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(a,-b/2,g))),g-=h;for(l=0;l<c;l++)g=2*l,h=g+2,l===c-1&&(h=0),g=new JSM.BodyPolygon([g,h,h+1,g+1]),e&&g.SetCurveGroup(0),f.AddPolygon(g);if(d){d=new JSM.BodyPolygon([]);e=new JSM.BodyPolygon([]);for(l=0;l<c;l++)d.AddVertexIndex(2*(c-l-1)),e.AddVertexIndex(2*l+1);f.AddPolygon(d);
f.AddPolygon(e)}f.SetCylindricalTextureProjection(new JSM.Coord(0,0,-(b/2)),a,new JSM.Coord(1,0,0),new JSM.Coord(0,0,1));return f};
JSM.GeneratePie=function(a,b,c,d,e,f){var g=new JSM.Body,h=c,l=c/(d-1);g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(0,b/2,0)));g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(0,-b/2,0)));for(c=0;c<d;c++)g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(a,b/2,h))),g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(a,-b/2,h))),h-=l;for(c=0;c<=d;c++)h=2*c,l=h+2,c===d&&(l=0),h=new JSM.BodyPolygon([h,l,l+1,h+1]),f&&(0<c&&c<d)&&h.SetCurveGroup(0),g.AddPolygon(h);if(e){e=
new JSM.BodyPolygon([]);f=new JSM.BodyPolygon([]);for(c=0;c<=d;c++)e.AddVertexIndex(2*(d-c)),f.AddVertexIndex(2*c+1);g.AddPolygon(e);g.AddPolygon(f)}g.SetCylindricalTextureProjection(new JSM.Coord(0,0,-(b/2)),a,new JSM.Coord(1,0,0),new JSM.Coord(0,0,1));return g};
JSM.GenerateCone=function(a,b,c,d,e,f){var g=new JSM.Body,h=JSM.IsZero(a),l=JSM.IsZero(b),k=2*Math.PI,m=2*Math.PI/d;h&&g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(0,c/2,0)));var n;for(n=0;n<d;n++)h||g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(a,c/2,k))),l||g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(b,-c/2,k))),k-=m;l&&g.AddVertex(new JSM.BodyVertex(JSM.CylindricalToCartesian(0,-c/2,0)));for(n=0;n<d;n++)h?(k=n+1,m=k+1,n===d-1&&(m=1),k=new JSM.BodyPolygon([0,
m,k])):l?(k=n,m=k+1,n===d-1&&(m=0),k=new JSM.BodyPolygon([k,m,d])):(k=2*n,m=k+2,n===d-1&&(m=0),k=new JSM.BodyPolygon([k,m,m+1,k+1])),f&&k.SetCurveGroup(0),g.AddPolygon(k);if(e)if(h){f=new JSM.BodyPolygon([]);for(n=0;n<d;n++)f.AddVertexIndex(n+1);g.AddPolygon(f)}else if(l){e=new JSM.BodyPolygon([]);for(n=0;n<d;n++)e.AddVertexIndex(d-n-1);g.AddPolygon(e)}else{e=new JSM.BodyPolygon([]);f=new JSM.BodyPolygon([]);for(n=0;n<d;n++)e.AddVertexIndex(2*(d-n-1)),f.AddVertexIndex(2*n+1);g.AddPolygon(e);g.AddPolygon(f)}g.SetCylindricalTextureProjection(new JSM.Coord(0,
0,-(c/2)),(a+b)/2,new JSM.Coord(1,0,0),new JSM.Coord(0,0,1));return g};
JSM.GeneratePrism=function(a,b,c,d){var e=new JSM.Body,f=a.length,g;for(g=0;g<f;g++)e.AddVertex(new JSM.BodyVertex(a[g])),e.AddVertex(new JSM.BodyVertex(JSM.CoordOffset(a[g],b,c)));var h;for(g=0;g<f;g++)c=2*g,h=c+2,g===f-1&&(h=0),e.AddPolygon(new JSM.BodyPolygon([c,h,h+1,c+1]));if(d){d=new JSM.BodyPolygon([]);c=new JSM.BodyPolygon([]);for(g=0;g<f;g++)d.AddVertexIndex(2*g+1),c.AddVertexIndex(2*(f-g-1));e.AddPolygon(d);e.AddPolygon(c)}f=JSM.VectorNormalize(JSM.CoordSub(a[1],a[0]));a=new JSM.Coord(a[0].x,
a[0].y,a[0].z);b=JSM.VectorNormalize(b);f=JSM.VectorCross(b,f);g=JSM.VectorCross(f,b);e.SetCubicTextureProjection(a,g,f,b);return e};JSM.GenerateCurvedPrism=function(a,b,c,d,e){c=JSM.GeneratePrism(a,c,d,e);if(void 0===b||null===b||a.length!=b.length)return c;for(d=0;d<a.length;d++)e=b[d],c.GetPolygon(d).SetCurveGroup(e);return c};
JSM.GeneratePrismWithHole=function(a,b,c,d){function e(){var b=0,c=[],d;for(d=0;d<a.length;d++)null===a[d]&&(b+=1),c.push(d-b);var b=JSM.CreatePolygonWithHole(a),e=new JSM.Polygon,g;for(d=0;d<b.length;d++)g=a[b[d]],e.AddVertex(g.x,g.y,g.z);g=JSM.PolygonTriangulate(e);var h,l,x;for(d=0;d<g.length;d++){h=g[d];l=new JSM.BodyPolygon([]);x=new JSM.BodyPolygon([]);for(e=0;3>e;e++)l.AddVertexIndex(2*c[b[h[e]]]+1),x.AddVertexIndex(2*c[b[h[3-e-1]]]);f.AddPolygon(l);f.AddPolygon(x)}}var f=new JSM.Body;(function(){var d;
for(d=0;d<a.length;d++)null!==a[d]&&(f.AddVertex(new JSM.BodyVertex(a[d])),f.AddVertex(new JSM.BodyVertex(JSM.CoordOffset(a[d],b,c))))})();(function(){var b=0,c=[];c.push(0);var d;for(d=0;d<a.length;d++)null===a[d]&&(c.push(d-b),b+=1);c.push(d-b);for(b=0;b<c.length-1;b++){var e=d=void 0,g=void 0,h=c[b],l=c[b+1];for(d=h;d<l;d++)e=2*d,g=e+2,d===l-1&&(g=2*h),f.AddPolygon(new JSM.BodyPolygon([e,g,g+1,e+1]))}})();d&&e();var g=JSM.VectorNormalize(JSM.CoordSub(a[1],a[0]));d=new JSM.Coord(a[0].x,a[0].y,a[0].z);
var h=JSM.VectorNormalize(b),g=JSM.VectorCross(h,g),l=JSM.VectorCross(g,h);f.SetCubicTextureProjection(d,l,g,h);return f};JSM.GenerateCurvedPrismWithHole=function(a,b,c,d,e){c=JSM.GeneratePrismWithHole(a,c,d,e);if(void 0===b||null===b||a.length!=b.length)return c;d=0;var f;for(e=0;e<a.length;e++)f=b[e],null!==f&&(c.GetPolygon(d).SetCurveGroup(f),d++);return c};
JSM.GeneratePrismShell=function(a,b,c,d,e){var f=new JSM.Body,g=a.length,h;for(h=0;h<g;h++)f.AddVertex(new JSM.BodyVertex(a[h]));h=new JSM.Polygon;h.vertices=a;d=JSM.OffsetPolygonContour(h,d).vertices;for(h=0;h<g;h++)f.AddVertex(new JSM.BodyVertex(d[h]));var l;for(h=0;h<g;h++)l=JSM.CoordOffset(a[h],b,c),f.AddVertex(new JSM.BodyVertex(l));for(h=0;h<g;h++)l=JSM.CoordOffset(d[h],b,c),f.AddVertex(new JSM.BodyVertex(l));var k;for(h=0;h<g;h++)c=h,d=c+1,l=c+2*g,k=l+1,h===g-1&&(d=0,k=2*g),f.AddPolygon(new JSM.BodyPolygon([c,
d,k,l])),f.AddPolygon(new JSM.BodyPolygon([c+g,l+g,k+g,d+g]));if(e)for(h=0;h<g;h++)c=h,d=c+1,l=h+g,k=l+1,h===g-1&&(d=0,k=g),f.AddPolygon(new JSM.BodyPolygon([c,l,k,d])),f.AddPolygon(new JSM.BodyPolygon([c+2*g,d+2*g,k+2*g,l+2*g]));e=JSM.VectorNormalize(JSM.CoordSub(a[1],a[0]));a=new JSM.Coord(a[0].x,a[0].y,a[0].z);b=JSM.VectorNormalize(b);e=JSM.VectorCross(b,e);g=JSM.VectorCross(e,b);f.SetCubicTextureProjection(a,g,e,b);return f};
JSM.GenerateCylinderShell=function(a,b,c,d,e,f){for(var g=new JSM.Vector(0,0,1),h=-b/2,l=[],k=2*Math.PI/d,m,n=0,n=0;n<d;n++)m=n*k,m=JSM.PolarToCartesian(a,m),l.push(new JSM.Coord(m.x,m.y,h));a=JSM.GeneratePrismShell(l,g,b,c,e);if(f)for(f=0;f<d;f++)a.GetPolygon(2*f).SetCurveGroup(0),a.GetPolygon(2*f+1).SetCurveGroup(0);return a};
JSM.GenerateLineShell=function(a,b,c,d,e,f){var g=new JSM.Body,h=a.length,l=[],k,m,n,p,q,r;for(k=0;k<h;k++)0===k||k===h-1?q=Math.PI/2:(m=k-1,n=k,p=k+1,r=JSM.CoordSub(a[p],a[n]),q=JSM.CoordSub(a[m],a[n]),q=JSM.GetVectorsAngle(r,q)/2,"Clockwise"===JSM.CoordTurnType(a[m],a[n],a[p],b)&&(q=Math.PI-q)),l.push(q);r=new JSM.Vector(0,0,1);m=[];var s;for(k=0;k<h;k++)n=k,k===h-1?s=JSM.CoordSub(a[n-1],a[n]):(p=(k+1)%h,s=JSM.CoordSub(a[n],a[p])),q=l[n],p=d/Math.sin(q),p=JSM.CoordOffset(a[n],s,p),p=JSM.CoordRotate(p,
r,-(Math.PI-q),a[n]),m.push(p);for(k=0;k<h;k++)g.AddVertex(new JSM.BodyVertex(a[k]));for(k=0;k<h;k++)g.AddVertex(new JSM.BodyVertex(m[k]));for(k=0;k<h;k++)n=JSM.CoordOffset(a[k],b,c),g.AddVertex(new JSM.BodyVertex(n));for(k=0;k<h;k++)n=JSM.CoordOffset(m[k],b,c),g.AddVertex(new JSM.BodyVertex(n));for(k=0;k<h-1;k++)n=k,p=n+1,c=n+2*h,d=c+1,g.AddPolygon(new JSM.BodyPolygon([n,p,d,c])),g.AddPolygon(new JSM.BodyPolygon([n+h,c+h,d+h,p+h]));e&&(n=0,g.AddPolygon(new JSM.BodyPolygon([n,n+2*h,n+3*h,n+h])),n=
h-1,g.AddPolygon(new JSM.BodyPolygon([n,n+h,n+3*h,n+2*h])));if(f)for(k=0;k<h-1;k++)n=k,p=n+1,c=k+h,d=c+1,g.AddPolygon(new JSM.BodyPolygon([n,c,d,p])),g.AddPolygon(new JSM.BodyPolygon([n+2*h,p+2*h,d+2*h,c+2*h]));e=JSM.VectorNormalize(JSM.CoordSub(a[1],a[0]));a=new JSM.Coord(a[0].x,a[0].y,a[0].z);b=JSM.VectorNormalize(b);e=JSM.VectorCross(b,e);f=JSM.VectorCross(e,b);g.SetCubicTextureProjection(a,f,e,b);return g};
JSM.GenerateTorus=function(a,b,c,d,e){var f=new JSM.Body,g=0,h=2*Math.PI/d,l=[],k,m;for(k=0;k<d;k++)m=JSM.PolarToCartesian(b,g),m=new JSM.Coord(m.x+a,0,m.y),l.push(m),g+=h;b=new JSM.Coord(0,0,1);g=new JSM.Coord(0,0,0);h=2*Math.PI/c;for(k=0;k<c;k++)for(a=0;a<d;a++)m=JSM.CoordRotate(l[a],b,k*h,g),f.AddVertex(new JSM.BodyVertex(m));for(k=0;k<c;k++){new JSM.BodyPolygon([]);for(a=0;a<d;a++)h=k*d+a,b=h+d,l=h+1,g=b+1,a===d-1&&(l=k*d,g=(k+1)*d),k===c-1&&(b=a,g=a+1,a===d-1&&(g=0)),h=new JSM.BodyPolygon([h,
b,g,l]),e&&h.SetCurveGroup(0),f.AddPolygon(h)}f.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return f};
JSM.GeneratePolyTorus=function(a,b,c,d){var e=new JSM.Body,f=a.length,g=2*Math.PI/f,h=[],l;for(l=0;l<f;l++)g=a[l],g=new JSM.Coord(g.x+b,0,g.y),h.push(g);b=new JSM.Coord(0,0,1);var k=new JSM.Coord(0,0,0),g=2*Math.PI/c,m;for(l=0;l<c;l++)for(a=0;a<f;a++)m=JSM.CoordRotate(h[a],b,l*g,k),e.AddVertex(new JSM.BodyVertex(m));for(l=0;l<c;l++){new JSM.BodyPolygon([]);for(a=0;a<f;a++)h=l*f+a,b=h+f,g=h+1,k=b+1,a===f-1&&(g=l*f,k=(l+1)*f),l===c-1&&(b=a,k=a+1,a===f-1&&(k=0)),h=new JSM.BodyPolygon([h,b,k,g]),d&&h.SetCurveGroup(a),
e.AddPolygon(h)}e.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return e};
JSM.GenerateRuledFromSectors=function(a,b,c,d,e){var f=new JSM.Body,g=[],h=[];JSM.GetSectorSegmentation(a,c,g);JSM.GetSectorSegmentation(b,c,h);b=[];a=[];JSM.GetRuledMesh(g,h,d,b,a);for(d=0;d<b.length;d++)f.AddVertex(new JSM.BodyVertex(b[d]));for(d=0;d<a.length;d++)g=a[d],g=new JSM.BodyPolygon(g),e&&g.SetCurveGroup(0),f.AddPolygon(g);f.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return f};
JSM.GenerateGrid=function(a,b,c,d,e){var f=new JSM.Sector(new JSM.Coord(0,0,0),new JSM.Coord(a,0,0));a=new JSM.Sector(new JSM.Coord(0,b,0),new JSM.Coord(a,b,0));return JSM.GenerateRuledFromSectors(f,a,c,d,e)};JSM.GenerateSquareGrid=function(a,b,c){return JSM.GenerateGrid(a,a,b,b,c)};
JSM.GenerateRuledFromSectorsWithHeight=function(a,b,c,d,e,f){var g=new JSM.Body,h=[],l=[];JSM.GetSectorSegmentation(a,c,h);JSM.GetSectorSegmentation(b,c,l);b=[];a=[];JSM.GetRuledMesh(h,l,d,b,a);for(h=0;h<b.length;h++)g.AddVertex(new JSM.BodyVertex(b[h]));for(var k,h=0;h<a.length;h++)k=a[h],k=new JSM.BodyPolygon(k),e&&k.SetCurveGroup(0),g.AddPolygon(k);l=g.VertexCount();for(h=0;h<b.length;h++)k=b[h],k=new JSM.Coord(k.x,k.y,k.z),k.z-=f,g.AddVertex(new JSM.BodyVertex(k));for(h=0;h<a.length;h++){k=a[h];
b=[];for(f=k.length-1;0<=f;f--)b.push(k[f]+l);k=new JSM.BodyPolygon(b);e&&k.SetCurveGroup(0);g.AddPolygon(k)}for(h=0;h<d;h++)e=h+l,f=e+1,a=e-l,b=a+1,k=new JSM.BodyPolygon([e,f,b,a]),g.AddPolygon(k);for(h=0;h<d;h++)e=h+c*(d+1)+l,f=e+1,a=e-l,b=a+1,k=new JSM.BodyPolygon([e,a,b,f]),g.AddPolygon(k);for(h=0;h<c;h++)e=h*(d+1)+l,f=e+d+1,a=e-l,b=a+d+1,k=new JSM.BodyPolygon([e,a,b,f]),g.AddPolygon(k);for(h=0;h<c;h++)e=(h+1)*d+h+l,f=e+d+1,a=e-l,b=a+d+1,k=new JSM.BodyPolygon([e,f,b,a]),g.AddPolygon(k);g.SetCubicTextureProjection(new JSM.Coord(0,
0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return g};JSM.GenerateRuledFromCoords=function(a,b,c,d){var e=new JSM.Body,f=[],g=[];JSM.GetRuledMesh(a,b,c,f,g);for(a=0;a<f.length;a++)e.AddVertex(new JSM.BodyVertex(f[a]));for(a=0;a<g.length;a++)f=g[a],f=new JSM.BodyPolygon(f),d&&f.SetCurveGroup(0),e.AddPolygon(f);e.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return e};
JSM.GenerateRevolved=function(a,b,c,d,e,f){var g=new JSM.Body,h=JSM.IsEqual(c,2*Math.PI),l=a.length,k=c/d;c=JSM.CoordSub(b.end,b.beg);var m,n,p;for(m=0;m<l;m++)for(n=0;n<=d;n++)h&&n===d||(p=JSM.CoordRotate(a[m],c,n*k,b.beg),g.AddVertex(new JSM.BodyVertex(p)));var q,r;for(m=0;m<l-1;m++)for(n=0;n<d;n++)k=m*(d+1)+n,p=k+d+1,q=k+1,r=p+1,h&&(k=m*d+n,p=k+d,q=k+1,r=p+1,n===d-1&&(q=m*d,r=(m+1)*d)),k=new JSM.BodyPolygon([k,q,r,p]),f&&k.SetCurveGroup(m),g.AddPolygon(k);if(h&&e){e=new JSM.BodyPolygon([]);f=new JSM.BodyPolygon([]);
for(m=0;m<d;m++)e.AddVertexIndex(d*(l-1)+m),f.AddVertexIndex(d-m-1);g.AddPolygon(e);g.AddPolygon(f)}e=new JSM.Line(b.beg,JSM.VectorNormalize(c));for(m=d=0;m<l;m++)f=JSM.ProjectCoordToLine(a[m],e),d+=JSM.CoordDistance(f,a[m]);d/=l;b=new JSM.Coord(b.beg.x,b.beg.y,b.beg.z);l=JSM.VectorNormalize(c);c=new JSM.Line(b,c);c=JSM.ProjectCoordToLine(a[0],c);a=JSM.VectorNormalize(JSM.CoordSub(a[0],c));g.SetCylindricalTextureProjection(b,d,a,l);return g};
JSM.GenerateTube=function(a,b){var c=new JSM.Body,d=a.length,e=a[0].length,f,g;for(g=0;g<e;g++)for(f=0;f<d;f++)c.AddVertex(new JSM.BodyVertex(a[f][g]));var h,l;for(g=0;g<d-1;g++)for(f=0;f<e;f++)h=g+d*f,l=h+d,f===e-1&&(l=g),c.AddPolygon(new JSM.BodyPolygon([h,l,l+1,h+1]));if(b){g=new JSM.BodyPolygon([]);h=new JSM.BodyPolygon([]);for(f=0;f<e;f++)g.AddVertexIndex(d*f+d-1);for(f=e-1;0<=f;f--)h.AddVertexIndex(d*f);c.AddPolygon(g);c.AddPolygon(h)}c.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,
0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return c};JSM.GenerateFunctionSurface=function(a,b,c,d,e){var f=new JSM.Sector(new JSM.Coord(b.x,b.y,0),new JSM.Coord(c.x,b.y,0));b=new JSM.Sector(new JSM.Coord(b.x,c.y,0),new JSM.Coord(c.x,c.y,0));d=JSM.GenerateRuledFromSectors(f,b,d,d,e);for(e=0;e<d.VertexCount();e++)f=d.GetVertexPosition(e),f.z=a(f.x,f.y);d.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return d};
JSM.GenerateFunctionSurfaceSolid=function(a,b,c,d,e,f){var g=new JSM.Sector(new JSM.Coord(c.x,b.y,0),new JSM.Coord(b.x,b.y,0));b=new JSM.Sector(new JSM.Coord(c.x,c.y,0),new JSM.Coord(b.x,c.y,0));e=JSM.GenerateRuledFromSectorsWithHeight(g,b,d,d,e,f);g=(d+1)*(d+1);for(d=0;d<g;d++)f=e.GetVertexPosition(d),f.z=a(f.x,f.y);e.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return e};
JSM.Camera=function(a,b,c,d,e,f){this.eye=JSM.ValueOrDefault(a,new JSM.Coord(1,1,1));this.center=JSM.ValueOrDefault(b,new JSM.Coord(0,0,0));this.up=JSM.ValueOrDefault(c,new JSM.Vector(0,0,1));this.fieldOfView=JSM.ValueOrDefault(d,45);this.nearClippingPlane=JSM.ValueOrDefault(e,0.1);this.farClippingPlane=JSM.ValueOrDefault(f,1E3)};
JSM.Camera.prototype.Set=function(a,b,c,d,e,f){this.eye=a;this.center=b;this.up=c;this.fieldOfView=JSM.ValueOrDefault(d,45);this.nearClippingPlane=JSM.ValueOrDefault(e,0.1);this.farClippingPlane=JSM.ValueOrDefault(f,1E3)};JSM.Camera.prototype.Clone=function(){var a=new JSM.Camera;a.eye=this.eye;a.center=this.center;a.up=this.up;a.fieldOfView=this.fieldOfView;a.nearClippingPlane=this.nearClippingPlane;a.farClippingPlane=this.farClippingPlane;return a};
JSM.ExplodeBodyToTriangles=function(a,b,c){if(void 0===c||null===c)return!1;var d=JSM.CalculateBodyVertexNormals(a),e,f,g=!1;if(void 0!==b&&null!==b)for(e=0;e<b.Count();e++)if(null!==b.GetMaterial(e).texture){g=!0;break}var h,l;if(g){h=JSM.CalculateBodyTextureCoords(a);for(e=0;e<h.length;e++)if(f=a.GetPolygon(e),f.HasMaterialIndex()){l=b.GetMaterial(f.GetMaterialIndex());for(f=0;f<h[e].length;f++)h[e][f].x/=l.textureWidth,h[e][f].y/=-l.textureHeight}}var k=!0;void 0!==c.hasConvexPolygons&&null!==
c.hasConvexPolygons&&(k=c.hasConvexPolygons);(function(a,b,c,d,e){function f(h,l){var t=b.GetMaterial(l);if(void 0!==e.onGeometryStart&&null!==e.onGeometryStart)e.onGeometryStart(t);var x;for(x=0;x<h.length;x++){var s=h[x],v=a.GetPolygon(s),y=v.VertexIndexCount();if(!(3>y)){var D=void 0,A=void 0,B=void 0,K=void 0,L=void 0,M=void 0,w=void 0,G=void 0,N=void 0,E=void 0;if(3==y||k)for(E=0;E<y-2;E++){if(D=a.GetVertex(v.GetVertexIndex(0)).position,A=a.GetVertex(v.GetVertexIndex((E+1)%y)).position,B=a.GetVertex(v.GetVertexIndex((E+
2)%y)).position,K=c[s][0],L=c[s][(E+1)%y],M=c[s][(E+2)%y],N=G=w=null,g&&(w=d[s][0],G=d[s][(E+1)%y],N=d[s][(E+2)%y]),void 0!==e.onTriangle&&null!==e.onTriangle)e.onTriangle(D,A,B,K,L,M,w,G,N)}else{D=new JSM.Polygon;A=void 0;for(E=0;E<y;E++)A=a.GetVertex(v.vertices[E]),D.AddVertex(A.position.x,A.position.y,A.position.z);for(var E=JSM.CalculateBodyPolygonNormal(a,s),y=JSM.PolygonTriangulate(D,E),O=void 0,E=0;E<y.length;E++)if(O=y[E],D=a.GetVertex(v.GetVertexIndex(O[0])).position,A=a.GetVertex(v.GetVertexIndex(O[1])).position,
B=a.GetVertex(v.GetVertexIndex(O[2])).position,K=c[s][O[0]],L=c[s][O[1]],M=c[s][O[2]],N=G=w=null,g&&(w=d[s][O[0]],G=d[s][O[1]],N=d[s][O[2]]),void 0!==e.onTriangle&&null!==e.onTriangle)e.onTriangle(D,A,B,K,L,M,w,G,N)}}}if(void 0!==e.onGeometryEnd&&null!==e.onGeometryEnd)e.onGeometryEnd(t)}var h,l=[],t=[];if(void 0===b||null===b)b=new JSM.Materials;for(h=0;h<b.Count();h++)l[h]=[];var y;for(h=0;h<a.PolygonCount();h++)y=a.GetPolygon(h),y.HasMaterialIndex()?(y=y.GetMaterialIndex(),l[y].push(h)):t.push(h);
for(h=0;h<l.length;h++)y=l[h],0!==y.length&&f(y,h);0!==t.length&&f(t,-1)})(a,b,d,h,c);return!0};
JSM.ExportBodyContentToStl=function(a,b,c){function d(a){g+=a+"\n"}function e(a,b,c,e){d("\tfacet normal "+a.x+" "+a.y+" "+a.z);d("\t\touter loop");d("\t\t\tvertex "+b.x+" "+b.y+" "+b.z);d("\t\t\tvertex "+c.x+" "+c.y+" "+c.z);d("\t\t\tvertex "+e.x+" "+e.y+" "+e.z);d("\t\tendloop");d("\tendfacet")}function f(b){var d=a.GetPolygon(b),f=d.VertexIndexCount();if(!(3>f)){var g,n,p,q=null;if(3===f)q=JSM.CalculateBodyPolygonNormal(a,b),g=a.GetVertex(d.GetVertexIndex(0)).position,n=a.GetVertex(d.GetVertexIndex(1)).position,
p=a.GetVertex(d.GetVertexIndex(2)).position,e(q,g,n,p);else if(g=!0,void 0!==c&&c&&(g=!1),q=JSM.CalculateBodyPolygonNormal(a,b),g){g=new JSM.Polygon;for(b=0;b<f;b++)n=a.GetVertex(d.vertices[b]),g.AddVertex(n.position.x,n.position.y,n.position.z);f=JSM.PolygonTriangulate(g,q);for(b=0;b<f.length;b++)p=f[b],g=a.GetVertex(d.GetVertexIndex(p[0])).position,n=a.GetVertex(d.GetVertexIndex(p[1])).position,p=a.GetVertex(d.GetVertexIndex(p[2])).position,e(q,g,n,p)}else for(b=0;b<f-2;b++)g=a.GetVertex(d.GetVertexIndex(0)).position,
n=a.GetVertex(d.GetVertexIndex((b+1)%f)).position,p=a.GetVertex(d.GetVertexIndex((b+2)%f)).position,e(q,g,n,p)}}var g="";for(b=0;b<a.PolygonCount();b++)f(b);return g};JSM.ExportBodyToStl=function(a,b,c){a=""+("solid "+b+"\n")+JSM.ExportBodyContentToStl(a,b,c);return a+="endsolid "+b+"\n"};JSM.ExportModelToStl=function(a,b,c){var d;d=""+("solid "+b+"\n");var e,f;for(e=0;e<a.BodyCount();e++)f=a.GetBody(e),d+=JSM.ExportBodyContentToStl(f,b+(e+1).toString(),c);return d+("endsolid "+b+"\n")};
JSM.ExportBodyContentToObj=function(a,b,c){function d(b){b=a.GetVertex(b).position;g+="v "+b.x+" "+b.y+" "+b.z+"\n"}function e(b){b=JSM.CalculateBodyPolygonNormal(a,b);g+="vn "+b.x+" "+b.y+" "+b.z+"\n"}function f(d){var e=a.GetPolygon(d);g+="f ";var f;for(f=0;f<e.VertexIndexCount();f++){var h=b+e.GetVertexIndex(f)+1+"//"+(c+d+1)+" ";g+=h}g+="\n"}var g="",h;for(h=0;h<a.VertexCount();h++)d(h);for(h=0;h<a.PolygonCount();h++)e(h);for(h=0;h<a.PolygonCount();h++)f(h);return g};
JSM.ExportBodyToObj=function(a){return JSM.ExportBodyContentToObj(a,0,0)};JSM.ExportModelToObj=function(a){var b="",c=0,d=0,e,f;for(e=0;e<a.BodyCount();e++)f=a.GetBody(e),b+=JSM.ExportBodyContentToObj(f,c,d),c+=f.VertexCount(),d+=f.PolygonCount();return b};
JSM.ExportMaterialsToGdl=function(a){function b(a,b){var d=JSM.HexColorToRGBComponents(a.diffuse);c+='define material "material'+b+'" 2, '+(d[0]/255+","+d[1]/255+","+d[2]/255)+" ! "+b+"\n"}var c="",d=!1;void 0!==a&&null!==a&&(d=!0);if(d){b(a.GetDefaultMaterial(),1);for(d=0;d<a.Count();d++)b(a.GetMaterial(d),d+2)}return c};
JSM.ExportBodyGeometryToGdl=function(a,b){function c(a){if(200<a.length){var b=0,c,d;for(c=0;c<a.length;c++)d=a[c],h+=d,b++,200<b&&","==d&&(h+="\n",b=0)}else h+=a}function d(a){c(a+"\n")}function e(b){var c=a.GetVertex(b).position;d("vert "+c.x+", "+c.y+", "+c.z+" ! "+(b+1))}function f(b){var c=l.edges[b],e=0;-1!=c.pgon1&&-1!=c.pgon2&&a.GetPolygon(c.pgon1).HasCurveGroup()&&a.GetPolygon(c.pgon2).HasCurveGroup()&&a.GetPolygon(c.pgon1).GetCurveGroup()==a.GetPolygon(c.pgon2).GetCurveGroup()&&(e=2);d("edge "+
(c.vert1+1)+", "+(c.vert2+1)+", -1, -1, "+e+" ! "+(b+1))}function g(e,f){var g=-1;b&&(g=a.GetPolygon(e).GetMaterialIndex()+2,g!=f&&d('set material "material'+g+'"'));var h=l.pgons[e],k=0;a.GetPolygon(e).HasCurveGroup()&&(k=2);c("pgon "+h.pedges.length+", 0, "+k+", ");var k="",m,v;for(m=0;m<h.pedges.length;m++)v=h.pedges[m],k=v.reverse?k+-(v.index+1):k+(v.index+1),m<h.pedges.length-1&&(k+=", ");c(k);c(" ! "+(e+1));d("");return g}var h="";d("base");var l=JSM.CalculateAdjacencyInfo(a),k;for(k=0;k<l.verts.length;k++)e(k);
for(k=0;k<l.edges.length;k++)f(k);var m=-1;for(k=0;k<l.pgons.length;k++)m=g(k,m);d("body -1");return h};JSM.ExportBodyToGdl=function(a,b){var c="",d=!1;void 0!==b&&null!==b&&(c+=JSM.ExportMaterialsToGdl(b),d=!0);return c+=JSM.ExportBodyGeometryToGdl(a,d)};JSM.ExportModelToGdl=function(a,b){var c="",d=!1;void 0!==b&&null!==b&&(c+=JSM.ExportMaterialsToGdl(b),d=!0);var e,f;for(e=0;e<a.BodyCount();e++)f=a.GetBody(e),c+=JSM.ExportBodyGeometryToGdl(f,d);return c};
JSM.TriangleBody=function(a){this.name=a;this.vertices=[];this.normals=[];this.triangles=[]};JSM.TriangleBody.prototype.SetName=function(a){this.name=a};JSM.TriangleBody.prototype.GetName=function(){return this.name};JSM.TriangleBody.prototype.AddVertex=function(a,b,c){this.vertices.push(new JSM.Coord(a,b,c));return this.vertices.length-1};JSM.TriangleBody.prototype.GetVertex=function(a){return this.vertices[a]};
JSM.TriangleBody.prototype.SetVertex=function(a,b,c,d){this.vertices[a]=new JSM.Coord(b,c,d)};JSM.TriangleBody.prototype.VertexCount=function(){return this.vertices.length};JSM.TriangleBody.prototype.AddNormal=function(a,b,c){this.normals.push(new JSM.Coord(a,b,c));return this.normals.length-1};JSM.TriangleBody.prototype.GetNormal=function(a){return this.normals[a]};JSM.TriangleBody.prototype.NormalCount=function(){return this.normals.length};
JSM.TriangleBody.prototype.AddTriangle=function(a,b,c,d,e,f,g,h,l,k,m){this.triangles.push({v0:a,v1:b,v2:c,n0:d,n1:e,n2:f,u0:g,u1:h,u2:l,mat:k,curve:m});return this.triangles.length-1};JSM.TriangleBody.prototype.GetTriangle=function(a){return this.triangles[a]};JSM.TriangleBody.prototype.TriangleCount=function(){return this.triangles.length};
JSM.TriangleBody.prototype.Finalize=function(a){function b(b,c,d,f){function g(a,b,c,d,e){var f=new JSM.Vector(0,0,0),h=0;c=a.GetTriangle(c);b=e[b];var k,l;for(e=0;e<b.length;e++)k=b[e],l=a.GetTriangle(k),c.curve==l.curve&&(f=JSM.CoordAdd(f,d[k]),h+=1);f=JSM.VectorMultiply(f,1/h);f=JSM.VectorNormalize(f);return a.AddNormal(f.x,f.y,f.z)}var p=b.triangles[e];void 0===p.mat&&(p.mat=a.AddDefaultMaterial());if(void 0===p.n0||void 0===p.n1||void 0===p.n2)void 0===p.curve||0===p.curve?(c=d[e],b=b.AddNormal(c.x,
c.y,c.z),p.n0=b,p.n1=b,p.n2=b):(p.n0=g(b,p.v0,c,d,f),p.n1=g(b,p.v1,c,d,f),p.n2=g(b,p.v2,c,d,f))}var c=[],d={},e;for(e=0;e<this.vertices.length;e++)d[e]=[];var f,g;for(e=0;e<this.triangles.length;e++)f=this.triangles[e],g=JSM.CalculateTriangleNormal(this.vertices[f.v0],this.vertices[f.v1],this.vertices[f.v2]),c.push(g),d[f.v0].push(e),d[f.v1].push(e),d[f.v2].push(e);for(e=0;e<this.triangles.length;e++)b(this,e,c,d)};
JSM.TriangleBody.prototype.Clone=function(){var a=new JSM.TriangleBody(this.name),b,c;for(b=0;b<this.vertices.length;b++)a.vertices.push(this.vertices[b].Clone());for(b=0;b<this.normals.length;b++)a.normals.push(this.normals[b].Clone());for(b=0;b<this.triangles.length;b++)c=this.triangles[b],a.triangles.push({v0:c.v0,v1:c.v1,v2:c.v2,n0:c.n0,n1:c.n1,n2:c.n2,u0:c.u0,u1:c.u1,u2:c.u2,mat:c.mat,curve:c.curve});return a};
JSM.TriangleModel=function(){this.materials=[];this.bodies=[];this.defaultMaterial=-1};JSM.TriangleModel.prototype.AddMaterial=function(a,b,c,d,e){this.materials.push({name:a,ambient:b,diffuse:c,specular:d,opacity:e});return this.materials.length-1};JSM.TriangleModel.prototype.GetMaterial=function(a){return this.materials[a]};
JSM.TriangleModel.prototype.AddDefaultMaterial=function(){-1==this.defaultMaterial&&(this.materials.push({name:"Default",ambient:{r:0.5,g:0.5,b:0.5},diffuse:{r:0.5,g:0.5,b:0.5},specular:{r:0.1,g:0.1,b:0.1},opacity:1}),this.defaultMaterial=this.materials.length-1);return this.defaultMaterial};JSM.TriangleModel.prototype.GetDefaultMaterialIndex=function(){return this.AddDefaultMaterial()};JSM.TriangleModel.prototype.MaterialCount=function(){return this.materials.length};
JSM.TriangleModel.prototype.AddBody=function(a){this.bodies.push(a);return this.bodies.length-1};JSM.TriangleModel.prototype.AddBodyToIndex=function(a,b){this.bodies.splice(b,0,a);return b};JSM.TriangleModel.prototype.GetBody=function(a){return this.bodies[a]};JSM.TriangleModel.prototype.BodyCount=function(){return this.bodies.length};JSM.TriangleModel.prototype.GetBody=function(a){return this.bodies[a]};
JSM.TriangleModel.prototype.Finalize=function(){var a,b;for(a=0;a<this.bodies.length;a++)b=this.bodies[a],b.Finalize(this)};JSM.BinaryReader=function(a,b){this.arrayBuffer=a;this.dataView=new DataView(a);this.isLittleEndian=b;this.position=0};JSM.BinaryReader.prototype.GetPosition=function(){return this.position};JSM.BinaryReader.prototype.GetByteLength=function(){return this.arrayBuffer.byteLength};JSM.BinaryReader.prototype.Skip=function(a){this.position+=a};
JSM.BinaryReader.prototype.End=function(){return this.position>=this.arrayBuffer.byteLength};JSM.BinaryReader.prototype.ReadBoolean=function(){var a=this.dataView.getInt8(this.position,this.isLittleEndian);this.position+=1;return a?!0:!1};JSM.BinaryReader.prototype.ReadCharacter=function(){var a=this.dataView.getInt8(this.position,this.isLittleEndian);this.position+=1;return a};
JSM.BinaryReader.prototype.ReadUnsignedCharacter=function(){var a=this.dataView.getUint8(this.position,this.isLittleEndian);this.position+=1;return a};JSM.BinaryReader.prototype.ReadInteger16=function(){var a=this.dataView.getInt16(this.position,this.isLittleEndian);this.position+=2;return a};JSM.BinaryReader.prototype.ReadUnsignedInteger16=function(){var a=this.dataView.getUint16(this.position,this.isLittleEndian);this.position+=2;return a};
JSM.BinaryReader.prototype.ReadInteger32=function(){var a=this.dataView.getInt32(this.position,this.isLittleEndian);this.position+=4;return a};JSM.BinaryReader.prototype.ReadUnsignedInteger32=function(){var a=this.dataView.getUint32(this.position,this.isLittleEndian);this.position+=4;return a};JSM.BinaryReader.prototype.ReadFloat32=function(){var a=this.dataView.getFloat32(this.position,this.isLittleEndian);this.position+=4;return a};
JSM.BinaryReader.prototype.ReadDouble64=function(){var a=this.dataView.getFloat64(this.position,this.isLittleEndian);this.position+=8;return a};JSM.GetArrayBufferFromURL=function(a,b){var c=new XMLHttpRequest;c.open("GET",a,!0);c.responseType="arraybuffer";c.onload=function(){var a=c.response;a&&b(a)};c.send(null)};JSM.GetArrayBufferFromFile=function(a,b){var c=new FileReader;c.onloadend=function(a){a.target.readyState==FileReader.DONE&&b(a.target.result)};c.readAsArrayBuffer(a)};
JSM.GetStringBufferFromURL=function(a,b){var c=new XMLHttpRequest;c.open("GET",a,!0);c.responseType="text";c.onload=function(){var a=c.response;a&&b(a)};c.send(null)};JSM.LoadMultipleBuffers=function(a,b,c,d,e){if(c>=a.length)e(b);else{var f=a[c];d(f,function(g){b.push({originalObject:f,resultBuffer:g});JSM.LoadMultipleBuffers(a,b,c+1,d,e)})}};JSM.GetStringBufferFromFile=function(a,b){var c=new FileReader;c.onloadend=function(a){a.target.readyState==FileReader.DONE&&b(a.target.result)};c.readAsText(a)};
JSM.GetStringBuffersFromURLList=function(a,b){JSM.LoadMultipleBuffers(a,[],0,JSM.GetStringBufferFromURL,function(a){b(a)})};JSM.GetStringBuffersFromFileList=function(a,b){JSM.LoadMultipleBuffers(a,[],0,JSM.GetStringBufferFromFile,function(a){b(a)})};
JSM.ConvertTriangleModelToJsonData=function(a){function b(a,b,c){var d=[],e=a.MaterialCount(),f;for(a=0;a<b.VertexCount();a++)f=b.GetVertex(a),c.vertices.push(f.x,f.y,f.z);for(a=0;a<b.NormalCount();a++)f=b.GetNormal(a),c.normals.push(f.x,f.y,f.z);c.uvs.push(0,0);for(a=0;a<e;a++)d.push([]);for(a=0;a<b.TriangleCount();a++)f=b.GetTriangle(a),void 0===f.mat||(0>f.mat||f.mat>=e)||d[f.mat].push(a);var p,q;for(a=0;a<d.length;a++)if(p=d[a],0!==p.length){q={material:a,parameters:[]};for(e=0;e<p.length;e++)f=
b.GetTriangle(p[e]),q.parameters.push(f.v0,f.v1,f.v2,f.n0,f.n1,f.n2,0,0,0);c.triangles.push(q)}}var c={version:1,materials:[],meshes:[]};(function(a,b){var c,d;for(c=0;c<a.MaterialCount();c++)d=a.GetMaterial(c),b.push({name:d.name,ambient:[d.ambient.r,d.ambient.g,d.ambient.b],diffuse:[d.diffuse.r,d.diffuse.g,d.diffuse.b],specular:[d.specular.r,d.specular.g,d.specular.b],opacity:d.opacity})})(a,c.materials);var d,e,f;for(d=0;d<a.BodyCount();d++)e=a.GetBody(d),0!==e.TriangleCount()&&(f={name:e.GetName(),
vertices:[],normals:[],uvs:[],triangles:[]},b(a,e,f),c.meshes.push(f));return c};
JSM.MergeJsonDataMeshes=function(a){function b(a,b,c){function d(a,b,c){var h=b.material,l=c[h];void 0===l&&(a.triangles.push({material:h,parameters:[]}),l=a.triangles.length-1,c[h]=l);a=a.triangles[l].parameters;for(c=0;c<b.parameters.length;c+=9)a.push(b.parameters[c]+e,b.parameters[c+1]+e,b.parameters[c+2]+e,b.parameters[c+3]+f,b.parameters[c+4]+f,b.parameters[c+5]+f,b.parameters[c+6]+g,b.parameters[c+7]+g,b.parameters[c+8]+g)}var e=a.vertices.length/3,f=a.normals.length/3,g=a.uvs.length/2;(function(a,
b){var c;for(c=0;c<b.vertices.length;c++)a.vertices.push(b.vertices[c]);for(c=0;c<b.normals.length;c++)a.normals.push(b.normals[c]);for(c=0;c<b.uvs.length;c++)a.uvs.push(b.uvs[c])})(a,b);var r,s;for(r=0;r<b.triangles.length;r++)s=b.triangles[r],d(a,s,c)}var c={version:a.version,materials:a.materials,meshes:[]},d={name:"Merged",vertices:[],normals:[],uvs:[],triangles:[]},e={},f,g;for(f=0;f<a.meshes.length;f++)g=a.meshes[f],b(d,g,e);c.meshes.push(d);return c};
JSM.Read3dsFile=function(a,b){var c,d,e,f,g,h,l,k,m,n,p,q,r,s,x,v,t,y,F,C,u,H,z,I,J,D,A,B,K,L,M;function w(a,c){if(void 0!==b.onLog&&null!==b.onLog)b.onLog(a,c)}function G(a){for(var b="",c=0,d=0;64>d;){c=a.ReadCharacter();if(0===c)break;b+=String.fromCharCode(c);d+=1}return b}function N(a){var b=[],c;for(c=0;3>c;c++)b[c]=a.ReadFloat32();return b}function E(a,b,c){for(;a.GetPosition()<=b-6;){var d=a,e=c,f=d.ReadUnsignedInteger16(),d=d.ReadUnsignedInteger32();e(f,d)}}if(void 0===b||null===b)b={};c=
15677;d=45055;e=40960;f=40976;g=40992;h=41008;l=41024;k=41040;m=16;n=17;p=18;q=19;r=48;s=49;x=16384;v=16640;t=17920;y=18176;F=16656;C=16672;u=16736;H=16688;z=16720;I=45056;J=45058;D=45072;A=45075;B=45088;K=45089;L=45090;M=45104;(function(a){function P(a,b,c){var d={};b=a.GetPosition()+c-6;var e=!1;E(a,b,function(b,c){b==n?e||(d.r=a.ReadUnsignedCharacter()/255,d.g=a.ReadUnsignedCharacter()/255,d.b=a.ReadUnsignedCharacter()/255):b==p?(d.r=a.ReadUnsignedCharacter()/255,d.g=a.ReadUnsignedCharacter()/
255,d.b=a.ReadUnsignedCharacter()/255,e=!0):b==m?e||(d.r=a.ReadFloat32(),d.g=a.ReadFloat32(),d.b=a.ReadFloat32()):b==q?(d.r=a.ReadFloat32(),d.g=a.ReadFloat32(),d.b=a.ReadFloat32(),e=!0):a.Skip(c-6)});return d}function Q(a,b,c){var d=0;b=a.GetPosition()+c-6;E(a,b,function(b,c){b==r?d=a.ReadUnsignedInteger16()/100:b==s?d=a.ReadFloat32():a.Skip(c-6)});return d}function R(a,c,d){w("Read material chunk ("+c.toString(16)+", "+d+")",2);var m={},n=a.GetPosition()+d-6;E(a,n,function(b,n){b==e?(w("Read material name chunk ("+
c.toString(16)+", "+d+")",3),m.name=G(a)):b==f?(w("Read material ambient chunk ("+c.toString(16)+", "+d+")",3),m.ambient=P(a,b,n)):b==g?(w("Read material diffuse chunk ("+c.toString(16)+", "+d+")",3),m.diffuse=P(a,b,n)):b==h?(w("Read material specular chunk ("+c.toString(16)+", "+d+")",3),m.specular=P(a,b,n)):b==l?(w("Read material shininess chunk ("+c.toString(16)+", "+d+")",3),m.shininess=Q(a,b,n)):b==k?(w("Read material transparency chunk ("+c.toString(16)+", "+d+")",3),m.transparency=Q(a,b,n)):
(w("Skip chunk ("+b.toString(16)+", "+n+")",3),a.Skip(n-6))});if(void 0!==b.onMaterial&&null!==b.onMaterial)b.onMaterial(m)}function S(a,c,d){w("Read faces chunk ("+c.toString(16)+", "+d+")",4);c=a.GetPosition()+d-6;var e=a.ReadUnsignedInteger16(),f,g,h,l;for(d=0;d<e;d++)if(f=a.ReadUnsignedInteger16(),g=a.ReadUnsignedInteger16(),h=a.ReadUnsignedInteger16(),l=a.ReadUnsignedInteger16(),void 0!==b.onFace&&null!==b.onFace)b.onFace(f,g,h,l);E(a,c,function(c,d){if(c==H){w("Read face materials chunk ("+
c.toString(16)+", "+d+")",5);var f=G(a),g=a.ReadUnsignedInteger16(),h,l;for(h=0;h<g;h++)if(l=a.ReadUnsignedInteger16(),void 0!==b.onFaceMaterial&&null!==b.onFaceMaterial)b.onFaceMaterial(l,f)}else if(c==z){w("Read face smoothing groups chunk ("+c.toString(16)+", "+d+")",5);for(f=0;f<e;f++)if(g=a.ReadUnsignedInteger32(),void 0!==b.onFaceSmoothingGroup&&null!==b.onFaceSmoothingGroup)b.onFaceSmoothingGroup(f,g)}else w("Skip chunk ("+c.toString(16)+", "+d+")",5),a.Skip(d-6)})}function T(a,c,d,e){w("Read mesh chunk ("+
c+", "+d.toString(16)+", "+e+")",3);if(void 0!==b.onMesh&&null!==b.onMesh)b.onMesh(c);c=a.GetPosition()+e-6;E(a,c,function(c,d){if(c==F){w("Read vertices chunk ("+c.toString(16)+", "+d+")",4);var e=a.ReadUnsignedInteger16(),f,g,h,l;for(f=0;f<e;f++)if(g=a.ReadFloat32(),h=a.ReadFloat32(),l=a.ReadFloat32(),void 0!==b.onVertex&&null!==b.onVertex)b.onVertex(g,h,l)}else if(c==C)S(a,c,d);else if(c==u){w("Read transformation chunk ("+c.toString(16)+", "+d+")",4);e=[];for(f=0;4>f;f++){for(g=0;3>g;g++)e.push(a.ReadFloat32());
3>f?e.push(0):e.push(1)}if(void 0!==b.onTransformation&&null!==b.onTransformation)b.onTransformation(e)}else w("Skip chunk ("+c.toString(16)+", "+d+")",4),a.Skip(d-6)})}function U(a,b,c){w("Read object chunk ("+b.toString(16)+", "+c+")",2);b=a.GetPosition()+c-6;var d=G(a);E(a,b,function(b,c){b==v?T(a,d,b,c):(b==t?w("Skip light chunk ("+d+", "+b.toString(16)+", "+c+")",3):b==y?w("Skip camera chunk ("+d+", "+b.toString(16)+", "+c+")",3):w("Skip chunk ("+b.toString(16)+", "+c+")",3),a.Skip(c-6))})}function V(a,
b,c){w("Read editor chunk ("+b.toString(16)+", "+c+")",1);b=a.GetPosition()+c-6;E(a,b,function(b,c){b==d?R(a,b,c):b==x?U(a,b,c):(w("Skip chunk ("+b.toString(16)+", "+c+")",2),a.Skip(c-6))})}function W(a,c,d){function e(a,b){var c=[];a.Skip(10);var d,f,g,h=a.ReadInteger32();for(d=0;d<h;d++)a.ReadInteger32(),f=a.ReadUnsignedInteger16(),0!==f&&a.ReadFloat32(),b==K?(g=a.ReadFloat32(),f=N(a),f[3]=g):f=N(a),c.push(f);return c}w("Read object node chunk ("+c.toString(16)+", "+d+")",2);var f={name:"",nodeId:-1,
flags:-1,userId:-1,pivot:[0,0,0],positions:[],rotations:[],scales:[]};c=a.GetPosition()+d-6;E(a,c,function(b,c){b==D?(f.name=G(a),f.flags=a.ReadUnsignedInteger32(),f.userId=a.ReadUnsignedInteger16()):b==A?f.pivot=N(a):b==B?f.positions=e(a,B):b==K?f.rotations=e(a,K):b==L?f.scales=e(a,L):b==M?f.nodeId=a.ReadUnsignedInteger16():(w("Skip chunk ("+b.toString(16)+", "+c+")",3),a.Skip(c-6))});if(void 0!==b.onObjectNode&&null!==b.onObjectNode)b.onObjectNode(f)}function X(a,b,c){w("Read keyframe chunk ("+
b.toString(16)+", "+c+")",1);b=a.GetPosition()+c-6;E(a,b,function(b,c){b==J?W(a,b,c):(w("Skip chunk ("+b.toString(16)+", "+c+")",2),a.Skip(c-6))})}function Y(a,b,d){w("Read main chunk ("+b.toString(16)+", "+d+")",0);b=a.GetPosition()+d-6;E(a,b,function(b,d){b==c?V(a,b,d):b==I?X(a,b,d):(w("Skip chunk ("+b.toString(16)+", "+d+")",1),a.Skip(d-6))})}var Z=a.GetByteLength();E(a,Z,function(b,c){19789==b?Y(a,b,c):(w("Skip chunk ("+b.toString(16)+", "+c+")",0),a.Skip(c-6))})})(new JSM.BinaryReader(a,!0))};
JSM.Convert3dsToJsonData=function(a){var b=new JSM.TriangleModel,c=null,d={},e={},f={nodes:[],nodeIdToIndex:{}};JSM.Read3dsFile(a,{onMaterial:function(a){function c(a){return void 0===a||null===a?{r:0,g:0,b:0}:a}var e=b.AddMaterial(a.name,c(a.ambient),c(a.diffuse),c(a.specular),void 0===a.transparency||null===a.transparency?1:1-a.transparency);void 0===d[a.name]&&(d[a.name]=e)},onMesh:function(a){var d=b.AddBody(new JSM.TriangleBody(a));c=b.GetBody(d);c.meshData={faceToMaterial:{},faceToSmoothingGroup:{},
objectNodes:[],transformation:null};e[a]=d},onTransformation:function(a){null!==c&&(c.meshData.transformation=a)},onObjectNode:function(a){var c=f.nodes.length;f.nodes.push(a);f.nodeIdToIndex[a.nodeId]=c;a=e[a.name];void 0!==a&&b.GetBody(a).meshData.objectNodes.push(c)},onVertex:function(a,b,d){null!==c&&c.AddVertex(a,b,d)},onFace:function(a,b,d){null!==c&&c.AddTriangle(a,b,d)},onFaceMaterial:function(a,b){null!==c&&(c.meshData.faceToMaterial[a]=b)},onFaceSmoothingGroup:function(a,b){null!==c&&(c.meshData.faceToSmoothingGroup[a]=
b)}});(function(a,b,c){function d(a,b,c){function e(a,b){var c=b[0],d=b[1],f=b[2],g;for(g=0;4>g;g++)a[0+g]*=c,a[4+g]*=d,a[8+g]*=f;return a}function f(a,b){var c=b[0],d=b[1],e=b[2],g;for(g=0;3>g;g++)a[12+g]+=a[0+g]*c+a[4+g]*d+a[8+g]*e;return a}function g(a,b){var c,d;for(c=0;c<a.VertexCount();c++)d=a.GetVertex(c),d=JSM.ApplyTransformation(b,d),a.SetVertex(c,d.x,d.y,d.z)}function h(a,b,c){var d=JSM.MatrixDeterminant(b);JSM.IsNegative(d)&&(b=JSM.MatrixClone(b),e(b,[-1,1,1]),c=JSM.MatrixMultiply(c,b),
g(a,c))}function l(a,b){if(void 0!==a.matrix)return a.matrix;var c=JSM.MatrixIdentity(),d;d=0===a.positions.length?[0,0,0]:a.positions[0];c=f(c,d);if(0===a.rotations.length)d=[0,0,0,0];else{d=a.rotations[0];var g=[0,0,0,1],h=Math.sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);JSM.IsPositive(h)&&(g=-0.5*d[3],h=Math.sin(g)/h,g=[h*d[0],h*d[1],h*d[2],Math.cos(g)]);d=g}d=JSM.MatrixRotationQuaternion(d);c=JSM.MatrixMultiply(d,c);d=0===a.scales.length?[0,0,0,0]:a.scales[0];c=e(c,d);65535!=a.userId&&(d=b.nodeIdToIndex[a.userId],
void 0!==d&&(d=l(b.nodes[d],b),c=JSM.MatrixMultiply(c,d)));return a.matrix=c}var k=a.meshData;k=void 0===k||null===k?null:k.transformation;if(null!==k){var m=null,m=null!==b?l(b,c):k;c=JSM.MatrixClone(m);m=JSM.MatrixClone(k);k=JSM.MatrixInvert(m);null!==k&&(h(a,m,k),b=void 0===b||null===b?[0,0,0]:b.pivot,f(c,[-b[0],-b[1],-b[2]]),b=JSM.MatrixMultiply(k,c),g(a,b))}}function e(a,b,c,f){d(a,b,f);b=a.meshData;var g,h;for(f=0;f<a.TriangleCount();f++)g=a.GetTriangle(f),h=b.faceToMaterial[f],void 0!==h&&
(h=c[h],void 0!==h&&(g.mat=h)),h=b.faceToSmoothingGroup[f],void 0!==h&&(g.curve=h)}function f(a,b,c,d){b=b.Clone();b.SetName(b.GetName()+" ("+d+")");c<a.BodyCount()?a.AddBodyToIndex(b,c):a.AddBody(b);return b}var p,q,r,s,x,v,t;for(p=0;p<b.BodyCount();p++)if(r=b.GetBody(p),s=r.meshData,0===s.objectNodes.length)e(r,null,c,a);else{v=a.nodes[s.objectNodes[0]];for(q=1;q<s.objectNodes.length;q++)x=a.nodes[s.objectNodes[q]],t=f(b,r,p+1,q+1),t.meshData=r.meshData,e(t,x,c,a),p+=1;e(r,v,c,a)}})(f,b,d);b.Finalize();
return JSM.ConvertTriangleModelToJsonData(b)};
JSM.ReadObjFile=function(a,b){function c(a){a=a.split("\n");var e,f;for(e=0;e<a.length;e++){var g=f=a[e].trim();if(0!==g.length&&"#"!=g[0]&&(f=g.split(/\s+/),!(0===f.length||"#"==f[0][0]))){var h=void 0,h=void 0;if("g"==f[0]){if(!(2>f.length)){g="";for(h=1;h<f.length;h++)g+=f[h],h<f.length-1&&(g+=" ");if(void 0!==b.onMesh&&null!==b.onMesh)b.onMesh(g)}}else if("v"==f[0]){if(!(4>f.length)&&(h=parseFloat(f[1]),g=parseFloat(f[2]),f=parseFloat(f[3]),void 0!==b.onVertex&&null!==b.onVertex))b.onVertex(h,
g,f)}else if("vn"==f[0]){if(!(4>f.length)&&(h=parseFloat(f[1]),g=parseFloat(f[2]),f=parseFloat(f[3]),void 0!==b.onNormal&&null!==b.onNormal))b.onNormal(h,g,f)}else if("f"==f[0]){if(!(4>f.length)){for(var g=[],l=[],k=void 0,h=1;h<f.length;h++)k=f[h].split("/"),g.push(parseInt(k[0],10)-1),2<k.length&&0<k[2].length&&l.push(parseInt(k[2],10)-1);if(void 0!==b.onFace&&null!==b.onFace)b.onFace(g,l)}}else if("usemtl"==f[0]){if(!(2>f.length)&&void 0!==b.onUseMaterial&&null!==b.onUseMaterial)b.onUseMaterial(f[1])}else if("newmtl"==
f[0]){if(!(2>f.length)&&void 0!==b.onNewMaterial&&null!==b.onNewMaterial)b.onNewMaterial(f[1])}else if("Ka"==f[0]||"Kd"==f[0]||"Ks"==f[0]){if(!(4>f.length)&&(h=parseFloat(f[1]),g=parseFloat(f[2]),l=parseFloat(f[3]),void 0!==b.onMaterialComponent&&null!==b.onMaterialComponent))b.onMaterialComponent(f[0],h,g,l)}else if("Ka"==f[0]||"Kd"==f[0]||"Ks"==f[0]){if(!(4>f.length)&&(h=parseFloat(f[1]),g=parseFloat(f[2]),l=parseFloat(f[3]),void 0!==b.onMaterialComponent&&null!==b.onMaterialComponent))b.onMaterialComponent(f[0],
h,g,l)}else"mtllib"==f[0]&&!(2>f.length)&&(f=g.indexOf("mtllib")+6,h=g.substr(f,g.length-f).trim(),f=h.trim(),f=void 0!==b.onFileRequested&&null!==b.onFileRequested?b.onFileRequested(f):null,null!==f&&c(f))}}}c(a)};
JSM.ConvertObjToJsonData=function(a,b){var c=new JSM.TriangleModel,d=c.AddBody(new JSM.TriangleBody("Default")),e=c.GetBody(d),f={},g=null,h=null,l=[],k=[];JSM.ReadObjFile(a,{onNewMaterial:function(a){var b=c.AddMaterial(a,{r:1,g:0,b:0},{r:1,g:0,b:0},{r:0,g:0,b:0},1);g=c.GetMaterial(b);f[a]=b},onMaterialComponent:function(a,b,c,d){null!==g&&("Ka"==a?(a=g.ambient,a.r=b,a.g=c,a.b=d):"Kd"==a?(a=g.diffuse,a.r=b,a.g=c,a.b=d):"Ks"==a&&(a=g.specular,a.r=b,a.g=c,a.b=d))},onUseMaterial:function(a){a=f[a];
void 0!==a&&(h=a)},onMesh:function(a){a=c.AddBody(new JSM.TriangleBody(a));e=c.GetBody(a)},onVertex:function(a,b,c){l.push(new JSM.Coord(a,b,c))},onNormal:function(a,b,c){k.push(new JSM.Coord(a,b,c))},onFace:function(a,b){var c,d,f=a.length==b.length,g=a.length;for(c=0;c<g-2;c++)d=e.AddTriangle(a[0],a[(c+1)%g],a[(c+2)%g]),d=e.GetTriangle(d),f&&(d.n0=b[0],d.n1=b[(c+1)%g],d.n2=b[(c+2)%g]),null!==h&&(d.mat=h)},onFileRequested:function(a){return void 0!==b.onFileRequested&&null!==b.onFileRequested?b.onFileRequested(a):
null}});(function(a,b,c){function d(a,b,c,e,f){if(void 0!==c){var g=e[c];if(void 0!==g)return g;b=b[c];0===f?g=a.AddVertex(b.x,b.y,b.z):1===f&&(g=a.AddNormal(b.x,b.y,b.z));return e[c]=g}}var e,f,g,h,l,k;for(e=0;e<a.BodyCount();e++){g=a.GetBody(e);l={};k={};for(f=0;f<g.TriangleCount();f++)h=g.GetTriangle(f),h.v0=d(g,b,h.v0,l,0),h.v1=d(g,b,h.v1,l,0),h.v2=d(g,b,h.v2,l,0),h.n0=d(g,c,h.n0,k,1),h.n1=d(g,c,h.n1,k,1),h.n2=d(g,c,h.n2,k,1)}})(c,l,k);c.Finalize();return JSM.ConvertTriangleModelToJsonData(c)};
JSM.ReadBinaryStlFile=function(a,b){function c(a){var b=[],c;for(c=0;3>c;c++)b[c]=a.ReadFloat32();return b}var d=new JSM.BinaryReader(a,!0);d.Skip(80);var e=d.ReadUnsignedInteger32(),f,g,h,l,k;for(f=0;f<e;f++)if(k=c(d),g=c(d),h=c(d),l=c(d),d.Skip(2),void 0!==b.onFace&&null!==b.onFace)b.onFace(g,h,l,k)};
JSM.ReadAsciiStlFile=function(a,b){function c(a,c){var d=a[c].trim();if(0===d.length)return c+1;d=d.split(/\s+/);if(0===d.length)return c+1;if("solid"!=d[0]&&"facet"==d[0]&&"normal"==d[1]){if(5>d.length)return-1;var d=[parseFloat(d[2]),parseFloat(d[3]),parseFloat(d[4])],e=[],k,m;for(k=c+1;k<a.length&&3>e.length;k++)if(m=a[k].trim(),0!==m.length&&(m=m.split(/\s+/),0!==m.length&&"vertex"==m[0]))if(4>m.length)break;else m=[parseFloat(m[1]),parseFloat(m[2]),parseFloat(m[3])],e.push(m);k+=1;if(3!=e.length)return-1;
if(void 0!==b.onFace&&null!==b.onFace)b.onFace(e[0],e[1],e[2],d);return k}return c+1}for(var d=0,e=a.split("\n");d<e.length&&-1!=d;)d=c(e,d)};
JSM.ConvertStlToJsonData=function(a){var b=new JSM.TriangleModel,c=b.AddBody(new JSM.TriangleBody("Default")),d=b.GetBody(c);(function(a){var b=a.byteLength;if(84>b)return!1;a=new JSM.BinaryReader(a,!0);a.Skip(80);a=a.ReadUnsignedInteger32();return b!=50*a+84?!1:!0})(a)?JSM.ReadBinaryStlFile(a,{onFace:function(a,b,c,h){a=d.AddVertex(a[0],a[1],a[2]);b=d.AddVertex(b[0],b[1],b[2]);c=d.AddVertex(c[0],c[1],c[2]);h=JSM.VectorNormalize(new JSM.Vector(h[0],h[1],h[2]));h=d.AddNormal(h.x,h.y,h.z);d.AddTriangle(a,
b,c,h,h,h)}}):(a=String.fromCharCode.apply(null,new Uint8Array(a)),JSM.ReadAsciiStlFile(a,{onFace:function(a,b,c,h){a=d.AddVertex(a[0],a[1],a[2]);b=d.AddVertex(b[0],b[1],b[2]);c=d.AddVertex(c[0],c[1],c[2]);h=JSM.VectorNormalize(new JSM.Vector(h[0],h[1],h[2]));h=d.AddNormal(h.x,h.y,h.z);d.AddTriangle(a,b,c,h,h,h)}}));b.Finalize();return JSM.ConvertTriangleModelToJsonData(b)};JSM.ImportFileList=function(){this.descriptors=null};
JSM.ImportFileList.prototype.Init=function(a){this.descriptors=[];var b,c;for(b=0;b<a.length;b++)c=a[b],c={originalObject:c,originalFileName:c.name,fileName:c.name.toUpperCase(),extension:this.GetFileExtension(c.name)},this.descriptors.push(c)};JSM.ImportFileList.prototype.GetFileDescriptor=function(a){return this.descriptors[a]};
JSM.ImportFileList.prototype.GetMainFileIndex=function(a){var b;for(a=0;a<this.descriptors.length;a++)if(b=this.descriptors[a],this.IsSupportedExtension(b.extension))return a;return-1};JSM.ImportFileList.prototype.GetFileIndexByName=function(a){var b,c;for(b=0;b<this.descriptors.length;b++)if(c=this.descriptors[b],c.fileName==a.toUpperCase())return b;return-1};JSM.ImportFileList.prototype.IsSupportedExtension=function(a){return".3DS"==a||".OBJ"==a||".STL"==a?!0:!1};
JSM.ImportFileList.prototype.GetFileExtension=function(a){var b=a.lastIndexOf(".");if(-1==b)return"";a=a.substr(b);return a=a.toUpperCase()};
JSM.ConvertFileListToJsonData=function(a,b){function c(a,c){if(void 0!==b.onReady&&null!==b.onReady)b.onReady(a,c)}var d=new JSM.ImportFileList;d.Init(a);var e=d.GetMainFileIndex();if(-1===e){if(void 0!==b.onError&&null!==b.onError)b.onError()}else{var f=d.GetFileDescriptor(e),g={main:f.originalFileName,requested:[],missing:[]};".3DS"==f.extension?JSM.GetArrayBufferFromFile(f.originalObject,function(a){a=JSM.Convert3dsToJsonData(a);c(g,a)}):".OBJ"==f.extension?JSM.GetStringBuffersFromFileList(a,function(a){var b=
JSM.ConvertObjToJsonData(a[e].resultBuffer,{onFileRequested:function(b){var c=d.GetFileIndexByName(b);if(-1==c)return g.missing.push(b),null;g.requested.push(b);return a[c].resultBuffer}});c(g,b)}):".STL"==f.extension&&JSM.GetArrayBufferFromFile(f.originalObject,function(a){a=JSM.ConvertStlToJsonData(a);c(g,a)})}};
JSM.GenerateSolidWithRadius=function(a,b){var c=new JSM.Body,d=!0;"Tetrahedron"===a?c=JSM.GenerateTetrahedron():"Hexahedron"===a?c=JSM.GenerateHexahedron():"Octahedron"===a?c=JSM.GenerateOctahedron():"Dodecahedron"===a?c=JSM.GenerateDodecahedron():"Icosahedron"===a?c=JSM.GenerateIcosahedron():"TruncatedTetrahedron"===a?c=JSM.GenerateTruncatedTetrahedron():"Cuboctahedron"===a?c=JSM.GenerateCuboctahedron():"TruncatedCube"===a?c=JSM.GenerateTruncatedCube():"TruncatedOctahedron"===a?c=JSM.GenerateTruncatedOctahedron():
"Rhombicuboctahedron"===a?c=JSM.GenerateRhombicuboctahedron():"TruncatedCuboctahedron"===a?c=JSM.GenerateTruncatedCuboctahedron():"SnubCube"===a?c=JSM.GenerateSnubCube():"Icosidodecahedron"===a?c=JSM.GenerateIcosidodecahedron():"TruncatedDodecahedron"===a?c=JSM.GenerateTruncatedDodecahedron():"TruncatedIcosahedron"===a?c=JSM.GenerateTruncatedIcosahedron():"Rhombicosidodecahedron"===a?c=JSM.GenerateRhombicosidodecahedron():"TruncatedIcosidodecahedron"===a?c=JSM.GenerateTruncatedIcosidodecahedron():
"SnubDodecahedron"===a?c=JSM.GenerateSnubDodecahedron():"TetrakisHexahedron"===a?(c=JSM.GenerateTetrakisHexahedron(),d=!1):"RhombicDodecahedron"===a?(c=JSM.GenerateRhombicDodecahedron(),d=!1):"PentakisDodecahedron"===a?(c=JSM.GeneratePentakisDodecahedron(),d=!1):"SmallStellatedDodecahedron"===a?(c=JSM.GenerateSmallStellatedDodecahedron(),d=!1):"GreatDodecahedron"===a?(c=JSM.GenerateGreatDodecahedron(),d=!1):"SmallTriambicIcosahedron"===a?(c=JSM.GenerateSmallTriambicIcosahedron(),d=!1):"GreatStellatedDodecahedron"===
a?(c=JSM.GenerateGreatStellatedDodecahedron(),d=!1):"SmallTriakisOctahedron"===a?(c=JSM.GenerateSmallTriakisOctahedron(),d=!1):"StellaOctangula"===a?(c=JSM.GenerateStellaOctangula(),d=!1):"TriakisTetrahedron"===a&&(c=JSM.GenerateTriakisTetrahedron(),d=!1);if(0<c.VertexCount()){var e=0;if(d)e=JSM.VectorLength(c.GetVertexPosition(0));else for(var f,d=0;d<c.VertexCount();d++)f=JSM.VectorLength(c.GetVertexPosition(d)),JSM.IsGreater(f,e)&&(e=f);e=b/e;for(d=0;d<c.VertexCount();d++)f=c.GetVertex(d),f.SetPosition(JSM.VectorMultiply(f.GetPosition(),
e))}return c};JSM.GenerateTetrahedron=function(){var a=new JSM.Body;a.AddVertex(new JSM.BodyVertex(new JSM.Coord(1,1,1)));a.AddVertex(new JSM.BodyVertex(new JSM.Coord(-1,-1,1)));a.AddVertex(new JSM.BodyVertex(new JSM.Coord(-1,1,-1)));a.AddVertex(new JSM.BodyVertex(new JSM.Coord(1,-1,-1)));a.AddPolygon(new JSM.BodyPolygon([0,1,3]));a.AddPolygon(new JSM.BodyPolygon([0,2,1]));a.AddPolygon(new JSM.BodyPolygon([0,3,2]));a.AddPolygon(new JSM.BodyPolygon([1,2,3]));return a};
JSM.GenerateHexahedron=function(){var a=new JSM.Body;JSM.AddVertexToBody(a,1,1,1);JSM.AddVertexToBody(a,1,1,-1);JSM.AddVertexToBody(a,1,-1,1);JSM.AddVertexToBody(a,-1,1,1);JSM.AddVertexToBody(a,1,-1,-1);JSM.AddVertexToBody(a,-1,1,-1);JSM.AddVertexToBody(a,-1,-1,1);JSM.AddVertexToBody(a,-1,-1,-1);JSM.AddPolygonToBody(a,[0,1,5,3]);JSM.AddPolygonToBody(a,[0,2,4,1]);JSM.AddPolygonToBody(a,[0,3,6,2]);JSM.AddPolygonToBody(a,[1,4,7,5]);JSM.AddPolygonToBody(a,[2,6,7,4]);JSM.AddPolygonToBody(a,[3,5,7,6]);
return a};JSM.GenerateOctahedron=function(){var a=new JSM.Body;JSM.AddVertexToBody(a,1,0,0);JSM.AddVertexToBody(a,-1,0,0);JSM.AddVertexToBody(a,0,1,0);JSM.AddVertexToBody(a,0,-1,0);JSM.AddVertexToBody(a,0,0,1);JSM.AddVertexToBody(a,0,0,-1);JSM.AddPolygonToBody(a,[0,2,4]);JSM.AddPolygonToBody(a,[0,3,5]);JSM.AddPolygonToBody(a,[0,4,3]);JSM.AddPolygonToBody(a,[0,5,2]);JSM.AddPolygonToBody(a,[1,2,5]);JSM.AddPolygonToBody(a,[1,3,4]);JSM.AddPolygonToBody(a,[1,4,2]);JSM.AddPolygonToBody(a,[1,5,3]);return a};
JSM.GenerateDodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=1/b;JSM.AddVertexToBody(a,1,1,1);JSM.AddVertexToBody(a,1,1,-1);JSM.AddVertexToBody(a,1,-1,1);JSM.AddVertexToBody(a,-1,1,1);JSM.AddVertexToBody(a,1,-1,-1);JSM.AddVertexToBody(a,-1,1,-1);JSM.AddVertexToBody(a,-1,-1,1);JSM.AddVertexToBody(a,-1,-1,-1);JSM.AddVertexToBody(a,0,+c,+b);JSM.AddVertexToBody(a,0,+c,-b);JSM.AddVertexToBody(a,0,-c,+b);JSM.AddVertexToBody(a,0,-c,-b);JSM.AddVertexToBody(a,+c,+b,0);JSM.AddVertexToBody(a,
+c,-b,0);JSM.AddVertexToBody(a,-c,+b,0);JSM.AddVertexToBody(a,-c,-b,0);JSM.AddVertexToBody(a,+b,0,+c);JSM.AddVertexToBody(a,-b,0,+c);JSM.AddVertexToBody(a,+b,0,-c);JSM.AddVertexToBody(a,-b,0,-c);JSM.AddPolygonToBody(a,[0,8,10,2,16]);JSM.AddPolygonToBody(a,[0,16,18,1,12]);JSM.AddPolygonToBody(a,[0,12,14,3,8]);JSM.AddPolygonToBody(a,[1,9,5,14,12]);JSM.AddPolygonToBody(a,[1,18,4,11,9]);JSM.AddPolygonToBody(a,[2,10,6,15,13]);JSM.AddPolygonToBody(a,[2,13,4,18,16]);JSM.AddPolygonToBody(a,[3,14,5,19,17]);
JSM.AddPolygonToBody(a,[3,17,6,10,8]);JSM.AddPolygonToBody(a,[4,13,15,7,11]);JSM.AddPolygonToBody(a,[5,9,11,7,19]);JSM.AddPolygonToBody(a,[6,17,19,7,15]);return a};
JSM.GenerateIcosahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2;JSM.AddVertexToBody(a,0,1,+b);JSM.AddVertexToBody(a,0,1,-b);JSM.AddVertexToBody(a,0,-1,+b);JSM.AddVertexToBody(a,0,-1,-b);JSM.AddVertexToBody(a,1,+b,0);JSM.AddVertexToBody(a,1,-b,0);JSM.AddVertexToBody(a,-1,+b,0);JSM.AddVertexToBody(a,-1,-b,0);JSM.AddVertexToBody(a,+b,0,1);JSM.AddVertexToBody(a,-b,0,1);JSM.AddVertexToBody(a,+b,0,-1);JSM.AddVertexToBody(a,-b,0,-1);JSM.AddPolygonToBody(a,[0,2,8]);JSM.AddPolygonToBody(a,[0,4,
6]);JSM.AddPolygonToBody(a,[0,6,9]);JSM.AddPolygonToBody(a,[0,8,4]);JSM.AddPolygonToBody(a,[0,9,2]);JSM.AddPolygonToBody(a,[1,3,11]);JSM.AddPolygonToBody(a,[1,4,10]);JSM.AddPolygonToBody(a,[1,6,4]);JSM.AddPolygonToBody(a,[1,10,3]);JSM.AddPolygonToBody(a,[1,11,6]);JSM.AddPolygonToBody(a,[2,5,8]);JSM.AddPolygonToBody(a,[2,7,5]);JSM.AddPolygonToBody(a,[2,9,7]);JSM.AddPolygonToBody(a,[3,5,7]);JSM.AddPolygonToBody(a,[3,7,11]);JSM.AddPolygonToBody(a,[3,10,5]);JSM.AddPolygonToBody(a,[4,8,10]);JSM.AddPolygonToBody(a,
[6,11,9]);JSM.AddPolygonToBody(a,[5,10,8]);JSM.AddPolygonToBody(a,[7,9,11]);return a};
JSM.GenerateTruncatedTetrahedron=function(){var a=new JSM.Body;JSM.AddVertexToBody(a,1,1,3);JSM.AddVertexToBody(a,1,-1,-3);JSM.AddVertexToBody(a,-1,-1,3);JSM.AddVertexToBody(a,-1,1,-3);JSM.AddVertexToBody(a,1,3,1);JSM.AddVertexToBody(a,1,-3,-1);JSM.AddVertexToBody(a,-1,-3,1);JSM.AddVertexToBody(a,-1,3,-1);JSM.AddVertexToBody(a,3,1,1);JSM.AddVertexToBody(a,3,-1,-1);JSM.AddVertexToBody(a,-3,-1,1);JSM.AddVertexToBody(a,-3,1,-1);JSM.AddPolygonToBody(a,[0,8,4]);JSM.AddPolygonToBody(a,[1,9,5]);JSM.AddPolygonToBody(a,
[2,10,6]);JSM.AddPolygonToBody(a,[3,11,7]);JSM.AddPolygonToBody(a,[0,2,6,5,9,8]);JSM.AddPolygonToBody(a,[0,4,7,11,10,2]);JSM.AddPolygonToBody(a,[1,3,7,4,8,9]);JSM.AddPolygonToBody(a,[1,5,6,10,11,3]);return a};
JSM.GenerateCuboctahedron=function(){var a=new JSM.Body;JSM.AddVertexToBody(a,1,1,0);JSM.AddVertexToBody(a,1,-1,0);JSM.AddVertexToBody(a,-1,-1,0);JSM.AddVertexToBody(a,-1,1,0);JSM.AddVertexToBody(a,1,0,1);JSM.AddVertexToBody(a,1,0,-1);JSM.AddVertexToBody(a,-1,0,1);JSM.AddVertexToBody(a,-1,0,-1);JSM.AddVertexToBody(a,0,1,1);JSM.AddVertexToBody(a,0,-1,-1);JSM.AddVertexToBody(a,0,-1,1);JSM.AddVertexToBody(a,0,1,-1);JSM.AddPolygonToBody(a,[0,5,11]);JSM.AddPolygonToBody(a,[0,8,4]);JSM.AddPolygonToBody(a,
[1,4,10]);JSM.AddPolygonToBody(a,[1,9,5]);JSM.AddPolygonToBody(a,[2,7,9]);JSM.AddPolygonToBody(a,[2,10,6]);JSM.AddPolygonToBody(a,[3,6,8]);JSM.AddPolygonToBody(a,[3,11,7]);JSM.AddPolygonToBody(a,[0,4,1,5]);JSM.AddPolygonToBody(a,[0,11,3,8]);JSM.AddPolygonToBody(a,[1,10,2,9]);JSM.AddPolygonToBody(a,[2,6,3,7]);JSM.AddPolygonToBody(a,[4,8,6,10]);JSM.AddPolygonToBody(a,[5,9,7,11]);return a};
JSM.GenerateTruncatedCube=function(){var a=new JSM.Body,b=Math.sqrt(2)-1;JSM.AddVertexToBody(a,1,1,+b);JSM.AddVertexToBody(a,1,1,-b);JSM.AddVertexToBody(a,1,-1,+b);JSM.AddVertexToBody(a,-1,1,+b);JSM.AddVertexToBody(a,1,-1,-b);JSM.AddVertexToBody(a,-1,1,-b);JSM.AddVertexToBody(a,-1,-1,+b);JSM.AddVertexToBody(a,-1,-1,-b);JSM.AddVertexToBody(a,1,+b,1);JSM.AddVertexToBody(a,1,+b,-1);JSM.AddVertexToBody(a,1,-b,1);JSM.AddVertexToBody(a,-1,+b,1);JSM.AddVertexToBody(a,1,-b,-1);JSM.AddVertexToBody(a,-1,+b,
-1);JSM.AddVertexToBody(a,-1,-b,1);JSM.AddVertexToBody(a,-1,-b,-1);JSM.AddVertexToBody(a,+b,1,1);JSM.AddVertexToBody(a,+b,1,-1);JSM.AddVertexToBody(a,+b,-1,1);JSM.AddVertexToBody(a,-b,1,1);JSM.AddVertexToBody(a,+b,-1,-1);JSM.AddVertexToBody(a,-b,1,-1);JSM.AddVertexToBody(a,-b,-1,1);JSM.AddVertexToBody(a,-b,-1,-1);JSM.AddPolygonToBody(a,[0,16,8]);JSM.AddPolygonToBody(a,[1,9,17]);JSM.AddPolygonToBody(a,[2,10,18]);JSM.AddPolygonToBody(a,[3,11,19]);JSM.AddPolygonToBody(a,[4,20,12]);JSM.AddPolygonToBody(a,
[5,21,13]);JSM.AddPolygonToBody(a,[6,22,14]);JSM.AddPolygonToBody(a,[7,15,23]);JSM.AddPolygonToBody(a,[0,1,17,21,5,3,19,16]);JSM.AddPolygonToBody(a,[0,8,10,2,4,12,9,1]);JSM.AddPolygonToBody(a,[2,18,22,6,7,23,20,4]);JSM.AddPolygonToBody(a,[3,5,13,15,7,6,14,11]);JSM.AddPolygonToBody(a,[8,16,19,11,14,22,18,10]);JSM.AddPolygonToBody(a,[9,12,20,23,15,13,21,17]);return a};
JSM.GenerateTruncatedOctahedron=function(){var a=new JSM.Body;JSM.AddVertexToBody(a,0,1,2);JSM.AddVertexToBody(a,0,1,-2);JSM.AddVertexToBody(a,0,-1,2);JSM.AddVertexToBody(a,0,-1,-2);JSM.AddVertexToBody(a,0,2,1);JSM.AddVertexToBody(a,0,-2,1);JSM.AddVertexToBody(a,0,2,-1);JSM.AddVertexToBody(a,0,-2,-1);JSM.AddVertexToBody(a,1,0,2);JSM.AddVertexToBody(a,1,0,-2);JSM.AddVertexToBody(a,-1,0,2);JSM.AddVertexToBody(a,-1,0,-2);JSM.AddVertexToBody(a,1,2,0);JSM.AddVertexToBody(a,1,-2,0);JSM.AddVertexToBody(a,
-1,2,0);JSM.AddVertexToBody(a,-1,-2,0);JSM.AddVertexToBody(a,2,0,1);JSM.AddVertexToBody(a,-2,0,1);JSM.AddVertexToBody(a,2,0,-1);JSM.AddVertexToBody(a,-2,0,-1);JSM.AddVertexToBody(a,2,1,0);JSM.AddVertexToBody(a,-2,1,0);JSM.AddVertexToBody(a,2,-1,0);JSM.AddVertexToBody(a,-2,-1,0);JSM.AddPolygonToBody(a,[0,10,2,8]);JSM.AddPolygonToBody(a,[1,9,3,11]);JSM.AddPolygonToBody(a,[4,12,6,14]);JSM.AddPolygonToBody(a,[5,15,7,13]);JSM.AddPolygonToBody(a,[16,22,18,20]);JSM.AddPolygonToBody(a,[17,21,19,23]);JSM.AddPolygonToBody(a,
[0,4,14,21,17,10]);JSM.AddPolygonToBody(a,[0,8,16,20,12,4]);JSM.AddPolygonToBody(a,[1,6,12,20,18,9]);JSM.AddPolygonToBody(a,[1,11,19,21,14,6]);JSM.AddPolygonToBody(a,[2,5,13,22,16,8]);JSM.AddPolygonToBody(a,[2,10,17,23,15,5]);JSM.AddPolygonToBody(a,[3,7,15,23,19,11]);JSM.AddPolygonToBody(a,[3,9,18,22,13,7]);return a};
JSM.GenerateRhombicuboctahedron=function(){var a=new JSM.Body,b=1+Math.sqrt(2);JSM.AddVertexToBody(a,1,1,+b);JSM.AddVertexToBody(a,1,1,-b);JSM.AddVertexToBody(a,1,-1,+b);JSM.AddVertexToBody(a,-1,1,+b);JSM.AddVertexToBody(a,1,-1,-b);JSM.AddVertexToBody(a,-1,1,-b);JSM.AddVertexToBody(a,-1,-1,+b);JSM.AddVertexToBody(a,-1,-1,-b);JSM.AddVertexToBody(a,1,+b,1);JSM.AddVertexToBody(a,1,+b,-1);JSM.AddVertexToBody(a,1,-b,1);JSM.AddVertexToBody(a,-1,+b,1);JSM.AddVertexToBody(a,1,-b,-1);JSM.AddVertexToBody(a,
-1,+b,-1);JSM.AddVertexToBody(a,-1,-b,1);JSM.AddVertexToBody(a,-1,-b,-1);JSM.AddVertexToBody(a,+b,1,1);JSM.AddVertexToBody(a,+b,1,-1);JSM.AddVertexToBody(a,+b,-1,1);JSM.AddVertexToBody(a,-b,1,1);JSM.AddVertexToBody(a,+b,-1,-1);JSM.AddVertexToBody(a,-b,1,-1);JSM.AddVertexToBody(a,-b,-1,1);JSM.AddVertexToBody(a,-b,-1,-1);JSM.AddPolygonToBody(a,[0,16,8]);JSM.AddPolygonToBody(a,[1,9,17]);JSM.AddPolygonToBody(a,[2,10,18]);JSM.AddPolygonToBody(a,[3,11,19]);JSM.AddPolygonToBody(a,[4,20,12]);JSM.AddPolygonToBody(a,
[5,21,13]);JSM.AddPolygonToBody(a,[6,22,14]);JSM.AddPolygonToBody(a,[7,15,23]);JSM.AddPolygonToBody(a,[0,2,18,16]);JSM.AddPolygonToBody(a,[0,3,6,2]);JSM.AddPolygonToBody(a,[0,8,11,3]);JSM.AddPolygonToBody(a,[1,4,7,5]);JSM.AddPolygonToBody(a,[1,5,13,9]);JSM.AddPolygonToBody(a,[1,17,20,4]);JSM.AddPolygonToBody(a,[2,6,14,10]);JSM.AddPolygonToBody(a,[3,19,22,6]);JSM.AddPolygonToBody(a,[4,12,15,7]);JSM.AddPolygonToBody(a,[5,7,23,21]);JSM.AddPolygonToBody(a,[8,9,13,11]);JSM.AddPolygonToBody(a,[8,16,17,
9]);JSM.AddPolygonToBody(a,[10,12,20,18]);JSM.AddPolygonToBody(a,[10,14,15,12]);JSM.AddPolygonToBody(a,[11,13,21,19]);JSM.AddPolygonToBody(a,[14,22,23,15]);JSM.AddPolygonToBody(a,[16,18,20,17]);JSM.AddPolygonToBody(a,[19,21,23,22]);return a};
JSM.GenerateTruncatedCuboctahedron=function(){var a=new JSM.Body,b=1+Math.sqrt(2),c=1+2*Math.sqrt(2);JSM.AddVertexToBody(a,1,+b,+c);JSM.AddVertexToBody(a,1,+b,-c);JSM.AddVertexToBody(a,1,-b,+c);JSM.AddVertexToBody(a,-1,+b,+c);JSM.AddVertexToBody(a,1,-b,-c);JSM.AddVertexToBody(a,-1,+b,-c);JSM.AddVertexToBody(a,-1,-b,+c);JSM.AddVertexToBody(a,-1,-b,-c);JSM.AddVertexToBody(a,1,+c,+b);JSM.AddVertexToBody(a,1,-c,+b);JSM.AddVertexToBody(a,1,+c,-b);JSM.AddVertexToBody(a,-1,+c,+b);JSM.AddVertexToBody(a,1,
-c,-b);JSM.AddVertexToBody(a,-1,-c,+b);JSM.AddVertexToBody(a,-1,+c,-b);JSM.AddVertexToBody(a,-1,-c,-b);JSM.AddVertexToBody(a,+b,1,+c);JSM.AddVertexToBody(a,+b,1,-c);JSM.AddVertexToBody(a,-b,1,+c);JSM.AddVertexToBody(a,+b,-1,+c);JSM.AddVertexToBody(a,-b,1,-c);JSM.AddVertexToBody(a,+b,-1,-c);JSM.AddVertexToBody(a,-b,-1,+c);JSM.AddVertexToBody(a,-b,-1,-c);JSM.AddVertexToBody(a,+b,+c,1);JSM.AddVertexToBody(a,+b,-c,1);JSM.AddVertexToBody(a,-b,+c,1);JSM.AddVertexToBody(a,+b,+c,-1);JSM.AddVertexToBody(a,
-b,-c,1);JSM.AddVertexToBody(a,+b,-c,-1);JSM.AddVertexToBody(a,-b,+c,-1);JSM.AddVertexToBody(a,-b,-c,-1);JSM.AddVertexToBody(a,+c,1,+b);JSM.AddVertexToBody(a,-c,1,+b);JSM.AddVertexToBody(a,+c,1,-b);JSM.AddVertexToBody(a,+c,-1,+b);JSM.AddVertexToBody(a,-c,1,-b);JSM.AddVertexToBody(a,-c,-1,+b);JSM.AddVertexToBody(a,+c,-1,-b);JSM.AddVertexToBody(a,-c,-1,-b);JSM.AddVertexToBody(a,+c,+b,1);JSM.AddVertexToBody(a,-c,+b,1);JSM.AddVertexToBody(a,+c,-b,1);JSM.AddVertexToBody(a,+c,+b,-1);JSM.AddVertexToBody(a,
-c,-b,1);JSM.AddVertexToBody(a,-c,+b,-1);JSM.AddVertexToBody(a,+c,-b,-1);JSM.AddVertexToBody(a,-c,-b,-1);JSM.AddPolygonToBody(a,[0,8,11,3]);JSM.AddPolygonToBody(a,[1,5,14,10]);JSM.AddPolygonToBody(a,[2,6,13,9]);JSM.AddPolygonToBody(a,[4,12,15,7]);JSM.AddPolygonToBody(a,[16,19,35,32]);JSM.AddPolygonToBody(a,[17,34,38,21]);JSM.AddPolygonToBody(a,[18,33,37,22]);JSM.AddPolygonToBody(a,[23,39,36,20]);JSM.AddPolygonToBody(a,[24,40,43,27]);JSM.AddPolygonToBody(a,[25,29,46,42]);JSM.AddPolygonToBody(a,[26,
30,45,41]);JSM.AddPolygonToBody(a,[28,44,47,31]);JSM.AddPolygonToBody(a,[0,16,32,40,24,8]);JSM.AddPolygonToBody(a,[1,10,27,43,34,17]);JSM.AddPolygonToBody(a,[2,9,25,42,35,19]);JSM.AddPolygonToBody(a,[3,11,26,41,33,18]);JSM.AddPolygonToBody(a,[4,21,38,46,29,12]);JSM.AddPolygonToBody(a,[5,20,36,45,30,14]);JSM.AddPolygonToBody(a,[6,22,37,44,28,13]);JSM.AddPolygonToBody(a,[7,15,31,47,39,23]);JSM.AddPolygonToBody(a,[0,3,18,22,6,2,19,16]);JSM.AddPolygonToBody(a,[1,17,21,4,7,23,20,5]);JSM.AddPolygonToBody(a,
[8,24,27,10,14,30,26,11]);JSM.AddPolygonToBody(a,[9,13,28,31,15,12,29,25]);JSM.AddPolygonToBody(a,[32,35,42,46,38,34,43,40]);JSM.AddPolygonToBody(a,[33,41,45,36,39,47,44,37]);return a};
JSM.GenerateSnubCube=function(){var a=new JSM.Body,b=1/3*(Math.pow(17+3*Math.sqrt(33),1/3)-Math.pow(-17+3*Math.sqrt(33),1/3)-1),c=1/b;JSM.AddVertexToBody(a,1,+b,-c);JSM.AddVertexToBody(a,1,-b,+c);JSM.AddVertexToBody(a,-1,+b,+c);JSM.AddVertexToBody(a,-1,-b,-c);JSM.AddVertexToBody(a,+b,-c,1);JSM.AddVertexToBody(a,-b,+c,1);JSM.AddVertexToBody(a,+b,+c,-1);JSM.AddVertexToBody(a,-b,-c,-1);JSM.AddVertexToBody(a,-c,1,+b);JSM.AddVertexToBody(a,+c,1,-b);JSM.AddVertexToBody(a,+c,-1,+b);JSM.AddVertexToBody(a,
-c,-1,-b);JSM.AddVertexToBody(a,1,+c,+b);JSM.AddVertexToBody(a,1,-c,-b);JSM.AddVertexToBody(a,-1,+c,-b);JSM.AddVertexToBody(a,-1,-c,+b);JSM.AddVertexToBody(a,+b,1,+c);JSM.AddVertexToBody(a,-b,1,-c);JSM.AddVertexToBody(a,-b,-1,+c);JSM.AddVertexToBody(a,+b,-1,-c);JSM.AddVertexToBody(a,+c,+b,1);JSM.AddVertexToBody(a,-c,-b,1);JSM.AddVertexToBody(a,+c,-b,-1);JSM.AddVertexToBody(a,-c,+b,-1);JSM.AddPolygonToBody(a,[0,6,9]);JSM.AddPolygonToBody(a,[0,9,22]);JSM.AddPolygonToBody(a,[0,17,6]);JSM.AddPolygonToBody(a,
[0,22,19]);JSM.AddPolygonToBody(a,[1,4,10]);JSM.AddPolygonToBody(a,[1,10,20]);JSM.AddPolygonToBody(a,[1,18,4]);JSM.AddPolygonToBody(a,[1,20,16]);JSM.AddPolygonToBody(a,[2,5,8]);JSM.AddPolygonToBody(a,[2,8,21]);JSM.AddPolygonToBody(a,[2,16,5]);JSM.AddPolygonToBody(a,[2,21,18]);JSM.AddPolygonToBody(a,[3,7,11]);JSM.AddPolygonToBody(a,[3,11,23]);JSM.AddPolygonToBody(a,[3,19,7]);JSM.AddPolygonToBody(a,[3,23,17]);JSM.AddPolygonToBody(a,[4,13,10]);JSM.AddPolygonToBody(a,[4,18,15]);JSM.AddPolygonToBody(a,
[5,14,8]);JSM.AddPolygonToBody(a,[5,16,12]);JSM.AddPolygonToBody(a,[6,12,9]);JSM.AddPolygonToBody(a,[6,17,14]);JSM.AddPolygonToBody(a,[7,15,11]);JSM.AddPolygonToBody(a,[7,19,13]);JSM.AddPolygonToBody(a,[8,14,23]);JSM.AddPolygonToBody(a,[9,12,20]);JSM.AddPolygonToBody(a,[10,13,22]);JSM.AddPolygonToBody(a,[11,15,21]);JSM.AddPolygonToBody(a,[12,16,20]);JSM.AddPolygonToBody(a,[13,19,22]);JSM.AddPolygonToBody(a,[14,17,23]);JSM.AddPolygonToBody(a,[15,18,21]);JSM.AddPolygonToBody(a,[0,19,3,17]);JSM.AddPolygonToBody(a,
[1,16,2,18]);JSM.AddPolygonToBody(a,[4,15,7,13]);JSM.AddPolygonToBody(a,[5,12,6,14]);JSM.AddPolygonToBody(a,[8,23,11,21]);JSM.AddPolygonToBody(a,[9,20,10,22]);return a};
JSM.GenerateIcosidodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=b/2,d=(1+b)/2;JSM.AddVertexToBody(a,0,0,+b);JSM.AddVertexToBody(a,0,0,-b);JSM.AddVertexToBody(a,0,+b,0);JSM.AddVertexToBody(a,0,-b,0);JSM.AddVertexToBody(a,+b,0,0);JSM.AddVertexToBody(a,-b,0,0);JSM.AddVertexToBody(a,0.5,+c,+d);JSM.AddVertexToBody(a,0.5,+c,-d);JSM.AddVertexToBody(a,0.5,-c,+d);JSM.AddVertexToBody(a,-0.5,+c,+d);JSM.AddVertexToBody(a,0.5,-c,-d);JSM.AddVertexToBody(a,-0.5,+c,-d);JSM.AddVertexToBody(a,-0.5,
-c,+d);JSM.AddVertexToBody(a,-0.5,-c,-d);JSM.AddVertexToBody(a,+c,+d,0.5);JSM.AddVertexToBody(a,+c,-d,0.5);JSM.AddVertexToBody(a,-c,+d,0.5);JSM.AddVertexToBody(a,+c,+d,-0.5);JSM.AddVertexToBody(a,-c,-d,0.5);JSM.AddVertexToBody(a,+c,-d,-0.5);JSM.AddVertexToBody(a,-c,+d,-0.5);JSM.AddVertexToBody(a,-c,-d,-0.5);JSM.AddVertexToBody(a,+d,0.5,+c);JSM.AddVertexToBody(a,-d,0.5,+c);JSM.AddVertexToBody(a,+d,0.5,-c);JSM.AddVertexToBody(a,+d,-0.5,+c);JSM.AddVertexToBody(a,-d,0.5,-c);JSM.AddVertexToBody(a,-d,-0.5,
+c);JSM.AddVertexToBody(a,+d,-0.5,-c);JSM.AddVertexToBody(a,-d,-0.5,-c);JSM.AddPolygonToBody(a,[0,6,9]);JSM.AddPolygonToBody(a,[0,12,8]);JSM.AddPolygonToBody(a,[1,10,13]);JSM.AddPolygonToBody(a,[1,11,7]);JSM.AddPolygonToBody(a,[2,14,17]);JSM.AddPolygonToBody(a,[2,20,16]);JSM.AddPolygonToBody(a,[3,18,21]);JSM.AddPolygonToBody(a,[3,19,15]);JSM.AddPolygonToBody(a,[4,22,25]);JSM.AddPolygonToBody(a,[4,28,24]);JSM.AddPolygonToBody(a,[5,26,29]);JSM.AddPolygonToBody(a,[5,27,23]);JSM.AddPolygonToBody(a,[6,
22,14]);JSM.AddPolygonToBody(a,[7,17,24]);JSM.AddPolygonToBody(a,[8,15,25]);JSM.AddPolygonToBody(a,[9,16,23]);JSM.AddPolygonToBody(a,[10,28,19]);JSM.AddPolygonToBody(a,[11,26,20]);JSM.AddPolygonToBody(a,[12,27,18]);JSM.AddPolygonToBody(a,[13,21,29]);JSM.AddPolygonToBody(a,[0,8,25,22,6]);JSM.AddPolygonToBody(a,[0,9,23,27,12]);JSM.AddPolygonToBody(a,[1,7,24,28,10]);JSM.AddPolygonToBody(a,[1,13,29,26,11]);JSM.AddPolygonToBody(a,[2,16,9,6,14]);JSM.AddPolygonToBody(a,[2,17,7,11,20]);JSM.AddPolygonToBody(a,
[3,15,8,12,18]);JSM.AddPolygonToBody(a,[3,21,13,10,19]);JSM.AddPolygonToBody(a,[4,24,17,14,22]);JSM.AddPolygonToBody(a,[4,25,15,19,28]);JSM.AddPolygonToBody(a,[5,23,16,20,26]);JSM.AddPolygonToBody(a,[5,29,21,18,27]);return a};
JSM.GenerateTruncatedDodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=1/b,d=2+b,e=2*b,f=Math.pow(b,2);JSM.AddVertexToBody(a,0,+c,+d);JSM.AddVertexToBody(a,0,+c,-d);JSM.AddVertexToBody(a,0,-c,+d);JSM.AddVertexToBody(a,0,-c,-d);JSM.AddVertexToBody(a,+d,0,+c);JSM.AddVertexToBody(a,-d,0,+c);JSM.AddVertexToBody(a,+d,0,-c);JSM.AddVertexToBody(a,-d,0,-c);JSM.AddVertexToBody(a,+c,+d,0);JSM.AddVertexToBody(a,+c,-d,0);JSM.AddVertexToBody(a,-c,+d,0);JSM.AddVertexToBody(a,-c,-d,0);JSM.AddVertexToBody(a,
+c,+b,+e);JSM.AddVertexToBody(a,+c,+b,-e);JSM.AddVertexToBody(a,+c,-b,+e);JSM.AddVertexToBody(a,-c,+b,+e);JSM.AddVertexToBody(a,+c,-b,-e);JSM.AddVertexToBody(a,-c,+b,-e);JSM.AddVertexToBody(a,-c,-b,+e);JSM.AddVertexToBody(a,-c,-b,-e);JSM.AddVertexToBody(a,+e,+c,+b);JSM.AddVertexToBody(a,+e,+c,-b);JSM.AddVertexToBody(a,+e,-c,+b);JSM.AddVertexToBody(a,-e,+c,+b);JSM.AddVertexToBody(a,+e,-c,-b);JSM.AddVertexToBody(a,-e,+c,-b);JSM.AddVertexToBody(a,-e,-c,+b);JSM.AddVertexToBody(a,-e,-c,-b);JSM.AddVertexToBody(a,
+b,+e,+c);JSM.AddVertexToBody(a,+b,+e,-c);JSM.AddVertexToBody(a,+b,-e,+c);JSM.AddVertexToBody(a,-b,+e,+c);JSM.AddVertexToBody(a,+b,-e,-c);JSM.AddVertexToBody(a,-b,+e,-c);JSM.AddVertexToBody(a,-b,-e,+c);JSM.AddVertexToBody(a,-b,-e,-c);JSM.AddVertexToBody(a,+b,2,+f);JSM.AddVertexToBody(a,+b,2,-f);JSM.AddVertexToBody(a,+b,-2,+f);JSM.AddVertexToBody(a,-b,2,+f);JSM.AddVertexToBody(a,+b,-2,-f);JSM.AddVertexToBody(a,-b,2,-f);JSM.AddVertexToBody(a,-b,-2,+f);JSM.AddVertexToBody(a,-b,-2,-f);JSM.AddVertexToBody(a,
+f,+b,2);JSM.AddVertexToBody(a,+f,+b,-2);JSM.AddVertexToBody(a,+f,-b,2);JSM.AddVertexToBody(a,-f,+b,2);JSM.AddVertexToBody(a,+f,-b,-2);JSM.AddVertexToBody(a,-f,+b,-2);JSM.AddVertexToBody(a,-f,-b,2);JSM.AddVertexToBody(a,-f,-b,-2);JSM.AddVertexToBody(a,2,+f,+b);JSM.AddVertexToBody(a,2,+f,-b);JSM.AddVertexToBody(a,2,-f,+b);JSM.AddVertexToBody(a,-2,+f,+b);JSM.AddVertexToBody(a,2,-f,-b);JSM.AddVertexToBody(a,-2,+f,-b);JSM.AddVertexToBody(a,-2,-f,+b);JSM.AddVertexToBody(a,-2,-f,-b);JSM.AddPolygonToBody(a,
[0,12,15]);JSM.AddPolygonToBody(a,[1,17,13]);JSM.AddPolygonToBody(a,[2,18,14]);JSM.AddPolygonToBody(a,[3,16,19]);JSM.AddPolygonToBody(a,[4,20,22]);JSM.AddPolygonToBody(a,[5,26,23]);JSM.AddPolygonToBody(a,[6,24,21]);JSM.AddPolygonToBody(a,[7,25,27]);JSM.AddPolygonToBody(a,[8,28,29]);JSM.AddPolygonToBody(a,[9,32,30]);JSM.AddPolygonToBody(a,[10,33,31]);JSM.AddPolygonToBody(a,[11,34,35]);JSM.AddPolygonToBody(a,[36,44,52]);JSM.AddPolygonToBody(a,[37,53,45]);JSM.AddPolygonToBody(a,[38,54,46]);JSM.AddPolygonToBody(a,
[39,55,47]);JSM.AddPolygonToBody(a,[40,48,56]);JSM.AddPolygonToBody(a,[41,49,57]);JSM.AddPolygonToBody(a,[42,50,58]);JSM.AddPolygonToBody(a,[43,59,51]);JSM.AddPolygonToBody(a,[0,2,14,38,46,22,20,44,36,12]);JSM.AddPolygonToBody(a,[0,15,39,47,23,26,50,42,18,2]);JSM.AddPolygonToBody(a,[1,3,19,43,51,27,25,49,41,17]);JSM.AddPolygonToBody(a,[1,13,37,45,21,24,48,40,16,3]);JSM.AddPolygonToBody(a,[4,6,21,45,53,29,28,52,44,20]);JSM.AddPolygonToBody(a,[4,22,46,54,30,32,56,48,24,6]);JSM.AddPolygonToBody(a,[5,
7,27,51,59,35,34,58,50,26]);JSM.AddPolygonToBody(a,[5,23,47,55,31,33,57,49,25,7]);JSM.AddPolygonToBody(a,[8,10,31,55,39,15,12,36,52,28]);JSM.AddPolygonToBody(a,[8,29,53,37,13,17,41,57,33,10]);JSM.AddPolygonToBody(a,[9,11,35,59,43,19,16,40,56,32]);JSM.AddPolygonToBody(a,[9,30,54,38,14,18,42,58,34,11]);return a};
JSM.GenerateTruncatedIcosahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=3*b,d=1+2*b,e=2+b,f=2*b;JSM.AddVertexToBody(a,0,1,+c);JSM.AddVertexToBody(a,0,1,-c);JSM.AddVertexToBody(a,0,-1,+c);JSM.AddVertexToBody(a,0,-1,-c);JSM.AddVertexToBody(a,1,+c,0);JSM.AddVertexToBody(a,1,-c,0);JSM.AddVertexToBody(a,-1,+c,0);JSM.AddVertexToBody(a,-1,-c,0);JSM.AddVertexToBody(a,+c,0,1);JSM.AddVertexToBody(a,-c,0,1);JSM.AddVertexToBody(a,+c,0,-1);JSM.AddVertexToBody(a,-c,0,-1);JSM.AddVertexToBody(a,2,+d,
+b);JSM.AddVertexToBody(a,2,+d,-b);JSM.AddVertexToBody(a,2,-d,+b);JSM.AddVertexToBody(a,-2,+d,+b);JSM.AddVertexToBody(a,2,-d,-b);JSM.AddVertexToBody(a,-2,+d,-b);JSM.AddVertexToBody(a,-2,-d,+b);JSM.AddVertexToBody(a,-2,-d,-b);JSM.AddVertexToBody(a,+d,+b,2);JSM.AddVertexToBody(a,+d,-b,2);JSM.AddVertexToBody(a,-d,+b,2);JSM.AddVertexToBody(a,+d,+b,-2);JSM.AddVertexToBody(a,-d,-b,2);JSM.AddVertexToBody(a,+d,-b,-2);JSM.AddVertexToBody(a,-d,+b,-2);JSM.AddVertexToBody(a,-d,-b,-2);JSM.AddVertexToBody(a,+b,
2,+d);JSM.AddVertexToBody(a,-b,2,+d);JSM.AddVertexToBody(a,+b,2,-d);JSM.AddVertexToBody(a,+b,-2,+d);JSM.AddVertexToBody(a,-b,2,-d);JSM.AddVertexToBody(a,-b,-2,+d);JSM.AddVertexToBody(a,+b,-2,-d);JSM.AddVertexToBody(a,-b,-2,-d);JSM.AddVertexToBody(a,1,+e,+f);JSM.AddVertexToBody(a,1,+e,-f);JSM.AddVertexToBody(a,1,-e,+f);JSM.AddVertexToBody(a,-1,+e,+f);JSM.AddVertexToBody(a,1,-e,-f);JSM.AddVertexToBody(a,-1,+e,-f);JSM.AddVertexToBody(a,-1,-e,+f);JSM.AddVertexToBody(a,-1,-e,-f);JSM.AddVertexToBody(a,
+e,+f,1);JSM.AddVertexToBody(a,+e,-f,1);JSM.AddVertexToBody(a,-e,+f,1);JSM.AddVertexToBody(a,+e,+f,-1);JSM.AddVertexToBody(a,-e,-f,1);JSM.AddVertexToBody(a,+e,-f,-1);JSM.AddVertexToBody(a,-e,+f,-1);JSM.AddVertexToBody(a,-e,-f,-1);JSM.AddVertexToBody(a,+f,1,+e);JSM.AddVertexToBody(a,-f,1,+e);JSM.AddVertexToBody(a,+f,1,-e);JSM.AddVertexToBody(a,+f,-1,+e);JSM.AddVertexToBody(a,-f,1,-e);JSM.AddVertexToBody(a,-f,-1,+e);JSM.AddVertexToBody(a,+f,-1,-e);JSM.AddVertexToBody(a,-f,-1,-e);JSM.AddPolygonToBody(a,
[0,28,36,39,29]);JSM.AddPolygonToBody(a,[1,32,41,37,30]);JSM.AddPolygonToBody(a,[2,33,42,38,31]);JSM.AddPolygonToBody(a,[3,34,40,43,35]);JSM.AddPolygonToBody(a,[4,12,44,47,13]);JSM.AddPolygonToBody(a,[5,16,49,45,14]);JSM.AddPolygonToBody(a,[6,17,50,46,15]);JSM.AddPolygonToBody(a,[7,18,48,51,19]);JSM.AddPolygonToBody(a,[8,20,52,55,21]);JSM.AddPolygonToBody(a,[9,24,57,53,22]);JSM.AddPolygonToBody(a,[10,25,58,54,23]);JSM.AddPolygonToBody(a,[11,26,56,59,27]);JSM.AddPolygonToBody(a,[0,2,31,55,52,28]);
JSM.AddPolygonToBody(a,[0,29,53,57,33,2]);JSM.AddPolygonToBody(a,[1,3,35,59,56,32]);JSM.AddPolygonToBody(a,[1,30,54,58,34,3]);JSM.AddPolygonToBody(a,[4,6,15,39,36,12]);JSM.AddPolygonToBody(a,[4,13,37,41,17,6]);JSM.AddPolygonToBody(a,[5,7,19,43,40,16]);JSM.AddPolygonToBody(a,[5,14,38,42,18,7]);JSM.AddPolygonToBody(a,[8,10,23,47,44,20]);JSM.AddPolygonToBody(a,[8,21,45,49,25,10]);JSM.AddPolygonToBody(a,[9,11,27,51,48,24]);JSM.AddPolygonToBody(a,[9,22,46,50,26,11]);JSM.AddPolygonToBody(a,[12,36,28,52,
20,44]);JSM.AddPolygonToBody(a,[13,47,23,54,30,37]);JSM.AddPolygonToBody(a,[14,45,21,55,31,38]);JSM.AddPolygonToBody(a,[15,46,22,53,29,39]);JSM.AddPolygonToBody(a,[16,40,34,58,25,49]);JSM.AddPolygonToBody(a,[17,41,32,56,26,50]);JSM.AddPolygonToBody(a,[18,42,33,57,24,48]);JSM.AddPolygonToBody(a,[19,51,27,59,35,43]);return a};
JSM.GenerateRhombicosidodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=Math.pow(b,2),d=Math.pow(b,3),e=2*b,f=2+b;JSM.AddVertexToBody(a,1,1,+d);JSM.AddVertexToBody(a,1,1,-d);JSM.AddVertexToBody(a,1,-1,+d);JSM.AddVertexToBody(a,-1,1,+d);JSM.AddVertexToBody(a,1,-1,-d);JSM.AddVertexToBody(a,-1,1,-d);JSM.AddVertexToBody(a,-1,-1,+d);JSM.AddVertexToBody(a,-1,-1,-d);JSM.AddVertexToBody(a,+d,1,1);JSM.AddVertexToBody(a,+d,1,-1);JSM.AddVertexToBody(a,+d,-1,1);JSM.AddVertexToBody(a,-d,1,1);JSM.AddVertexToBody(a,
+d,-1,-1);JSM.AddVertexToBody(a,-d,1,-1);JSM.AddVertexToBody(a,-d,-1,1);JSM.AddVertexToBody(a,-d,-1,-1);JSM.AddVertexToBody(a,1,+d,1);JSM.AddVertexToBody(a,1,+d,-1);JSM.AddVertexToBody(a,1,-d,1);JSM.AddVertexToBody(a,-1,+d,1);JSM.AddVertexToBody(a,1,-d,-1);JSM.AddVertexToBody(a,-1,+d,-1);JSM.AddVertexToBody(a,-1,-d,1);JSM.AddVertexToBody(a,-1,-d,-1);JSM.AddVertexToBody(a,+c,+b,+e);JSM.AddVertexToBody(a,+c,+b,-e);JSM.AddVertexToBody(a,+c,-b,+e);JSM.AddVertexToBody(a,-c,+b,+e);JSM.AddVertexToBody(a,
+c,-b,-e);JSM.AddVertexToBody(a,-c,+b,-e);JSM.AddVertexToBody(a,-c,-b,+e);JSM.AddVertexToBody(a,-c,-b,-e);JSM.AddVertexToBody(a,+e,+c,+b);JSM.AddVertexToBody(a,+e,+c,-b);JSM.AddVertexToBody(a,+e,-c,+b);JSM.AddVertexToBody(a,-e,+c,+b);JSM.AddVertexToBody(a,+e,-c,-b);JSM.AddVertexToBody(a,-e,+c,-b);JSM.AddVertexToBody(a,-e,-c,+b);JSM.AddVertexToBody(a,-e,-c,-b);JSM.AddVertexToBody(a,+b,+e,+c);JSM.AddVertexToBody(a,+b,+e,-c);JSM.AddVertexToBody(a,+b,-e,+c);JSM.AddVertexToBody(a,-b,+e,+c);JSM.AddVertexToBody(a,
+b,-e,-c);JSM.AddVertexToBody(a,-b,+e,-c);JSM.AddVertexToBody(a,-b,-e,+c);JSM.AddVertexToBody(a,-b,-e,-c);JSM.AddVertexToBody(a,+f,0,+c);JSM.AddVertexToBody(a,+f,0,-c);JSM.AddVertexToBody(a,-f,0,+c);JSM.AddVertexToBody(a,-f,0,-c);JSM.AddVertexToBody(a,+c,+f,0);JSM.AddVertexToBody(a,-c,+f,0);JSM.AddVertexToBody(a,+c,-f,0);JSM.AddVertexToBody(a,-c,-f,0);JSM.AddVertexToBody(a,0,+c,+f);JSM.AddVertexToBody(a,0,-c,+f);JSM.AddVertexToBody(a,0,+c,-f);JSM.AddVertexToBody(a,0,-c,-f);JSM.AddPolygonToBody(a,
[0,56,3]);JSM.AddPolygonToBody(a,[1,5,58]);JSM.AddPolygonToBody(a,[2,6,57]);JSM.AddPolygonToBody(a,[4,59,7]);JSM.AddPolygonToBody(a,[8,48,10]);JSM.AddPolygonToBody(a,[9,12,49]);JSM.AddPolygonToBody(a,[11,14,50]);JSM.AddPolygonToBody(a,[13,51,15]);JSM.AddPolygonToBody(a,[16,52,17]);JSM.AddPolygonToBody(a,[18,20,54]);JSM.AddPolygonToBody(a,[19,21,53]);JSM.AddPolygonToBody(a,[22,55,23]);JSM.AddPolygonToBody(a,[24,32,40]);JSM.AddPolygonToBody(a,[25,41,33]);JSM.AddPolygonToBody(a,[26,42,34]);JSM.AddPolygonToBody(a,
[27,43,35]);JSM.AddPolygonToBody(a,[28,36,44]);JSM.AddPolygonToBody(a,[29,37,45]);JSM.AddPolygonToBody(a,[30,38,46]);JSM.AddPolygonToBody(a,[31,47,39]);JSM.AddPolygonToBody(a,[0,3,6,2]);JSM.AddPolygonToBody(a,[0,24,40,56]);JSM.AddPolygonToBody(a,[1,4,7,5]);JSM.AddPolygonToBody(a,[1,58,41,25]);JSM.AddPolygonToBody(a,[2,57,42,26]);JSM.AddPolygonToBody(a,[3,56,43,27]);JSM.AddPolygonToBody(a,[4,28,44,59]);JSM.AddPolygonToBody(a,[5,29,45,58]);JSM.AddPolygonToBody(a,[6,30,46,57]);JSM.AddPolygonToBody(a,
[7,59,47,31]);JSM.AddPolygonToBody(a,[8,10,12,9]);JSM.AddPolygonToBody(a,[8,32,24,48]);JSM.AddPolygonToBody(a,[9,49,25,33]);JSM.AddPolygonToBody(a,[10,48,26,34]);JSM.AddPolygonToBody(a,[11,13,15,14]);JSM.AddPolygonToBody(a,[11,50,27,35]);JSM.AddPolygonToBody(a,[12,36,28,49]);JSM.AddPolygonToBody(a,[13,37,29,51]);JSM.AddPolygonToBody(a,[14,38,30,50]);JSM.AddPolygonToBody(a,[15,51,31,39]);JSM.AddPolygonToBody(a,[16,17,21,19]);JSM.AddPolygonToBody(a,[16,40,32,52]);JSM.AddPolygonToBody(a,[17,52,33,41]);
JSM.AddPolygonToBody(a,[18,22,23,20]);JSM.AddPolygonToBody(a,[18,54,34,42]);JSM.AddPolygonToBody(a,[19,53,35,43]);JSM.AddPolygonToBody(a,[20,44,36,54]);JSM.AddPolygonToBody(a,[21,45,37,53]);JSM.AddPolygonToBody(a,[22,46,38,55]);JSM.AddPolygonToBody(a,[23,55,39,47]);JSM.AddPolygonToBody(a,[0,2,26,48,24]);JSM.AddPolygonToBody(a,[1,25,49,28,4]);JSM.AddPolygonToBody(a,[3,27,50,30,6]);JSM.AddPolygonToBody(a,[5,7,31,51,29]);JSM.AddPolygonToBody(a,[8,9,33,52,32]);JSM.AddPolygonToBody(a,[10,34,54,36,12]);
JSM.AddPolygonToBody(a,[11,35,53,37,13]);JSM.AddPolygonToBody(a,[14,15,39,55,38]);JSM.AddPolygonToBody(a,[16,19,43,56,40]);JSM.AddPolygonToBody(a,[17,41,58,45,21]);JSM.AddPolygonToBody(a,[18,42,57,46,22]);JSM.AddPolygonToBody(a,[20,23,47,59,44]);return a};
JSM.GenerateTruncatedIcosidodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=1/b,d=3+b,e=2/b,f=1+2*b,g=Math.pow(b,2),h=-1+3*b,l=-1+2*b,k=2+b,m=2*b;JSM.AddVertexToBody(a,+c,+c,+d);JSM.AddVertexToBody(a,+c,+c,-d);JSM.AddVertexToBody(a,+c,-c,+d);JSM.AddVertexToBody(a,-c,+c,+d);JSM.AddVertexToBody(a,+c,-c,-d);JSM.AddVertexToBody(a,-c,+c,-d);JSM.AddVertexToBody(a,-c,-c,+d);JSM.AddVertexToBody(a,-c,-c,-d);JSM.AddVertexToBody(a,+c,+d,+c);JSM.AddVertexToBody(a,+c,-d,+c);JSM.AddVertexToBody(a,
-c,+d,+c);JSM.AddVertexToBody(a,+c,+d,-c);JSM.AddVertexToBody(a,-c,-d,+c);JSM.AddVertexToBody(a,+c,-d,-c);JSM.AddVertexToBody(a,-c,+d,-c);JSM.AddVertexToBody(a,-c,-d,-c);JSM.AddVertexToBody(a,+d,+c,+c);JSM.AddVertexToBody(a,-d,+c,+c);JSM.AddVertexToBody(a,+d,+c,-c);JSM.AddVertexToBody(a,+d,-c,+c);JSM.AddVertexToBody(a,-d,+c,-c);JSM.AddVertexToBody(a,-d,-c,+c);JSM.AddVertexToBody(a,+d,-c,-c);JSM.AddVertexToBody(a,-d,-c,-c);JSM.AddVertexToBody(a,+e,+b,+f);JSM.AddVertexToBody(a,+e,+b,-f);JSM.AddVertexToBody(a,
+e,-b,+f);JSM.AddVertexToBody(a,-e,+b,+f);JSM.AddVertexToBody(a,+e,-b,-f);JSM.AddVertexToBody(a,-e,+b,-f);JSM.AddVertexToBody(a,-e,-b,+f);JSM.AddVertexToBody(a,-e,-b,-f);JSM.AddVertexToBody(a,+b,+f,+e);JSM.AddVertexToBody(a,+b,-f,+e);JSM.AddVertexToBody(a,-b,+f,+e);JSM.AddVertexToBody(a,+b,+f,-e);JSM.AddVertexToBody(a,-b,-f,+e);JSM.AddVertexToBody(a,+b,-f,-e);JSM.AddVertexToBody(a,-b,+f,-e);JSM.AddVertexToBody(a,-b,-f,-e);JSM.AddVertexToBody(a,+f,+e,+b);JSM.AddVertexToBody(a,-f,+e,+b);JSM.AddVertexToBody(a,
+f,+e,-b);JSM.AddVertexToBody(a,+f,-e,+b);JSM.AddVertexToBody(a,-f,+e,-b);JSM.AddVertexToBody(a,-f,-e,+b);JSM.AddVertexToBody(a,+f,-e,-b);JSM.AddVertexToBody(a,-f,-e,-b);JSM.AddVertexToBody(a,+c,+g,+h);JSM.AddVertexToBody(a,+c,+g,-h);JSM.AddVertexToBody(a,+c,-g,+h);JSM.AddVertexToBody(a,-c,+g,+h);JSM.AddVertexToBody(a,+c,-g,-h);JSM.AddVertexToBody(a,-c,+g,-h);JSM.AddVertexToBody(a,-c,-g,+h);JSM.AddVertexToBody(a,-c,-g,-h);JSM.AddVertexToBody(a,+g,+h,+c);JSM.AddVertexToBody(a,+g,-h,+c);JSM.AddVertexToBody(a,
-g,+h,+c);JSM.AddVertexToBody(a,+g,+h,-c);JSM.AddVertexToBody(a,-g,-h,+c);JSM.AddVertexToBody(a,+g,-h,-c);JSM.AddVertexToBody(a,-g,+h,-c);JSM.AddVertexToBody(a,-g,-h,-c);JSM.AddVertexToBody(a,+h,+c,+g);JSM.AddVertexToBody(a,-h,+c,+g);JSM.AddVertexToBody(a,+h,+c,-g);JSM.AddVertexToBody(a,+h,-c,+g);JSM.AddVertexToBody(a,-h,+c,-g);JSM.AddVertexToBody(a,-h,-c,+g);JSM.AddVertexToBody(a,+h,-c,-g);JSM.AddVertexToBody(a,-h,-c,-g);JSM.AddVertexToBody(a,+l,2,+k);JSM.AddVertexToBody(a,+l,2,-k);JSM.AddVertexToBody(a,
+l,-2,+k);JSM.AddVertexToBody(a,-l,2,+k);JSM.AddVertexToBody(a,+l,-2,-k);JSM.AddVertexToBody(a,-l,2,-k);JSM.AddVertexToBody(a,-l,-2,+k);JSM.AddVertexToBody(a,-l,-2,-k);JSM.AddVertexToBody(a,2,+k,+l);JSM.AddVertexToBody(a,2,-k,+l);JSM.AddVertexToBody(a,-2,+k,+l);JSM.AddVertexToBody(a,2,+k,-l);JSM.AddVertexToBody(a,-2,-k,+l);JSM.AddVertexToBody(a,2,-k,-l);JSM.AddVertexToBody(a,-2,+k,-l);JSM.AddVertexToBody(a,-2,-k,-l);JSM.AddVertexToBody(a,+k,+l,2);JSM.AddVertexToBody(a,-k,+l,2);JSM.AddVertexToBody(a,
+k,+l,-2);JSM.AddVertexToBody(a,+k,-l,2);JSM.AddVertexToBody(a,-k,+l,-2);JSM.AddVertexToBody(a,-k,-l,2);JSM.AddVertexToBody(a,+k,-l,-2);JSM.AddVertexToBody(a,-k,-l,-2);JSM.AddVertexToBody(a,+b,3,+m);JSM.AddVertexToBody(a,+b,3,-m);JSM.AddVertexToBody(a,+b,-3,+m);JSM.AddVertexToBody(a,-b,3,+m);JSM.AddVertexToBody(a,+b,-3,-m);JSM.AddVertexToBody(a,-b,3,-m);JSM.AddVertexToBody(a,-b,-3,+m);JSM.AddVertexToBody(a,-b,-3,-m);JSM.AddVertexToBody(a,3,+m,+b);JSM.AddVertexToBody(a,3,-m,+b);JSM.AddVertexToBody(a,
-3,+m,+b);JSM.AddVertexToBody(a,3,+m,-b);JSM.AddVertexToBody(a,-3,-m,+b);JSM.AddVertexToBody(a,3,-m,-b);JSM.AddVertexToBody(a,-3,+m,-b);JSM.AddVertexToBody(a,-3,-m,-b);JSM.AddVertexToBody(a,+m,+b,3);JSM.AddVertexToBody(a,-m,+b,3);JSM.AddVertexToBody(a,+m,+b,-3);JSM.AddVertexToBody(a,+m,-b,3);JSM.AddVertexToBody(a,-m,+b,-3);JSM.AddVertexToBody(a,-m,-b,3);JSM.AddVertexToBody(a,+m,-b,-3);JSM.AddVertexToBody(a,-m,-b,-3);JSM.AddPolygonToBody(a,[0,3,6,2]);JSM.AddPolygonToBody(a,[1,4,7,5]);JSM.AddPolygonToBody(a,
[8,11,14,10]);JSM.AddPolygonToBody(a,[9,12,15,13]);JSM.AddPolygonToBody(a,[16,19,22,18]);JSM.AddPolygonToBody(a,[17,20,23,21]);JSM.AddPolygonToBody(a,[24,72,96,48]);JSM.AddPolygonToBody(a,[25,49,97,73]);JSM.AddPolygonToBody(a,[26,50,98,74]);JSM.AddPolygonToBody(a,[27,51,99,75]);JSM.AddPolygonToBody(a,[28,76,100,52]);JSM.AddPolygonToBody(a,[29,77,101,53]);JSM.AddPolygonToBody(a,[30,78,102,54]);JSM.AddPolygonToBody(a,[31,55,103,79]);JSM.AddPolygonToBody(a,[32,80,104,56]);JSM.AddPolygonToBody(a,[33,
57,105,81]);JSM.AddPolygonToBody(a,[34,58,106,82]);JSM.AddPolygonToBody(a,[35,59,107,83]);JSM.AddPolygonToBody(a,[36,84,108,60]);JSM.AddPolygonToBody(a,[37,85,109,61]);JSM.AddPolygonToBody(a,[38,86,110,62]);JSM.AddPolygonToBody(a,[39,63,111,87]);JSM.AddPolygonToBody(a,[40,88,112,64]);JSM.AddPolygonToBody(a,[41,65,113,89]);JSM.AddPolygonToBody(a,[42,66,114,90]);JSM.AddPolygonToBody(a,[43,67,115,91]);JSM.AddPolygonToBody(a,[44,92,116,68]);JSM.AddPolygonToBody(a,[45,93,117,69]);JSM.AddPolygonToBody(a,
[46,94,118,70]);JSM.AddPolygonToBody(a,[47,71,119,95]);JSM.AddPolygonToBody(a,[0,24,48,51,27,3]);JSM.AddPolygonToBody(a,[1,5,29,53,49,25]);JSM.AddPolygonToBody(a,[2,6,30,54,50,26]);JSM.AddPolygonToBody(a,[4,28,52,55,31,7]);JSM.AddPolygonToBody(a,[8,32,56,59,35,11]);JSM.AddPolygonToBody(a,[9,13,37,61,57,33]);JSM.AddPolygonToBody(a,[10,14,38,62,58,34]);JSM.AddPolygonToBody(a,[12,36,60,63,39,15]);JSM.AddPolygonToBody(a,[16,40,64,67,43,19]);JSM.AddPolygonToBody(a,[17,21,45,69,65,41]);JSM.AddPolygonToBody(a,
[18,22,46,70,66,42]);JSM.AddPolygonToBody(a,[20,44,68,71,47,23]);JSM.AddPolygonToBody(a,[72,112,88,104,80,96]);JSM.AddPolygonToBody(a,[73,97,83,107,90,114]);JSM.AddPolygonToBody(a,[74,98,81,105,91,115]);JSM.AddPolygonToBody(a,[75,99,82,106,89,113]);JSM.AddPolygonToBody(a,[76,118,94,109,85,100]);JSM.AddPolygonToBody(a,[78,117,93,108,84,102]);JSM.AddPolygonToBody(a,[79,103,87,111,95,119]);JSM.AddPolygonToBody(a,[86,101,77,116,92,110]);JSM.AddPolygonToBody(a,[0,2,26,74,115,67,64,112,72,24]);JSM.AddPolygonToBody(a,
[1,25,73,114,66,70,118,76,28,4]);JSM.AddPolygonToBody(a,[3,27,75,113,65,69,117,78,30,6]);JSM.AddPolygonToBody(a,[5,7,31,79,119,71,68,116,77,29]);JSM.AddPolygonToBody(a,[8,10,34,82,99,51,48,96,80,32]);JSM.AddPolygonToBody(a,[9,33,81,98,50,54,102,84,36,12]);JSM.AddPolygonToBody(a,[11,35,83,97,49,53,101,86,38,14]);JSM.AddPolygonToBody(a,[13,15,39,87,103,55,52,100,85,37]);JSM.AddPolygonToBody(a,[16,18,42,90,107,59,56,104,88,40]);JSM.AddPolygonToBody(a,[17,41,89,106,58,62,110,92,44,20]);JSM.AddPolygonToBody(a,
[19,43,91,105,57,61,109,94,46,22]);JSM.AddPolygonToBody(a,[21,23,47,95,111,63,60,108,93,45]);return a};
JSM.GenerateSnubDodecahedron=function(){var a=new JSM.Body,b=(1+Math.sqrt(5))/2,c=Math.pow(b/2+0.5*Math.sqrt(b-5/27),1/3)+Math.pow(b/2-0.5*Math.sqrt(b-5/27),1/3),d=c-1/c,e=c*b+Math.pow(b,2)+b/c,c=2*d,f=2*e,g=d+e/b+b,h=-(d*b)+e+1/b,l=d/b+e*b-1,k=-(d/b)+e*b+1,m=-d+e/b-b,n=d*b+e-1/b,p=-(d/b)+e*b-1,q=d-e/b-b,r=d*b+e+1/b,s=d+e/b-b,x=d*b-e+1/b,b=d/b+e*b+1;JSM.AddVertexToBody(a,+c,2,-f);JSM.AddVertexToBody(a,+c,-2,+f);JSM.AddVertexToBody(a,-c,2,+f);JSM.AddVertexToBody(a,-c,-2,-f);JSM.AddVertexToBody(a,2,
-f,+c);JSM.AddVertexToBody(a,-2,+f,+c);JSM.AddVertexToBody(a,2,+f,-c);JSM.AddVertexToBody(a,-2,-f,-c);JSM.AddVertexToBody(a,-f,+c,2);JSM.AddVertexToBody(a,+f,+c,-2);JSM.AddVertexToBody(a,+f,-c,2);JSM.AddVertexToBody(a,-f,-c,-2);JSM.AddVertexToBody(a,+g,+h,-l);JSM.AddVertexToBody(a,+g,-h,+l);JSM.AddVertexToBody(a,-g,+h,+l);JSM.AddVertexToBody(a,-g,-h,-l);JSM.AddVertexToBody(a,+h,-l,+g);JSM.AddVertexToBody(a,-h,+l,+g);JSM.AddVertexToBody(a,+h,+l,-g);JSM.AddVertexToBody(a,-h,-l,-g);JSM.AddVertexToBody(a,
-l,+g,+h);JSM.AddVertexToBody(a,+l,+g,-h);JSM.AddVertexToBody(a,+l,-g,+h);JSM.AddVertexToBody(a,-l,-g,-h);JSM.AddVertexToBody(a,+k,+m,-n);JSM.AddVertexToBody(a,+k,-m,+n);JSM.AddVertexToBody(a,-k,+m,+n);JSM.AddVertexToBody(a,-k,-m,-n);JSM.AddVertexToBody(a,+m,-n,+k);JSM.AddVertexToBody(a,-m,+n,+k);JSM.AddVertexToBody(a,+m,+n,-k);JSM.AddVertexToBody(a,-m,-n,-k);JSM.AddVertexToBody(a,-n,+k,+m);JSM.AddVertexToBody(a,+n,+k,-m);JSM.AddVertexToBody(a,+n,-k,+m);JSM.AddVertexToBody(a,-n,-k,-m);JSM.AddVertexToBody(a,
+p,+q,-r);JSM.AddVertexToBody(a,+p,-q,+r);JSM.AddVertexToBody(a,-p,+q,+r);JSM.AddVertexToBody(a,-p,-q,-r);JSM.AddVertexToBody(a,+q,-r,+p);JSM.AddVertexToBody(a,-q,+r,+p);JSM.AddVertexToBody(a,+q,+r,-p);JSM.AddVertexToBody(a,-q,-r,-p);JSM.AddVertexToBody(a,-r,+p,+q);JSM.AddVertexToBody(a,+r,+p,-q);JSM.AddVertexToBody(a,+r,-p,+q);JSM.AddVertexToBody(a,-r,-p,-q);JSM.AddVertexToBody(a,+s,+x,-b);JSM.AddVertexToBody(a,+s,-x,+b);JSM.AddVertexToBody(a,-s,+x,+b);JSM.AddVertexToBody(a,-s,-x,-b);JSM.AddVertexToBody(a,
+x,-b,+s);JSM.AddVertexToBody(a,-x,+b,+s);JSM.AddVertexToBody(a,+x,+b,-s);JSM.AddVertexToBody(a,-x,-b,-s);JSM.AddVertexToBody(a,-b,+s,+x);JSM.AddVertexToBody(a,+b,+s,-x);JSM.AddVertexToBody(a,+b,-s,+x);JSM.AddVertexToBody(a,-b,-s,-x);JSM.AddPolygonToBody(a,[0,3,51]);JSM.AddPolygonToBody(a,[0,30,12]);JSM.AddPolygonToBody(a,[0,48,3]);JSM.AddPolygonToBody(a,[0,51,30]);JSM.AddPolygonToBody(a,[1,2,50]);JSM.AddPolygonToBody(a,[1,28,13]);JSM.AddPolygonToBody(a,[1,49,2]);JSM.AddPolygonToBody(a,[1,50,28]);
JSM.AddPolygonToBody(a,[2,29,14]);JSM.AddPolygonToBody(a,[2,49,29]);JSM.AddPolygonToBody(a,[3,31,15]);JSM.AddPolygonToBody(a,[3,48,31]);JSM.AddPolygonToBody(a,[4,7,55]);JSM.AddPolygonToBody(a,[4,34,16]);JSM.AddPolygonToBody(a,[4,52,7]);JSM.AddPolygonToBody(a,[4,55,34]);JSM.AddPolygonToBody(a,[5,6,54]);JSM.AddPolygonToBody(a,[5,32,17]);JSM.AddPolygonToBody(a,[5,53,6]);JSM.AddPolygonToBody(a,[5,54,32]);JSM.AddPolygonToBody(a,[6,33,18]);JSM.AddPolygonToBody(a,[6,53,33]);JSM.AddPolygonToBody(a,[7,35,
19]);JSM.AddPolygonToBody(a,[7,52,35]);JSM.AddPolygonToBody(a,[8,11,59]);JSM.AddPolygonToBody(a,[8,26,20]);JSM.AddPolygonToBody(a,[8,56,11]);JSM.AddPolygonToBody(a,[8,59,26]);JSM.AddPolygonToBody(a,[9,10,58]);JSM.AddPolygonToBody(a,[9,24,21]);JSM.AddPolygonToBody(a,[9,57,10]);JSM.AddPolygonToBody(a,[9,58,24]);JSM.AddPolygonToBody(a,[10,25,22]);JSM.AddPolygonToBody(a,[10,57,25]);JSM.AddPolygonToBody(a,[11,27,23]);JSM.AddPolygonToBody(a,[11,56,27]);JSM.AddPolygonToBody(a,[12,18,21]);JSM.AddPolygonToBody(a,
[12,21,24]);JSM.AddPolygonToBody(a,[12,30,18]);JSM.AddPolygonToBody(a,[13,16,22]);JSM.AddPolygonToBody(a,[13,22,25]);JSM.AddPolygonToBody(a,[13,28,16]);JSM.AddPolygonToBody(a,[14,17,20]);JSM.AddPolygonToBody(a,[14,20,26]);JSM.AddPolygonToBody(a,[14,29,17]);JSM.AddPolygonToBody(a,[15,19,23]);JSM.AddPolygonToBody(a,[15,23,27]);JSM.AddPolygonToBody(a,[15,31,19]);JSM.AddPolygonToBody(a,[16,34,22]);JSM.AddPolygonToBody(a,[17,32,20]);JSM.AddPolygonToBody(a,[18,33,21]);JSM.AddPolygonToBody(a,[19,35,23]);
JSM.AddPolygonToBody(a,[24,58,36]);JSM.AddPolygonToBody(a,[25,57,37]);JSM.AddPolygonToBody(a,[26,59,38]);JSM.AddPolygonToBody(a,[27,56,39]);JSM.AddPolygonToBody(a,[28,50,40]);JSM.AddPolygonToBody(a,[29,49,41]);JSM.AddPolygonToBody(a,[30,51,42]);JSM.AddPolygonToBody(a,[31,48,43]);JSM.AddPolygonToBody(a,[32,54,44]);JSM.AddPolygonToBody(a,[33,53,45]);JSM.AddPolygonToBody(a,[34,55,46]);JSM.AddPolygonToBody(a,[35,52,47]);JSM.AddPolygonToBody(a,[36,43,48]);JSM.AddPolygonToBody(a,[36,46,43]);JSM.AddPolygonToBody(a,
[36,58,46]);JSM.AddPolygonToBody(a,[37,41,49]);JSM.AddPolygonToBody(a,[37,45,41]);JSM.AddPolygonToBody(a,[37,57,45]);JSM.AddPolygonToBody(a,[38,40,50]);JSM.AddPolygonToBody(a,[38,47,40]);JSM.AddPolygonToBody(a,[38,59,47]);JSM.AddPolygonToBody(a,[39,42,51]);JSM.AddPolygonToBody(a,[39,44,42]);JSM.AddPolygonToBody(a,[39,56,44]);JSM.AddPolygonToBody(a,[40,47,52]);JSM.AddPolygonToBody(a,[41,45,53]);JSM.AddPolygonToBody(a,[42,44,54]);JSM.AddPolygonToBody(a,[43,46,55]);JSM.AddPolygonToBody(a,[0,12,24,36,
48]);JSM.AddPolygonToBody(a,[1,13,25,37,49]);JSM.AddPolygonToBody(a,[2,14,26,38,50]);JSM.AddPolygonToBody(a,[3,15,27,39,51]);JSM.AddPolygonToBody(a,[4,16,28,40,52]);JSM.AddPolygonToBody(a,[5,17,29,41,53]);JSM.AddPolygonToBody(a,[6,18,30,42,54]);JSM.AddPolygonToBody(a,[7,19,31,43,55]);JSM.AddPolygonToBody(a,[8,20,32,44,56]);JSM.AddPolygonToBody(a,[9,21,33,45,57]);JSM.AddPolygonToBody(a,[10,22,34,46,58]);JSM.AddPolygonToBody(a,[11,23,35,47,59]);return a};
JSM.AddCumulatedPolygonToBody=function(a,b,c){var d=new JSM.Coord(0,0,0),e=new JSM.Vector(0,0,0),f=d,g=[],h;for(h=0;h<b.length;h++)g.push(a.GetVertexPosition(b[h]));h=JSM.CalculateCentroid(g);g=JSM.CalculateNormal(g);f.Set(h.x,h.y,h.z);e.Set(g.x,g.y,g.z);d=JSM.CoordOffset(d,e,c);c=a.VertexCount();JSM.AddVertexToBody(a,d.x,d.y,d.z);d=b.length;for(e=0;e<d;e++)f=b[e],g=b[e<d-1?e+1:0],JSM.AddPolygonToBody(a,[f,g,c])};
JSM.GenerateCumulatedTetrahedron=function(a){var b=new JSM.Body;b.AddVertex(new JSM.BodyVertex(new JSM.Coord(1,1,1)));b.AddVertex(new JSM.BodyVertex(new JSM.Coord(-1,-1,1)));b.AddVertex(new JSM.BodyVertex(new JSM.Coord(-1,1,-1)));b.AddVertex(new JSM.BodyVertex(new JSM.Coord(1,-1,-1)));a*=2*Math.sqrt(2);JSM.AddCumulatedPolygonToBody(b,[0,1,3],a);JSM.AddCumulatedPolygonToBody(b,[0,2,1],a);JSM.AddCumulatedPolygonToBody(b,[0,3,2],a);JSM.AddCumulatedPolygonToBody(b,[1,2,3],a);return b};
JSM.GenerateCumulatedHexahedron=function(a){var b=new JSM.Body;JSM.AddVertexToBody(b,1,1,1);JSM.AddVertexToBody(b,1,1,-1);JSM.AddVertexToBody(b,1,-1,1);JSM.AddVertexToBody(b,-1,1,1);JSM.AddVertexToBody(b,1,-1,-1);JSM.AddVertexToBody(b,-1,1,-1);JSM.AddVertexToBody(b,-1,-1,1);JSM.AddVertexToBody(b,-1,-1,-1);a*=2;JSM.AddCumulatedPolygonToBody(b,[0,1,5,3],a);JSM.AddCumulatedPolygonToBody(b,[0,2,4,1],a);JSM.AddCumulatedPolygonToBody(b,[0,3,6,2],a);JSM.AddCumulatedPolygonToBody(b,[1,4,7,5],a);JSM.AddCumulatedPolygonToBody(b,
[2,6,7,4],a);JSM.AddCumulatedPolygonToBody(b,[3,5,7,6],a);return b};
JSM.GenerateCumulatedOctahedron=function(a){var b=new JSM.Body;JSM.AddVertexToBody(b,1,0,0);JSM.AddVertexToBody(b,-1,0,0);JSM.AddVertexToBody(b,0,1,0);JSM.AddVertexToBody(b,0,-1,0);JSM.AddVertexToBody(b,0,0,1);JSM.AddVertexToBody(b,0,0,-1);a*=Math.sqrt(2);JSM.AddCumulatedPolygonToBody(b,[0,2,4],a);JSM.AddCumulatedPolygonToBody(b,[0,3,5],a);JSM.AddCumulatedPolygonToBody(b,[0,4,3],a);JSM.AddCumulatedPolygonToBody(b,[0,5,2],a);JSM.AddCumulatedPolygonToBody(b,[1,2,5],a);JSM.AddCumulatedPolygonToBody(b,
[1,3,4],a);JSM.AddCumulatedPolygonToBody(b,[1,4,2],a);JSM.AddCumulatedPolygonToBody(b,[1,5,3],a);return b};
JSM.GenerateCumulatedDodecahedron=function(a){var b=new JSM.Body,c=(1+Math.sqrt(5))/2,d=1/c;JSM.AddVertexToBody(b,1,1,1);JSM.AddVertexToBody(b,1,1,-1);JSM.AddVertexToBody(b,1,-1,1);JSM.AddVertexToBody(b,-1,1,1);JSM.AddVertexToBody(b,1,-1,-1);JSM.AddVertexToBody(b,-1,1,-1);JSM.AddVertexToBody(b,-1,-1,1);JSM.AddVertexToBody(b,-1,-1,-1);JSM.AddVertexToBody(b,0,+d,+c);JSM.AddVertexToBody(b,0,+d,-c);JSM.AddVertexToBody(b,0,-d,+c);JSM.AddVertexToBody(b,0,-d,-c);JSM.AddVertexToBody(b,+d,+c,0);JSM.AddVertexToBody(b,
+d,-c,0);JSM.AddVertexToBody(b,-d,+c,0);JSM.AddVertexToBody(b,-d,-c,0);JSM.AddVertexToBody(b,+c,0,+d);JSM.AddVertexToBody(b,-c,0,+d);JSM.AddVertexToBody(b,+c,0,-d);JSM.AddVertexToBody(b,-c,0,-d);a*=Math.sqrt(5)-1;JSM.AddCumulatedPolygonToBody(b,[0,8,10,2,16],a);JSM.AddCumulatedPolygonToBody(b,[0,16,18,1,12],a);JSM.AddCumulatedPolygonToBody(b,[0,12,14,3,8],a);JSM.AddCumulatedPolygonToBody(b,[1,9,5,14,12],a);JSM.AddCumulatedPolygonToBody(b,[1,18,4,11,9],a);JSM.AddCumulatedPolygonToBody(b,[2,10,6,15,
13],a);JSM.AddCumulatedPolygonToBody(b,[2,13,4,18,16],a);JSM.AddCumulatedPolygonToBody(b,[3,14,5,19,17],a);JSM.AddCumulatedPolygonToBody(b,[3,17,6,10,8],a);JSM.AddCumulatedPolygonToBody(b,[4,13,15,7,11],a);JSM.AddCumulatedPolygonToBody(b,[5,9,11,7,19],a);JSM.AddCumulatedPolygonToBody(b,[6,17,19,7,15],a);return b};
JSM.GenerateCumulatedIcosahedron=function(a){var b=new JSM.Body,c=(1+Math.sqrt(5))/2;JSM.AddVertexToBody(b,0,1,+c);JSM.AddVertexToBody(b,0,1,-c);JSM.AddVertexToBody(b,0,-1,+c);JSM.AddVertexToBody(b,0,-1,-c);JSM.AddVertexToBody(b,1,+c,0);JSM.AddVertexToBody(b,1,-c,0);JSM.AddVertexToBody(b,-1,+c,0);JSM.AddVertexToBody(b,-1,-c,0);JSM.AddVertexToBody(b,+c,0,1);JSM.AddVertexToBody(b,-c,0,1);JSM.AddVertexToBody(b,+c,0,-1);JSM.AddVertexToBody(b,-c,0,-1);a*=2;JSM.AddCumulatedPolygonToBody(b,[0,2,8],a);JSM.AddCumulatedPolygonToBody(b,
[0,4,6],a);JSM.AddCumulatedPolygonToBody(b,[0,6,9],a);JSM.AddCumulatedPolygonToBody(b,[0,8,4],a);JSM.AddCumulatedPolygonToBody(b,[0,9,2],a);JSM.AddCumulatedPolygonToBody(b,[1,3,11],a);JSM.AddCumulatedPolygonToBody(b,[1,4,10],a);JSM.AddCumulatedPolygonToBody(b,[1,6,4],a);JSM.AddCumulatedPolygonToBody(b,[1,10,3],a);JSM.AddCumulatedPolygonToBody(b,[1,11,6],a);JSM.AddCumulatedPolygonToBody(b,[2,5,8],a);JSM.AddCumulatedPolygonToBody(b,[2,7,5],a);JSM.AddCumulatedPolygonToBody(b,[2,9,7],a);JSM.AddCumulatedPolygonToBody(b,
[3,5,7],a);JSM.AddCumulatedPolygonToBody(b,[3,7,11],a);JSM.AddCumulatedPolygonToBody(b,[3,10,5],a);JSM.AddCumulatedPolygonToBody(b,[4,8,10],a);JSM.AddCumulatedPolygonToBody(b,[6,11,9],a);JSM.AddCumulatedPolygonToBody(b,[5,10,8],a);JSM.AddCumulatedPolygonToBody(b,[7,9,11],a);return b};JSM.GenerateTetrakisHexahedron=function(){return JSM.GenerateCumulatedHexahedron(0.25)};JSM.GenerateRhombicDodecahedron=function(){return JSM.GenerateCumulatedHexahedron(0.5)};
JSM.GeneratePentakisDodecahedron=function(){var a=Math.sqrt((65+22*Math.sqrt(5))/5)/19;return JSM.GenerateCumulatedDodecahedron(a)};JSM.GenerateSmallStellatedDodecahedron=function(){var a=Math.sqrt((5+2*Math.sqrt(5))/5);return JSM.GenerateCumulatedDodecahedron(a)};JSM.GenerateGreatDodecahedron=function(){var a=Math.sqrt(3)*(Math.sqrt(5)-3)/6;return JSM.GenerateCumulatedIcosahedron(a)};JSM.GenerateSmallTriambicIcosahedron=function(){var a=Math.sqrt(15)/15;return JSM.GenerateCumulatedIcosahedron(a)};
JSM.GenerateGreatStellatedDodecahedron=function(){var a=Math.sqrt(3)*(3+Math.sqrt(5))/6;return JSM.GenerateCumulatedIcosahedron(a)};JSM.GenerateSmallTriakisOctahedron=function(){var a=Math.sqrt(3)-2*Math.sqrt(6)/3;return JSM.GenerateCumulatedOctahedron(a)};JSM.GenerateStellaOctangula=function(){var a=Math.sqrt(6)/3;return JSM.GenerateCumulatedOctahedron(a)};JSM.GenerateTriakisTetrahedron=function(){var a=Math.sqrt(6)/15;return JSM.GenerateCumulatedTetrahedron(a)};
JSM.LegoDimensions=function(){this.legoWidth=0.78;this.legoSmallHeight=0.32;this.legoLargeHeight=0.96;this.legoWallWidth=0.16;this.legoCylinderWidth=0.5;this.legoCylinderHeight=0.17;this.legoBottomSmallCylinderWidth=0.3;this.legoBottomLargeCylinderWidth=0.6;this.legoBottomLargeCylinderWallWidth=0.1};
JSM.GenerateLegoBrick=function(a,b,c,d,e,f,g){function h(a,b){var c,d;for(c=0;c<a.VertexCount();c++)d=a.GetVertex(c),d.position=JSM.CoordAdd(d.position,b)}var l=new JSM.LegoDimensions,k=new JSM.Vector(0,0,1),m=l.legoWidth,n=l.legoLargeHeight;c||(n=l.legoSmallHeight);c=l.legoWallWidth;var p=l.legoCylinderWidth,q=l.legoCylinderHeight,r=l.legoBottomSmallCylinderWidth,s=l.legoBottomLargeCylinderWidth,x=l.legoBottomLargeCylinderWallWidth,v=[];v.push(new JSM.Coord(0,0,0));v.push(new JSM.Coord(m*a,0,0));
v.push(new JSM.Coord(m*a,m*b,0));v.push(new JSM.Coord(0,m*b,0));var l=new JSM.Body,t=JSM.GeneratePrismShell(v,k,n-c,c,!0);l.Merge(t);for(t=0;4>t;t++)v[t].z=n-c;t=JSM.GeneratePrism(v,k,c,!0);l.Merge(t);if(d)for(t=0;t<a;t++)for(v=0;v<b;v++)d=new JSM.Coord(m*t+m/2,m*v+m/2,n+q/2),k=JSM.GenerateCylinder(p/2,q,f,!0,g),h(k,d),l.Merge(k);if(e)if(1===a&&1<b||1===b&&1<a){e=b;p=!0;a>b&&(e=a,p=!1);for(t=0;t<e-1;t++)d=p?new JSM.Coord(m/2,m*(t+1),(n-c)/2):new JSM.Coord(m*(t+1),m/2,(n-c)/2),k=JSM.GenerateCylinder(r/
2,n-c,f,!0,g),h(k,d),l.Merge(k)}else if(1<a&&1<b)for(t=0;t<a-1;t++)for(v=0;v<b-1;v++)d=new JSM.Coord(m*(t+1),m*(v+1),(n-c)/2),k=JSM.GenerateCylinderShell(s/2,n-c,x,f,!0,g),h(k,d),l.Merge(k);l.SetCubicTextureProjection(new JSM.Coord(0,0,0),new JSM.Coord(1,0,0),new JSM.Coord(0,1,0),new JSM.Coord(0,0,1));return l};
JSM.GenerateConvexHullBody=function(a){var b=new JSM.Body,c=JSM.ConvexHull3D(a),d={},e,f,g,h;for(e=0;e<c.length;e++){g=c[e];for(f=0;f<g.length;f++)h=g[f],h in d||(d[h]=b.VertexCount(),b.AddVertex(new JSM.BodyVertex(a[h])))}for(e=0;e<c.length;e++){g=c[e];a=[];for(f=0;f<g.length;f++)h=g[f],a.push(d[h]);b.AddPolygon(new JSM.BodyPolygon(a))}return b};
JSM.GenerateSuperShape=function(a,b,c,d,e,f,g,h,l,k,m,n,p,q){function r(a){var b=Math.sqrt(a.x*a.x+a.y*a.y+a.z*a.z),c=Math.asin(a.z/b);a=Math.atan2(a.y,a.x);return[b,c,a]}function s(a,b,c,d,e,f,g){b=Math.abs(Math.cos(d*a/4)/b);a=Math.abs(Math.sin(d*a/4)/c);return Math.pow(Math.pow(b,f)+Math.pow(a,g),-1/e)}function x(p,q){var x=new JSM.Coord(0,0,0),t=s(p,g,h,l,k,m,n),r=s(q,a,b,c,d,e,f);x.x=r*Math.cos(q)*t*Math.cos(p);x.y=r*Math.sin(q)*t*Math.cos(p);x.z=t*Math.sin(p);return x}p=JSM.GenerateSphere(1,
p,q);var v,t;for(q=0;q<p.VertexCount();q++)v=p.GetVertex(q),t=v.position,t=r(t),t=x(t[1],t[2]),v.SetPosition(t);return p};
JSM.OrderPolygons=function(a,b,c){var d=[],e=[],f=[],g=[],h=[],l=[],k=[],m=a.PolygonCount(),n,p;for(n=0;n<m;n++){l.push(n);k.push([]);for(p=0;p<m;p++)k[n].push(null)}(function(){var k=JSM.VectorNormalize(JSM.CoordSub(c,b)),k=JSM.GetPlaneFromCoordAndDirection(b,k),l,m,n,p,t,y;for(l=0;l<a.PolygonCount();l++){t=JSM.Inf;y=-JSM.Inf;n=a.GetPolygon(l);for(m=0;m<n.VertexIndexCount();m++)p=a.GetVertexPosition(n.GetVertexIndex(m)),p=JSM.CoordPlaneDistance(p,k),JSM.IsLower(p,t)&&(t=p),JSM.IsGreater(p,y)&&(y=
p);d.push(t);e.push(y);m=a.GetPolygon(l);n=new JSM.Coord(0,0,0);y=t=void 0;for(t=0;t<m.VertexIndexCount();t++)y=a.GetVertexPosition(m.GetVertexIndex(t)),n=JSM.CoordAdd(n,y);m=n=JSM.VectorMultiply(n,1/m.VertexIndexCount());n=JSM.CoordPlaneDistance(m,k);f.push(m);g.push(n);n=JSM.CalculateBodyPolygonNormal(a,l);t=JSM.VectorNormalize(JSM.CoordSub(m,b));t=JSM.VectorDot(n,t);JSM.IsGreaterOrEqual(t,0)&&(n=JSM.VectorMultiply(n,-1));m=JSM.GetPlaneFromCoordAndDirection(m,n);h.push(m)}})();(function(){var a=
l.length,b,c;for(b=0;b<a-1;b++)for(c=0;c<a-b-1;c++){var d;d=l[c];var f=l[c+1];d=JSM.IsLower(e[d],e[f])?!0:JSM.IsEqual(e[d],e[f])&&JSM.IsLower(g[d],g[f])?!0:!1;if(d){d=l;var f=c+1,h=d[c];d[c]=d[f];d[f]=h}}})();(function(){var b=l.length,c,f;for(c=0;c<b-1;c++)for(f=0;f<b-c-1;f++){var g;g=l[f];var m=l[f+1];if(null!==k[g][m])g=k[g][m];else{var n;if(n=JSM.IsLowerOrEqual(d[g],e[m])){var p=m;n=h[g];for(var F=h[p],C=void 0,u=void 0,H=!0,z=a.GetPolygon(g),C=0;C<z.VertexIndexCount();C++)if(u=a.GetVertexPosition(z.GetVertexIndex(C)),
"CoordInFrontOfPlane"===JSM.CoordPlanePosition(u,F)){H=!1;break}if(H)n=!1;else{F=!0;p=a.GetPolygon(p);for(C=0;C<p.VertexIndexCount();C++)if(u=a.GetVertexPosition(p.GetVertexIndex(C)),"CoordAtBackOfPlane"===JSM.CoordPlanePosition(u,n)){F=!1;break}n=F?!1:!0}}g=n?k[g][m]=!0:k[g][m]=!1}g&&(g=l,m=f+1,n=g[f],g[f]=g[m],g[m]=n)}})();return l};JSM.CanvasDrawer=function(a){this.canvas=a;this.context=this.canvas.getContext("2d")};JSM.CanvasDrawer.prototype.GetWidth=function(){return this.canvas.width};
JSM.CanvasDrawer.prototype.GetHeight=function(){return this.canvas.height};JSM.CanvasDrawer.prototype.BeginPath=function(){this.context.beginPath()};JSM.CanvasDrawer.prototype.EndPath=function(){this.context.stroke()};JSM.CanvasDrawer.prototype.Clear=function(){this.context.clearRect(0,0,this.canvas.width,this.canvas.height);this.context.fillStyle="#ffffff";this.context.fillRect(0,0,this.canvas.width,this.canvas.height)};
JSM.CanvasDrawer.prototype.DrawLine=function(a,b){this.context.moveTo(a.x,this.canvas.height-a.y);this.context.lineTo(b.x,this.canvas.height-b.y)};
JSM.CanvasDrawer.prototype.DrawPolygon=function(a,b){var c=this.context,d=JSM.HexColorToRGBComponents(b);c.fillStyle="rgb("+d[0]+","+d[1]+","+d[2]+")";this.context.beginPath();for(var e,c=0;c<a.VertexCount();c++)d=a.GetVertex(c),0===c?this.context.moveTo(d.x,this.canvas.height-d.y):this.context.lineTo(d.x,this.canvas.height-d.y);this.context.closePath();this.context.fill();this.BeginPath();for(c=0;c<a.VertexCount();c++)d=a.GetVertex(c),e=a.GetVertex(c<a.VertexCount()-1?c+1:0),this.DrawLine(d,e);this.EndPath()};
JSM.SVGDrawer=function(a){this.svgObject=a;this.svgNameSpace="http://www.w3.org/2000/svg"};JSM.SVGDrawer.prototype.GetWidth=function(){return this.svgObject.getAttribute("width")};JSM.SVGDrawer.prototype.GetHeight=function(){return this.svgObject.getAttribute("height")};JSM.SVGDrawer.prototype.BeginPath=function(){};JSM.SVGDrawer.prototype.EndPath=function(){};JSM.SVGDrawer.prototype.Clear=function(){for(;this.svgObject.lastChild;)this.svgObject.removeChild(this.svgObject.lastChild)};
JSM.SVGDrawer.prototype.DrawLine=function(a,b){var c=document.createElementNS(this.svgNameSpace,"line"),d=this.GetHeight();c.setAttributeNS(null,"stroke","black");c.setAttributeNS(null,"x1",a.x);c.setAttributeNS(null,"y1",d-a.y);c.setAttributeNS(null,"x2",b.x);c.setAttributeNS(null,"y2",d-b.y);this.svgObject.appendChild(c)};
JSM.SVGDrawer.prototype.DrawPolygon=function(a,b){var c="",d=this.GetHeight(),e,f;for(e=0;e<a.VertexCount();e++)f=a.GetVertex(e),c=c+f.x+", "+(d-f.y),e<a.VertexCount()-1&&(c+=", ");d=document.createElementNS(this.svgNameSpace,"polygon");d.setAttributeNS(null,"points",c);d.setAttributeNS(null,"fill",function(a){a=JSM.HexColorToRGBComponents(a);return"rgb("+a[0]+","+a[1]+","+a[2]+")"}(b));d.setAttributeNS(null,"fill-opacity","1.0");d.setAttributeNS(null,"stroke","black");this.svgObject.appendChild(d)};
JSM.DrawProjectedBody=function(a,b,c,d,e,f){function g(b){var c=new JSM.Polygon2D,d,e,f;for(d=0;d<b.VertexIndexCount();d++)e=a.GetVertexPosition(b.GetVertexIndex(d)),f=JSM.Project(e,l,k,m,n*JSM.DegRad,p,q,r,s),e=f.x,f=f.y,c.AddVertex(e,f);return c}e&&f.Clear();e=f.GetWidth();var h=f.GetHeight(),l=c.eye,k=c.center,m=c.up,n=c.fieldOfView,p=e/h,q=c.nearClippingPlane,r=c.farClippingPlane,s=[0,0,e,h];if("HiddenLinePainter"==d){h=JSM.OrderPolygons(a,l,k);if(void 0===b||null===b)b=new JSM.Materials;for(c=
0;c<h.length;c++)e=a.GetPolygon(h[c]),d=g(e),e=e.GetMaterialIndex(),e=b.GetMaterial(e).diffuse,f.DrawPolygon(d,e)}else if("HiddenLineFrontFacing"==d){if(void 0===b||null===b)b=new JSM.Materials;for(c=0;c<a.PolygonCount();c++)e=a.GetPolygon(c),d=g(e),"CounterClockwise"==JSM.PolygonOrientation2D(d)&&(e=e.GetMaterialIndex(),e=b.GetMaterial(e).diffuse,f.DrawPolygon(d,e))}else if("Wireframe"==d){var x,v,t;f.BeginPath();var y=[];for(c=0;c<a.PolygonCount();c++){v=x=null;e=a.GetPolygon(c);h=e.VertexIndexCount();
for(b=0;b<=h;b++)t=e.GetVertexIndex(b%h),d=a.GetVertexPosition(t),d=JSM.Project(d,l,k,m,n*JSM.DegRad,p,q,r,s),null!==x&&(null!==v&&void 0===y[[v,t]])&&(f.DrawLine(x,d),y[[v,t]]=!0,y[[t,v]]=!0),v=t,x=d}f.EndPath()}return!0};
JSM.CatmullClarkSubdivisionOneIteration=function(a){var b=new JSM.Body,c=JSM.CalculateAdjacencyInfo(a);(function(){var d,e;for(d=0;d<c.verts.length;d++)e=a.GetVertex(d).position,b.AddVertex(new JSM.BodyVertex(new JSM.Coord(e.x,e.y,e.z)))})();var d=[];(function(){var e,g,h,l,k;for(e=0;e<c.pgons.length;e++){h=c.pgons[e];k=new JSM.Coord(0,0,0);for(g=0;g<h.verts.length;g++)l=a.GetVertex(h.verts[g]).position,k=JSM.CoordAdd(k,l);k=JSM.VectorMultiply(k,1/h.verts.length);d.push(b.AddVertex(new JSM.BodyVertex(k)))}})();
var e=[];(function(){var f,g,h,l,k;for(f=0;f<c.edges.length;f++){h=c.edges[f];l=new JSM.Coord(0,0,0);l=JSM.CoordAdd(l,JSM.VectorMultiply(a.GetVertex(h.vert1).position,0.25));l=JSM.CoordAdd(l,JSM.VectorMultiply(a.GetVertex(h.vert2).position,0.25));for(g=0;2>g;g++)k=0===g?h.pgon1:h.pgon2,-1===k&&(k=0===g?h.pgon2:h.pgon1),k=b.GetVertex(d[k]).position,l=JSM.CoordAdd(l,JSM.VectorMultiply(k,0.25));e.push(b.AddVertex(new JSM.BodyVertex(l)))}})();(function(){var e=[],g,h,l,k;for(l=0;l<c.edges.length;l++)g=
c.edges[l],h=JSM.MidCoord(a.GetVertex(g.vert1).position,a.GetVertex(g.vert2).position),e.push(h);var m,n,p;for(l=0;l<c.verts.length;l++){m=c.verts[l];p=new JSM.Coord(0,0,0);g=new JSM.Coord(0,0,0);n=1/m.pgons.length;for(k=0;k<m.pgons.length;k++)h=b.GetVertex(d[m.pgons[k]]).position,p=JSM.CoordAdd(p,JSM.VectorMultiply(h,n));n=1/m.edges.length;for(k=0;k<m.edges.length;k++)h=e[m.edges[k]],g=JSM.CoordAdd(g,JSM.VectorMultiply(h,n));m=m.edges.length;k=b.GetVertex(l).position;k.x=(p.x+2*g.x+(m-3)*k.x)/m;
k.y=(p.y+2*g.y+(m-3)*k.y)/m;k.z=(p.z+2*g.z+(m-3)*k.z)/m}})();(function(){var f,g,h,l,k,m,n,p;for(m=0;m<c.pgons.length;m++){p=c.pgons[m];f=p.verts.length;for(n=0;n<f;n++)g=p.pedges[n],h=p.pedges[(n+1)%f],l=d[m],g=e[g.index],k=JSM.GetPolyEdgeStartVertex(h,c),h=e[h.index],l=new JSM.BodyPolygon([l,g,k,h]),h=a.GetPolygon(m),l.material=h.material,l.curved=h.curved,b.AddPolygon(l)}})();return b};
JSM.CatmullClarkSubdivision=function(a,b){var c=a,d;for(d=0;d<b;d++)c=JSM.CatmullClarkSubdivisionOneIteration(c);return c};
JSM.SvgToModel=function(a,b,c){function d(a,b){function c(a,b,d,e,f,g){a=a.createSVGPoint();a.x=f;a.y=g;e=a.matrixTransform(e.getCTM());a=new JSM.Coord2D(e.x,e.y);f=new JSM.Coord2D(f,g);g=b.VertexCount(d);if(0<g&&JSM.CoordIsEqual2DWithEps(b.GetVertex(d,g-1),a,0.1))return f;b.AddVertex(d,e.x,e.y);return f}function d(a,b,e,f,g,h,k){var l=document.createElementNS("http://www.w3.org/2000/svg","path"),m="M "+f.x+" "+f.y+" ",n,q,t,r,s;for(n=0;n<g.length;n++)if(q=g[n],q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS||
q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL)t=q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS?"C":"c",m+=t+" "+q.x1+" "+q.y1+" "+q.x2+" "+q.y2+" "+q.x+" "+q.y+" ";else if(q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS||q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL)t=q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS?"Q":"q",m+=t+" "+q.x1+" "+q.y1+" "+q.x+" "+q.y+" ";else if(q.pathSegType==SVGPathSeg.PATHSEG_ARC_ABS||q.pathSegType==SVGPathSeg.PATHSEG_ARC_REL)t=q.pathSegType==
SVGPathSeg.PATHSEG_ARC_ABS?"A":"a",r=q.largeArcFlag?1:0,s=q.sweepFlag?1:0,m+=t+" "+q.r1+" "+q.r2+" "+q.angle+" "+r+" "+s+" "+q.x+" "+q.y+" ";else if(q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS||q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL)t=q.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS?"S":"s",m+=t+" "+q.x2+" "+q.y2+" "+q.x+" "+q.y+" ";l.setAttributeNS(null,"d",m);m=l.getTotalLength();g=0;0<e&&(g=parseInt(m/e,10));3>g&&(g=3);e=m/g;for(m=1;m<=g;m++)f=l.getPointAtLength(m*
e),f=c(a,h,k,b,f.x,f.y);return f}function e(a,b){var c=a.VertexCount(b);if(0!==c){var d=a.GetVertex(b,0),c=a.GetVertex(b,c-1);JSM.CoordIsEqual2DWithEps(d,c,0.1)&&a.GetContour(b).vertices.pop()}}function f(a,b){return 0<a.VertexCount(b)?(e(a,b),a.AddContour(),b+1):b}var g=new JSM.ContourPolygon2D,h=document.createElementNS("http://www.w3.org/2000/svg","svg"),l;if(a instanceof SVGPathElement){var k=new JSM.Coord2D(0,0),F=new JSM.Coord2D(0,0),C=b;a.hasAttribute("segmentlength")&&(C=parseFloat(a.getAttribute("segmentlength")));
var u,H,z=0;for(l=0;l<a.pathSegList.numberOfItems;l++)if(u=a.pathSegList.getItem(l),u.pathSegType!=SVGPathSeg.PATHSEG_CLOSEPATH)if(u.pathSegType==SVGPathSeg.PATHSEG_MOVETO_ABS)z=f(g,z),k=c(h,g,z,a,u.x,u.y),F=k.Clone();else if(u.pathSegType==SVGPathSeg.PATHSEG_MOVETO_REL)z=f(g,z),k=c(h,g,z,a,F.x+u.x,F.y+u.y),F=k.Clone();else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_ABS)k=c(h,g,z,a,u.x,u.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_REL)k=c(h,g,z,a,k.x+u.x,k.y+u.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS)k=
c(h,g,z,a,u.x,k.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS)k=c(h,g,z,a,k.x,u.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL)k=c(h,g,z,a,k.x+u.x,k.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL)k=c(h,g,z,a,k.x,k.y+u.y);else if(u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL||
u.pathSegType==SVGPathSeg.PATHSEG_ARC_ABS||u.pathSegType==SVGPathSeg.PATHSEG_ARC_REL||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL){H=[];if(u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL){for(;l<a.pathSegList.numberOfItems;l++){u=a.pathSegList.getItem(l);if(!(u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS||u.pathSegType==SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL))break;
H.push(u)}l-=1}else H.push(u);k=d(h,a,C,k,H,g,z)}e(g,z)}else if(a instanceof SVGRectElement)c(h,g,0,a,a.x.baseVal.value,a.y.baseVal.value),c(h,g,0,a,a.x.baseVal.value+a.width.baseVal.value,a.y.baseVal.value),c(h,g,0,a,a.x.baseVal.value+a.width.baseVal.value,a.y.baseVal.value+a.height.baseVal.value),c(h,g,0,a,a.x.baseVal.value,a.y.baseVal.value+a.height.baseVal.value);else if(a instanceof SVGPolygonElement)for(l=0;l<a.points.numberOfItems;l++)k=a.points.getItem(l),c(h,g,0,a,k.x,k.y);g.color=function(a){for(var b=
"";null!==a&&void 0!==a&&0===b.length;)b=a.getAttribute("fill"),null===b&&(b=a.style.fill),a=a.parentElement;a=0;if(0===b.length)return a;if("#"==b[0])a=JSM.HexColorToRGBColor(b.substring(1));else{var c=b.indexOf("("),d=b.indexOf(")");if(-1==c||-1==d)return a;b=b.substring(c+1,d).split(", ");if(3!=b.length)return a;a=JSM.RGBComponentsToHexColor(b[0],b[1],b[2])}return a}(a);return g}function e(a,b){function c(a,b){var d=[],e,f;if("Clockwise"==b)for(e=0;e<a.VertexCount();e++)f=a.GetVertex(e),d.push(new JSM.Coord(f.x,
0,-f.y));else for(e=a.VertexCount()-1;0<=e;e--)f=a.GetVertex(e),d.push(new JSM.Coord(f.x,0,-f.y));return d}function d(a,b,c){a.push(null);var e;if("CounterClockwise"==c)for(c=0;c<b.VertexCount();c++)e=b.GetVertex(c),a.push(new JSM.Coord(e.x,0,-e.y));else for(c=b.VertexCount()-1;0<=c;c--)e=b.GetVertex(c),a.push(new JSM.Coord(e.x,0,-e.y))}var e=[],f=new JSM.Vector(0,-1,0),g,h;h=a.ContourCount();if(1==h)h=JSM.PolygonOrientation2D(a.GetContour(0)),g=c(a.GetContour(0),h),g=JSM.GeneratePrism(g,f,b,!0),
e.push(g);else if(1<h){h=JSM.PolygonOrientation2D(a.GetContour(0));var k=c(a.GetContour(0),h),l=!1,F;for(F=1;F<a.ContourCount();F++)g=JSM.PolygonOrientation2D(a.GetContour(F)),g==h?(g=c(a.GetContour(F),h),g=JSM.GeneratePrism(g,f,b,!0),e.push(g)):(d(k,a.GetContour(F),g),l=!0);g=l?JSM.GeneratePrismWithHole(k,f,b,!0):JSM.GeneratePrism(k,f,b,!0);e.push(g)}f=new JSM.Material({ambient:a.color,diffuse:a.color});return[e,f]}var f=new JSM.Model,g=new JSM.Materials;c=function(a,b){function c(a,b,d){a=a.getElementsByTagName(b);
for(b=0;b<a.length;b++)d.push(a[b])}var e=[],f=[];c(a,"path",f);c(a,"rect",f);c(a,"polygon",f);var g=b;a.hasAttribute("segmentlength")&&(g=parseFloat(a.getAttribute("segmentlength")));var h,k;for(h=0;h<f.length;h++)k=d(f[h],g),e.push(k);return e}(a,c);a.hasAttribute("modelheight")&&(b=parseFloat(a.getAttribute("modelheight")));var h,l,k;for(a=0;a<c.length;a++){h=e(c[a],b);l=h[0];h=h[1];g.AddMaterial(h);for(h=0;h<l.length;h++)k=l[h],k.SetPolygonsMaterialIndex(g.Count()-1),f.AddBody(k)}return[f,g]};
JSM.BSPPolygonUserData=function(){this.material=this.id=null};JSM.AddBodyToBSPTree=function(a,b,c){var d,e,f;for(d=0;d<a.PolygonCount();d++){f=new JSM.BSPPolygonUserData;f.id=c;e=a;var g=f,h=e.GetPolygon(d);g.material=h.GetMaterialIndex();for(var g=new JSM.Polygon,l=void 0,k=void 0,l=0;l<h.VertexIndexCount();l++)k=e.GetVertexPosition(h.GetVertexIndex(l)),g.AddVertex(k.x,k.y,k.z);e=g;b.AddPolygon(e,f)}};
JSM.BooleanOperation=function(a,b,c){function d(a,b,c){function d(a){b.AddVertex(new JSM.BodyVertex(a));return b.VertexCount()-1}var e=new JSM.BodyPolygon([]),f;if(c)for(c=a.VertexCount()-1;0<=c;c--)f=d(a.GetVertex(c)),e.AddVertexIndex(f);else for(c=0;c<a.VertexCount();c++)f=d(a.GetVertex(c)),e.AddVertexIndex(f);void 0!==a.userData&&e.SetMaterialIndex(a.userData.material);b.AddPolygon(e)}function e(a,b,c){var e;for(e=0;e<a.length;e++)d(a[e],b,c)}function f(a,b,c,d,e,f){function g(a,b){var c;for(c=
0;c<a.length;c++)a[c].userData=b}var h,k;for(h=0;h<a.length;h++)k=a[h],JSM.ClipPolygonWithBSPTree(k.polygon,b,c,d,e,f),g(c,k.userData),g(d,k.userData),g(e,k.userData),g(f,k.userData)}var g=new JSM.BSPTree,h=new JSM.BSPTree;JSM.AddBodyToBSPTree(b,g,"a");JSM.AddBodyToBSPTree(c,h,"b");b=new JSM.Body;c=[];var l=[],k=[],m=[];f(g.GetNodes(),h,c,l,k,m);var n=[],p=[],q=[];f(h.GetNodes(),g,n,p,q,[]);"Union"==a?(e(c,b,!1),e(k,b,!1),e(m,b,!1),e(n,b,!1),e(q,b,!1)):"Difference"==a?(e(c,b,!1),e(k,b,!1),e(p,b,!0)):
"Intersection"==a&&(e(l,b,!1),e(m,b,!1),e(p,b,!1));return b};
JSM.GenerateSurface=function(a,b,c,d,e,f,g,h){var l=new JSM.Body,k=a[0],m=b[0],n=(a[1]-a[0])/c,p=(b[1]-b[0])/d;(function(){var a,b,e,f;for(a=0;a<=d;a++)for(b=0;b<=c;b++)e=k+b*n,f=m+a*p,e=g(a,b,e,f,h),l.AddVertex(new JSM.BodyVertex(e))})();(function(){var a,b,g,h,k,m;for(b=0;b<d;b++)for(a=0;a<c;a++)g=b*(c+1)+a,h=g+1,k=g+c+1,m=k+1,e?(h=new JSM.BodyPolygon([g,h,m]),f&&h.SetCurveGroup(0),l.AddPolygon(h),h=new JSM.BodyPolygon([g,m,k])):h=new JSM.BodyPolygon([g,h,m,k]),f&&h.SetCurveGroup(0),l.AddPolygon(h)})();
return l};JSM.SurfaceControlPoints=function(a,b){this.n=a;this.m=b;this.points=[];var c,d;for(c=0;c<=this.n;c++){this.points.push([]);for(d=0;d<=this.m;d++)this.points[c].push(new JSM.Coord(0,0,0))}};JSM.SurfaceControlPoints.prototype.GetNValue=function(){return this.n};JSM.SurfaceControlPoints.prototype.GetMValue=function(){return this.m};JSM.SurfaceControlPoints.prototype.GetControlPoint=function(a,b){return this.points[a][b]};
JSM.SurfaceControlPoints.prototype.InitPlanar=function(a,b){var c=a/this.n,d=b/this.m,e,f,g;for(e=0;e<=this.n;e++)for(f=0;f<=this.m;f++)g=this.points[e][f],g.x=e*c,g.y=f*d};
JSM.GenerateBezierSurface=function(a,b,c,d){return JSM.GenerateSurface([0,1],[0,1],b,c,!1,d,function(a,b,c,d,l){function k(a,b,c){var d=1,e=JSM.Minimum(a,b-a),f;for(f=0;f<e;f++)d*=b-f,d/=f+1;return d*Math.pow(c,a)*Math.pow(1-c,b-a)}var m,n,p,q=l.GetNValue(),r=l.GetMValue();m=new JSM.Coord(0,0,0);for(a=0;a<=q;a++){n=new JSM.Coord(0,0,0);for(b=0;b<=r;b++)p=k(a,q,c)*k(b,r,d),p=JSM.VectorMultiply(l.GetControlPoint(a,b),p),n=JSM.CoordAdd(n,p);m=JSM.CoordAdd(m,n)}return m},a)};
JSM.RenderMaterial=function(a,b,c,d,e,f,g){this.ambient=a;this.diffuse=b;this.specular=c;this.shininess=d;this.texture=e;this.textureWidth=f;this.textureHeight=g;this.textureImage=this.textureBuffer=null;this.textureLoaded=!1};JSM.RenderMaterial.prototype.HasTexture=function(){return null!==this.texture&&this.textureLoaded};
JSM.RenderMaterial.prototype.Compile=function(a,b){if(null!==this.texture){var c=this;this.textureBuffer=a.createTexture();this.textureImage=new Image;this.textureImage.src=this.texture;this.textureImage.onload=function(){a.bindTexture(a.TEXTURE_2D,c.textureBuffer);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,c.textureImage);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR_MIPMAP_LINEAR);a.generateMipmap(a.TEXTURE_2D);
a.bindTexture(a.TEXTURE_2D,null);c.textureLoaded=!0;void 0!==b&&null!==b&&b()}}};JSM.RenderGeometry=function(){this.transformation=new JSM.Transformation;this.uvBuffer=this.normalBuffer=this.vertexBuffer=this.uvArray=this.normalArray=this.vertexArray=this.material=null};JSM.RenderGeometry.prototype.SetMaterial=function(a){this.material=a};JSM.RenderGeometry.prototype.GetMaterial=function(){return this.material};JSM.RenderGeometry.prototype.SetVertexArray=function(a){this.vertexArray=new Float32Array(a)};
JSM.RenderGeometry.prototype.SetNormalArray=function(a){this.normalArray=new Float32Array(a)};JSM.RenderGeometry.prototype.SetUVArray=function(a){this.uvArray=new Float32Array(a)};JSM.RenderGeometry.prototype.GetTransformation=function(){return this.transformation};JSM.RenderGeometry.prototype.GetTransformationMatrix=function(){return this.transformation.matrix};JSM.RenderGeometry.prototype.SetTransformation=function(a){this.transformation=a};JSM.RenderGeometry.prototype.GetVertexBuffer=function(){return this.vertexBuffer};
JSM.RenderGeometry.prototype.GetNormalBuffer=function(){return this.normalBuffer};JSM.RenderGeometry.prototype.GetUVBuffer=function(){return this.uvBuffer};JSM.RenderGeometry.prototype.VertexCount=function(){return parseInt(this.vertexArray.length/3,10)};JSM.RenderGeometry.prototype.GetVertex=function(a){return new JSM.Coord(this.vertexArray[3*a],this.vertexArray[3*a+1],this.vertexArray[3*a+2])};JSM.RenderGeometry.prototype.GetTransformedVertex=function(a){a=this.GetVertex(a);return this.transformation.Apply(a)};
JSM.RenderGeometry.prototype.Compile=function(a,b){this.material.Compile(a,b);this.vertexBuffer=a.createBuffer();a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer);a.bufferData(a.ARRAY_BUFFER,this.vertexArray,a.STATIC_DRAW);this.vertexBuffer.itemSize=3;this.vertexBuffer.numItems=parseInt(this.vertexArray.length/3,10);this.normalBuffer=a.createBuffer();a.bindBuffer(a.ARRAY_BUFFER,this.normalBuffer);a.bufferData(a.ARRAY_BUFFER,this.normalArray,a.STATIC_DRAW);this.normalBuffer.itemSize=3;this.normalBuffer.numItems=
parseInt(this.normalArray.length/3,10);null!==this.uvArray&&(this.uvBuffer=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),a.bufferData(a.ARRAY_BUFFER,this.uvArray,a.STATIC_DRAW),this.uvBuffer.itemSize=2,this.uvBuffer.numItems=parseInt(this.uvArray.length/2,10))};JSM.Renderer=function(){this.geometries=this.light=this.camera=this.texShader=this.shader=this.context=this.canvas=null};
JSM.Renderer.prototype.Init=function(a,b,c){return!this.InitContext(a)||!this.InitView(b,c)||!this.InitShaders()||!this.InitBuffers()?!1:!0};
JSM.Renderer.prototype.InitContext=function(a){if(!window.WebGLRenderingContext)return!1;this.canvas=document.getElementById(a);if(null===this.canvas||void 0===this.canvas.getContext)return!1;this.context=this.canvas.getContext("webgl")||this.canvas.getContext("experimental-webgl");if(null===this.context)return!1;this.context.viewportWidth=this.canvas.width;this.context.viewportHeight=this.canvas.height;this.context.viewport(0,0,this.context.viewportWidth,this.context.viewportHeight);this.context.clearColor(1,
1,1,1);this.context.enable(this.context.DEPTH_TEST);this.context.depthFunc(this.context.LEQUAL);this.context.enable(this.context.BLEND);this.context.blendEquation(this.context.FUNC_ADD);this.context.blendFunc(this.context.SRC_ALPHA,this.context.ONE_MINUS_SRC_ALPHA);return!0};
JSM.Renderer.prototype.InitShaders=function(){function a(a,b,c){c=a.createShader(c);a.shaderSource(c,b);a.compileShader(c);return!a.getShaderParameter(c,a.COMPILE_STATUS)?null:c}function b(b,c,d){c=a(b,c,b.FRAGMENT_SHADER);d=a(b,d,b.VERTEX_SHADER);if(null===c||null===d)return null;var e=b.createProgram();b.attachShader(e,d);b.attachShader(e,c);b.linkProgram(e);return!b.getProgramParameter(e,b.LINK_STATUS)?null:e}function c(a){var b="";a&&(b="#define USETEXTURE");return[b,"uniform highp vec3 uPolygonAmbientColor;\nuniform highp vec3 uPolygonDiffuseColor;\nuniform highp vec3 uPolygonSpecularColor;\nuniform highp float uPolygonShininess;\nuniform highp vec3 uLightAmbientColor;\nuniform highp vec3 uLightDiffuseColor;\nuniform highp vec3 uLightSpecularColor;\nvarying highp vec3 vVertex;\nvarying highp vec3 vNormal;\nvarying highp vec3 vLight;\n#ifdef USETEXTURE\nvarying highp vec2 vUV;\nuniform sampler2D uSampler;\n#endif\nvoid main (void) {\n\thighp vec3 N = normalize (vNormal);\n\tif (!gl_FrontFacing) {\n\t\tN = -N;\n\t}\n\thighp vec3 L = normalize (-vLight);\n\thighp vec3 E = normalize (-vVertex);\n\thighp vec3 R = normalize (-reflect (L, N));\n\thighp vec3 ambientComponent = uPolygonAmbientColor * uLightAmbientColor;\n\thighp vec3 diffuseComponent = uPolygonDiffuseColor * uLightDiffuseColor * max (dot (N, L), 0.0);\n\thighp vec3 specularComponent = uPolygonSpecularColor * uLightSpecularColor * pow (max (dot (R, E), 0.0), uPolygonShininess);\n#ifdef USETEXTURE\n\thighp vec3 textureColor = texture2D (uSampler, vec2 (vUV.s, vUV.t)).xyz;\n\tambientComponent = textureColor * ambientComponent;\n\tdiffuseComponent = textureColor * diffuseComponent;\n\tspecularComponent = textureColor * specularComponent;\n#endif\n\tambientComponent = clamp (ambientComponent, 0.0, 1.0);\n\tdiffuseComponent = clamp (diffuseComponent, 0.0, 1.0);\n\tspecularComponent = clamp (specularComponent, 0.0, 1.0);\n\tgl_FragColor = vec4 (ambientComponent + diffuseComponent + specularComponent, 1.0);\n}"].join("\n")}
function d(a){var b="";a&&(b="#define USETEXTURE");return[b,"attribute highp vec3 aVertexPosition;\nattribute highp vec3 aVertexNormal;\nuniform highp mat4 uViewMatrix;\nuniform highp mat4 uModelViewMatrix;\nuniform highp mat4 uProjectionMatrix;\nuniform highp vec3 uLightDirection;\nvarying highp vec3 vVertex;\nvarying highp vec3 vNormal;\nvarying highp vec3 vLight;\n#ifdef USETEXTURE\nattribute highp vec2 aVertexUV;\nvarying highp vec2 vUV;\n#endif\nvoid main (void) {\n\tvVertex = vec3 (uModelViewMatrix * vec4 (aVertexPosition, 1.0));\n\tvNormal = normalize (vec3 (uModelViewMatrix * vec4 (aVertexNormal, 0.0)));\n\tvLight = normalize (vec3 (uViewMatrix * vec4 (uLightDirection, 0.0)));\n#ifdef USETEXTURE\n\tvUV = aVertexUV;\n#endif\n\tgl_Position = uProjectionMatrix * vec4 (vVertex, 1.0);\n}"].join("\n")}
function e(a,b){b.vertexPositionAttribute=a.getAttribLocation(b,"aVertexPosition");b.vertexNormalAttribute=a.getAttribLocation(b,"aVertexNormal");b.lightAmbientColorUniform=a.getUniformLocation(b,"uLightAmbientColor");b.lightDiffuseColorUniform=a.getUniformLocation(b,"uLightDiffuseColor");b.lightSpecularColorUniform=a.getUniformLocation(b,"uLightSpecularColor");b.lightDirectionUniform=a.getUniformLocation(b,"uLightDirection");b.vMatrixUniform=a.getUniformLocation(b,"uViewMatrix");b.mvMatrixUniform=
a.getUniformLocation(b,"uModelViewMatrix");b.pMatrixUniform=a.getUniformLocation(b,"uProjectionMatrix");b.polygonAmbientColorUniform=a.getUniformLocation(b,"uPolygonAmbientColor");b.polygonDiffuseColorUniform=a.getUniformLocation(b,"uPolygonDiffuseColor");b.polygonSpecularColorUniform=a.getUniformLocation(b,"uPolygonSpecularColor");b.polygonShininessUniform=a.getUniformLocation(b,"uPolygonShininess")}this.shader=function(a){var g=c(!1),h=d(!1),g=b(a,g,h);if(null===g)return null;a.useProgram(g);e(a,
g);return g}(this.context);if(null===this.shader)return!1;this.texShader=function(a){var g=c(!0),h=d(!0),g=b(a,g,h);if(null===g)return null;a.useProgram(g);e(a,g);g.vertexUVAttribute=a.getAttribLocation(g,"aVertexUV");g.samplerUniform=a.getUniformLocation(g,"uSampler");return g}(this.context);return null===this.texShader?!1:!0};JSM.Renderer.prototype.InitBuffers=function(){this.geometries=[];return!0};
JSM.Renderer.prototype.InitView=function(a,b){this.camera=JSM.ValueOrDefault(a,new JSM.Camera);if(!this.camera)return!1;this.light=JSM.ValueOrDefault(b,new JSM.Light);return!this.light?!1:!0};JSM.Renderer.prototype.SetClearColor=function(a,b,c){this.context.clearColor(a,b,c,1)};JSM.Renderer.prototype.AddGeometries=function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.Compile(this.context,this.Render.bind(this)),this.geometries.push(c)};
JSM.Renderer.prototype.RemoveGeometries=function(){this.geometries=[]};JSM.Renderer.prototype.Resize=function(){this.context.viewportWidth=this.canvas.width;this.context.viewportHeight=this.canvas.height;this.context.viewport(0,0,this.context.viewportWidth,this.context.viewportHeight)};
JSM.Renderer.prototype.Render=function(){this.context.clear(this.context.COLOR_BUFFER_BIT|this.context.DEPTH_BUFFER_BIT);var a=JSM.MatrixPerspective(this.camera.fieldOfView*JSM.DegRad,this.context.viewportWidth/this.context.viewportHeight,this.camera.nearClippingPlane,this.camera.farClippingPlane),b=JSM.MatrixView(this.camera.eye,this.camera.center,this.camera.up),c=JSM.MatrixIdentity(),d=JSM.HexColorToNormalizedRGBComponents(this.light.ambient),e=JSM.HexColorToNormalizedRGBComponents(this.light.diffuse),
f=JSM.HexColorToNormalizedRGBComponents(this.light.specular);this.light.direction=JSM.VectorNormalize(JSM.CoordSub(this.camera.center,this.camera.eye));var g,h,l,k,m,n;for(g=0;g<this.geometries.length;g++)m=this.geometries[g],c=m.GetMaterial().HasTexture()?this.texShader:this.shader,n!=c&&(n=c,this.context.useProgram(n),this.context.uniformMatrix4fv(n.pMatrixUniform,!1,a),this.context.uniformMatrix4fv(n.vMatrixUniform,!1,b),this.context.uniform3f(n.lightDirectionUniform,this.light.direction.x,this.light.direction.y,
this.light.direction.z),this.context.uniform3f(n.lightAmbientColorUniform,d[0],d[1],d[2]),this.context.uniform3f(n.lightDiffuseColorUniform,e[0],e[1],e[2]),this.context.uniform3f(n.lightSpecularColorUniform,f[0],f[1],f[2])),c=m.material.ambient,h=m.material.diffuse,l=m.material.specular,k=m.material.shininess,this.context.uniform3f(n.polygonAmbientColorUniform,c[0],c[1],c[2]),this.context.uniform3f(n.polygonDiffuseColorUniform,h[0],h[1],h[2]),this.context.uniform3f(n.polygonSpecularColorUniform,l[0],
l[1],l[2]),this.context.uniform1f(n.polygonShininessUniform,k),n==this.texShader&&(c=m.GetUVBuffer(),this.context.activeTexture(this.context.TEXTURE0),this.context.bindTexture(this.context.TEXTURE_2D,m.material.textureBuffer),this.context.bindBuffer(this.context.ARRAY_BUFFER,c),this.context.vertexAttribPointer(n.vertexUVAttribute,c.itemSize,this.context.FLOAT,!1,0,0),this.context.enableVertexAttribArray(n.vertexUVAttribute),this.context.uniform1i(n.samplerUniform,0)),c=JSM.MatrixMultiply(m.GetTransformationMatrix(),
b),this.context.uniformMatrix4fv(n.mvMatrixUniform,!1,c),c=m.GetVertexBuffer(),this.context.bindBuffer(this.context.ARRAY_BUFFER,c),this.context.enableVertexAttribArray(n.vertexPositionAttribute),this.context.vertexAttribPointer(n.vertexPositionAttribute,c.itemSize,this.context.FLOAT,!1,0,0),m=m.GetNormalBuffer(),this.context.bindBuffer(this.context.ARRAY_BUFFER,m),this.context.enableVertexAttribArray(n.vertexNormalAttribute),this.context.vertexAttribPointer(n.vertexNormalAttribute,m.itemSize,this.context.FLOAT,
!1,0,0),this.context.drawArrays(this.context.TRIANGLES,0,c.numItems)};JSM.PointCloudRenderer=function(){this.pointSize=this.points=this.camera=this.shader=this.context=this.canvas=null};JSM.PointCloudRenderer.prototype.Init=function(a,b){return!this.InitContext(a)||!this.InitShaders()||!this.InitBuffers()||!this.InitView(b)?!1:!0};
JSM.PointCloudRenderer.prototype.InitContext=function(a){if(!window.WebGLRenderingContext)return!1;this.canvas=document.getElementById(a);if(null===this.canvas||void 0===this.canvas.getContext)return!1;this.context=this.canvas.getContext("experimental-webgl");if(null===this.context)return!1;this.context.viewportWidth=this.canvas.width;this.context.viewportHeight=this.canvas.height;this.context.clearColor(1,1,1,1);this.context.enable(this.context.DEPTH_TEST);return!0};
JSM.PointCloudRenderer.prototype.InitShaders=function(){function a(a,b,c){c=a.createShader(c);a.shaderSource(c,b);a.compileShader(c);return!a.getShaderParameter(c,a.COMPILE_STATUS)?null:c}var b=a(this.context,"varying highp vec3 vColor;\nvoid main (void) {\n\tgl_FragColor = vec4 (vColor, 1.0);\n}",this.context.FRAGMENT_SHADER),c=a(this.context,"attribute highp vec3 aVertexPosition;\nattribute highp vec3 aVertexColor;\nuniform highp mat4 uViewMatrix;\nuniform highp mat4 uProjectionMatrix;\nuniform highp float uPointSize;\nvarying highp vec3 vColor;\nvoid main (void) {\n\tvColor = aVertexColor;\n\tgl_PointSize = uPointSize;\n\tgl_Position = uProjectionMatrix * uViewMatrix * vec4 (aVertexPosition, 1.0);\n}",
this.context.VERTEX_SHADER);if(null===b||null===c)return!1;this.shader=this.context.createProgram();this.context.attachShader(this.shader,c);this.context.attachShader(this.shader,b);this.context.linkProgram(this.shader);if(!this.context.getProgramParameter(this.shader,this.context.LINK_STATUS))return!1;this.context.useProgram(this.shader);this.shader.vertexPositionAttribute=this.context.getAttribLocation(this.shader,"aVertexPosition");this.context.enableVertexAttribArray(this.shader.vertexPositionAttribute);
this.shader.vertexColorAttribute=this.context.getAttribLocation(this.shader,"aVertexColor");this.context.enableVertexAttribArray(this.shader.vertexColorAttribute);this.shader.pMatrixUniform=this.context.getUniformLocation(this.shader,"uProjectionMatrix");this.shader.vMatrixUniform=this.context.getUniformLocation(this.shader,"uViewMatrix");this.shader.pointSizeUniform=this.context.getUniformLocation(this.shader,"uPointSize");return!0};
JSM.PointCloudRenderer.prototype.InitBuffers=function(){this.points=[];this.pointSize=1;return!0};JSM.PointCloudRenderer.prototype.InitView=function(a){this.camera=JSM.ValueOrDefault(a,new JSM.Camera);return!this.camera?!1:!0};JSM.PointCloudRenderer.prototype.SetClearColor=function(a,b,c){this.context.clearColor(a,b,c,1)};JSM.PointCloudRenderer.prototype.SetPointSize=function(a){this.pointSize=a};
JSM.PointCloudRenderer.prototype.AddPoints=function(a,b){var c=this.context.createBuffer(),d=new Float32Array(a);this.context.bindBuffer(this.context.ARRAY_BUFFER,c);this.context.bufferData(this.context.ARRAY_BUFFER,d,this.context.STATIC_DRAW);c.itemSize=3;c.numItems=parseInt(d.length/3,10);var e=this.context.createBuffer(),f=new Float32Array(b);this.context.bindBuffer(this.context.ARRAY_BUFFER,e);this.context.bufferData(this.context.ARRAY_BUFFER,f,this.context.STATIC_DRAW);e.itemSize=3;e.numItems=
parseInt(f.length/3,10);this.points.push({pointArray:d,pointBuffer:c,colorBuffer:e})};JSM.PointCloudRenderer.prototype.RemovePoints=function(){this.points=[]};JSM.PointCloudRenderer.prototype.Resize=function(){this.context.viewportWidth=this.canvas.width;this.context.viewportHeight=this.canvas.height};
JSM.PointCloudRenderer.prototype.Render=function(){this.context.viewport(0,0,this.context.viewportWidth,this.context.viewportHeight);this.context.clear(this.context.COLOR_BUFFER_BIT|this.context.DEPTH_BUFFER_BIT);var a=JSM.MatrixPerspective(this.camera.fieldOfView*JSM.DegRad,this.context.viewportWidth/this.context.viewportHeight,this.camera.nearClippingPlane,this.camera.farClippingPlane);this.context.uniformMatrix4fv(this.shader.pMatrixUniform,!1,a);a=JSM.MatrixView(this.camera.eye,this.camera.center,
this.camera.up);this.context.uniformMatrix4fv(this.shader.vMatrixUniform,!1,a);this.context.uniform1f(this.shader.pointSizeUniform,this.pointSize);for(var b,c,a=0;a<this.points.length;a++)b=this.points[a].pointBuffer,c=this.points[a].colorBuffer,this.context.bindBuffer(this.context.ARRAY_BUFFER,b),this.context.vertexAttribPointer(this.shader.vertexPositionAttribute,b.itemSize,this.context.FLOAT,!1,0,0),this.context.bindBuffer(this.context.ARRAY_BUFFER,c),this.context.vertexAttribPointer(this.shader.vertexColorAttribute,
c.itemSize,this.context.FLOAT,!1,0,0),this.context.drawArrays(this.context.POINTS,0,b.numItems)};
JSM.ConvertBodyToRenderGeometries=function(a,b){var c=[],d=null,e=null,f=null,g=null;JSM.ExplodeBodyToTriangles(a,b,{hasConvexPolygons:!1,onGeometryStart:function(a){e=[];f=[];g=[];var b=JSM.HexColorToNormalizedRGBComponents(a.ambient),k=JSM.HexColorToNormalizedRGBComponents(a.diffuse),m=JSM.HexColorToNormalizedRGBComponents(a.specular);a=new JSM.RenderMaterial(b,k,m,a.shininess,a.texture,a.textureWidth,a.textureHeight);d=new JSM.RenderGeometry;d.SetMaterial(a);c.push(d)},onGeometryEnd:function(a){d.SetVertexArray(e);
d.SetNormalArray(f);null!==a.texture&&d.SetUVArray(g)},onTriangle:function(a,b,c,d,n,p,q,r,s){e.push(a.x,a.y,a.z);e.push(b.x,b.y,b.z);e.push(c.x,c.y,c.z);f.push(d.x,d.y,d.z);f.push(n.x,n.y,n.z);f.push(p.x,p.y,p.z);null!==q&&(null!==r&&null!==s)&&(g.push(q.x,q.y),g.push(r.x,r.y),g.push(s.x,s.y))}});return c};JSM.ConvertModelToRenderGeometries=function(a,b){var c=[],d,e;for(d=0;d<a.BodyCount();d++){e=a.GetBody(d);var f=JSM.ConvertBodyToRenderGeometries(e,b,c);for(e=0;e<f.length;e++)c.push(f[e])}return c};
JSM.JSONFileLoader=function(a){this.onReady=a};JSM.JSONFileLoader.prototype.Load=function(a){var b=this,c=new XMLHttpRequest;c.overrideMimeType("application/json");c.open("GET",a,!0);c.onreadystatechange=function(){4==c.readyState&&b.OnReady(c.responseText)};c.send(null)};JSM.JSONFileLoader.prototype.OnReady=function(a){null!==this.onReady&&(a=JSON.parse(a),this.onReady(a))};
JSM.Mouse=function(){this.down=!1;this.button=0;this.alt=this.ctrl=this.shift=!1;this.diffY=this.diffX=this.currY=this.currX=this.prevY=this.prevX=0};JSM.Mouse.prototype.Down=function(a,b){var c=a;void 0===c&&(c=window.event);this.down=!0;this.button=a.which;this.shift=a.shiftKey;this.ctrl=a.ctrlKey;this.alt=a.altKey;this.SetCurrent(c,b);this.prevX=this.currX;this.prevY=this.currY};
JSM.Mouse.prototype.Move=function(a,b){var c=a;void 0===c&&(c=window.event);this.shift=a.shiftKey;this.ctrl=a.ctrlKey;this.alt=a.altKey;this.SetCurrent(c,b);this.diffX=this.currX-this.prevX;this.diffY=this.currY-this.prevY;this.prevX=this.currX;this.prevY=this.currY};JSM.Mouse.prototype.Up=function(a,b){var c=a;void 0===c&&(c=window.event);this.down=!1;this.SetCurrent(c,b)};JSM.Mouse.prototype.Out=function(a,b){var c=a;void 0===c&&(c=window.event);this.down=!1;this.SetCurrent(c,b)};
JSM.Mouse.prototype.SetCurrent=function(a,b){this.currX=a.clientX;this.currY=a.clientY;void 0!==b&&(void 0!==b.offsetLeft&&void 0!==b.offsetTop)&&(this.currX-=b.offsetLeft,this.currY-=b.offsetTop)};JSM.Touch=function(){this.down=!1;this.diffY=this.diffX=this.currY=this.currX=this.prevY=this.prevX=0};JSM.Touch.prototype.Start=function(a,b){if(0!==a.touches.length){var c=a.touches[0];this.down=!0;this.SetCurrent(c,b);this.prevX=this.currX;this.prevY=this.currY}};
JSM.Touch.prototype.Move=function(a,b){0!==a.touches.length&&(this.SetCurrent(a.touches[0],b),this.diffX=this.currX-this.prevX,this.diffY=this.currY-this.prevY,this.prevX=this.currX,this.prevY=this.currY)};JSM.Touch.prototype.End=function(a,b){if(0!==a.touches.length){var c=a.touches[0];this.down=!1;this.SetCurrent(c,b)}};
JSM.Touch.prototype.SetCurrent=function(a,b){this.currX=a.pageX;this.currY=a.pageY;void 0!==b&&(void 0!==b.offsetLeft&&void 0!==b.offsetTop)&&(this.currX=a.pageX-b.offsetLeft,this.currY=a.pageY-b.offsetTop)};JSM.Navigation=function(){this.orbitCenter=this.cameraEnableZoom=this.cameraEnablePan=this.cameraEnableOrbit=this.cameraFixUp=this.touch=this.mouse=this.resizeCallback=this.drawCallback=this.camera=this.canvas=null};
JSM.Navigation.prototype.Init=function(a,b,c,d){this.canvas=a;this.camera=b;this.drawCallback=c;this.resizeCallback=d;this.mouse=new JSM.Mouse;this.touch=new JSM.Touch;this.cameraEnableZoom=this.cameraEnablePan=this.cameraEnableOrbit=this.cameraFixUp=!0;this.orbitCenter=this.camera.center.Clone();var e=this;document.addEventListener&&(document.addEventListener("mousemove",function(a){e.OnMouseMove(a)}),document.addEventListener("mouseup",function(a){e.OnMouseUp(a)}));this.canvas.addEventListener&&
(this.canvas.addEventListener("mousedown",function(a){e.OnMouseDown(a)},!1),this.canvas.addEventListener("DOMMouseScroll",function(a){e.OnMouseWheel(a)},!1),this.canvas.addEventListener("mousewheel",function(a){e.OnMouseWheel(a)},!1),this.canvas.addEventListener("touchstart",function(a){e.OnTouchStart(a)},!1),this.canvas.addEventListener("touchmove",function(a){e.OnTouchMove(a)},!1),this.canvas.addEventListener("touchend",function(a){e.OnTouchEnd(a)},!1),this.canvas.addEventListener("contextmenu",
function(a){e.OnContextMenu(a)},!1));window.addEventListener&&window.addEventListener("resize",function(a){e.OnResize(a)},!1);return!0};JSM.Navigation.prototype.SetCamera=function(a,b,c){this.camera.Set(a,b,c);this.orbitCenter=this.camera.center.Clone()};JSM.Navigation.prototype.EnableFixUp=function(a){this.cameraFixUp=a};JSM.Navigation.prototype.EnableOrbit=function(a){this.cameraEnableOrbit=a};JSM.Navigation.prototype.EnablePan=function(a){this.cameraEnablePan=a};
JSM.Navigation.prototype.EnableZoom=function(a){this.cameraEnableZoom=a};JSM.Navigation.prototype.SetOrbitCenter=function(a){this.orbitCenter=a};
JSM.Navigation.prototype.FitInWindow=function(a,b){var c=JSM.CoordSub(this.camera.center,a);this.camera.center=a;this.camera.eye=JSM.CoordSub(this.camera.eye,c);var c=JSM.VectorNormalize(JSM.CoordSub(this.camera.eye,this.camera.center)),d=this.camera.fieldOfView/2;this.canvas.width<this.canvas.height&&(d=d*this.canvas.width/this.canvas.height);d=b/Math.sin(d*JSM.DegRad);this.camera.eye=JSM.CoordOffset(this.camera.center,c,d);this.orbitCenter=this.camera.center.Clone()};
JSM.Navigation.prototype.Orbit=function(a,b){var c=a*JSM.DegRad,d=b*JSM.DegRad,e=JSM.VectorNormalize(JSM.CoordSub(this.camera.center,this.camera.eye)),f=JSM.VectorNormalize(JSM.VectorCross(e,this.camera.up)),g=!JSM.CoordIsEqual(this.orbitCenter,this.camera.center);this.cameraFixUp?(e=JSM.GetVectorsAngle(e,this.camera.up)+d,JSM.IsGreater(e,0)&&JSM.IsLower(e,Math.PI)&&(this.camera.eye=JSM.CoordRotate(this.camera.eye,f,-d,this.orbitCenter),g&&(this.camera.center=JSM.CoordRotate(this.camera.center,f,
-d,this.orbitCenter))),this.camera.eye=JSM.CoordRotate(this.camera.eye,this.camera.up,-c,this.orbitCenter),g&&(this.camera.center=JSM.CoordRotate(this.camera.center,this.camera.up,-c,this.orbitCenter))):(e=JSM.VectorNormalize(JSM.VectorCross(f,e)),this.camera.eye=JSM.CoordRotate(this.camera.eye,f,-d,this.orbitCenter),this.camera.eye=JSM.CoordRotate(this.camera.eye,e,-c,this.orbitCenter),g&&(this.camera.center=JSM.CoordRotate(this.camera.center,f,-d,this.orbitCenter),this.camera.center=JSM.CoordRotate(this.camera.center,
e,-c,this.orbitCenter)),this.camera.up=e)};JSM.Navigation.prototype.Pan=function(a,b){var c=JSM.VectorNormalize(JSM.CoordSub(this.camera.center,this.camera.eye)),d=JSM.VectorNormalize(JSM.VectorCross(c,this.camera.up)),c=JSM.VectorNormalize(JSM.VectorCross(d,c));this.camera.eye=JSM.CoordOffset(this.camera.eye,d,-a);this.camera.center=JSM.CoordOffset(this.camera.center,d,-a);this.camera.eye=JSM.CoordOffset(this.camera.eye,c,b);this.camera.center=JSM.CoordOffset(this.camera.center,c,b)};
JSM.Navigation.prototype.Zoom=function(a){var b=JSM.CoordSub(this.camera.center,this.camera.eye),c=JSM.VectorLength(b);if(a&&0.1>c)return 0;c*=0.1;a||(c*=-1);this.camera.eye=JSM.CoordOffset(this.camera.eye,b,c)};JSM.Navigation.prototype.DrawCallback=function(){void 0!==this.drawCallback&&null!==this.drawCallback&&this.drawCallback()};JSM.Navigation.prototype.ResizeCallback=function(){void 0!==this.resizeCallback&&null!==this.resizeCallback&&this.resizeCallback()};
JSM.Navigation.prototype.OnMouseDown=function(a){a.preventDefault();this.mouse.Down(a,this.canvas)};JSM.Navigation.prototype.OnMouseMove=function(a){a.preventDefault();this.mouse.Move(a,this.canvas);this.mouse.down&&(a=0,1==this.mouse.button?this.cameraEnableOrbit&&(a=0.5,this.Orbit(this.mouse.diffX*a,this.mouse.diffY*a),this.DrawCallback()):3==this.mouse.button&&this.cameraEnablePan&&(a=0.001*JSM.CoordDistance(this.camera.eye,this.camera.center),this.Pan(this.mouse.diffX*a,this.mouse.diffY*a),this.DrawCallback()))};
JSM.Navigation.prototype.OnMouseUp=function(a){a.preventDefault();this.mouse.Up(a,this.canvas)};JSM.Navigation.prototype.OnMouseOut=function(a){a.preventDefault();this.mouse.Out(a,this.canvas)};JSM.Navigation.prototype.OnMouseWheel=function(a){a.preventDefault();if(this.cameraEnableZoom){null===a&&(a=window.event);var b=0;a.detail?b=-a.detail:a.wheelDelta&&(b=a.wheelDelta/40);this.Zoom(0<b);this.DrawCallback()}};
JSM.Navigation.prototype.OnTouchStart=function(a){a.preventDefault();this.touch.Start(a,this.canvas)};JSM.Navigation.prototype.OnTouchMove=function(a){a.preventDefault();this.touch.Move(a,this.canvas);this.touch.down&&this.cameraEnableOrbit&&(this.Orbit(0.5*this.touch.diffX,0.5*this.touch.diffY),this.DrawCallback())};JSM.Navigation.prototype.OnTouchEnd=function(a){a.preventDefault();this.touch.End(a,this.canvas)};JSM.Navigation.prototype.OnContextMenu=function(a){a.preventDefault()};
JSM.Navigation.prototype.OnResize=function(a){a.preventDefault();this.ResizeCallback()};JSM.SoftwareViewer=function(){this.navigation=this.drawMode=this.drawer=this.bodies=this.camera=this.canvas=null};JSM.SoftwareViewer.prototype.Start=function(a,b){return!this.InitCanvas(a)||!this.InitCamera(b)?!1:!0};
JSM.SoftwareViewer.prototype.InitCanvas=function(a){this.bodies=[];this.canvas=document.getElementById(a);if(!this.canvas)return!1;this.canvas instanceof HTMLCanvasElement?this.drawer=new JSM.CanvasDrawer(this.canvas):this.canvas instanceof SVGSVGElement&&(this.drawer=new JSM.SVGDrawer(this.canvas));if(!this.drawer)return!1;this.drawMode="Wireframe";return!0};
JSM.SoftwareViewer.prototype.InitCamera=function(a){this.camera=JSM.ValueOrDefault(a,new JSM.Camera);if(!this.camera)return!1;this.navigation=new JSM.Navigation;return!this.navigation.Init(this.canvas,this.camera,this.Draw.bind(this),this.Resize.bind(this))?!1:!0};JSM.SoftwareViewer.prototype.AddBody=function(a,b){this.bodies.push([a,b])};JSM.SoftwareViewer.prototype.RemoveBodies=function(){this.bodies=[]};
JSM.SoftwareViewer.prototype.FitInWindow=function(){var a=this.GetCenter(),b=this.GetBoundingSphereRadius(a);this.navigation.FitInWindow(a,b);this.Draw()};JSM.SoftwareViewer.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.SoftwareViewer.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d,e,f;for(c=0;c<this.bodies.length;c++){e=this.bodies[c][0];for(d=0;d<e.VertexCount();d++)f=e.GetVertex(d),a.x=JSM.Minimum(a.x,f.position.x),a.y=JSM.Minimum(a.y,f.position.y),a.z=JSM.Minimum(a.z,f.position.z),b.x=JSM.Maximum(b.x,f.position.x),b.y=JSM.Maximum(b.y,f.position.y),b.z=JSM.Maximum(b.z,f.position.z)}return[a,b]};
JSM.SoftwareViewer.prototype.GetBoundingSphereRadius=function(a){if(void 0===a||null===a)a=this.GetCenter();var b=0,c,d,e,f;for(c=0;c<this.bodies.length;c++){e=this.bodies[c][0];for(d=0;d<e.VertexCount();d++)f=e.GetVertex(d),f=JSM.CoordDistance(a,f.position),JSM.IsGreater(f,b)&&(b=f)}return b};JSM.SoftwareViewer.prototype.Resize=function(){this.Draw()};
JSM.SoftwareViewer.prototype.Draw=function(){var a,b;this.drawer.Clear();for(a=0;a<this.bodies.length;a++)b=this.bodies[a],JSM.DrawProjectedBody(b[0],b[1],this.camera,this.drawMode,!1,this.drawer);return!0};JSM.SpriteViewer=function(){this.navigation=this.projected=this.points=this.callbacks=this.camera=this.canvas=null};JSM.SpriteViewer.prototype.Start=function(a,b,c){return!this.InitCanvas(a)||!this.InitCamera(b)||!this.InitCallbacks(c)?!1:!0};
JSM.SpriteViewer.prototype.InitCanvas=function(a){this.points=[];this.canvas=document.getElementById(a);return!this.canvas?!1:!0};JSM.SpriteViewer.prototype.InitCamera=function(a){this.camera=JSM.ValueOrDefault(a,new JSM.Camera);if(!this.camera)return!1;this.navigation=new JSM.Navigation;return!this.navigation.Init(this.canvas,this.camera,this.Draw.bind(this))?!1:!0};
JSM.SpriteViewer.prototype.InitCallbacks=function(a){this.callbacks={onPointDraw:null};void 0!==a&&(void 0!==a.onDrawStart&&(this.callbacks.onDrawStart=a.onDrawStart),void 0!==a.onPointDraw&&(this.callbacks.onPointDraw=a.onPointDraw),void 0!==a.onDrawEnd&&(this.callbacks.onDrawEnd=a.onDrawEnd));return!0};JSM.SpriteViewer.prototype.AddPoint=function(a){this.points.push(a)};JSM.SpriteViewer.prototype.RemovePoints=function(){this.points=[]};JSM.SpriteViewer.prototype.Resize=function(){this.Draw()};
JSM.SpriteViewer.prototype.NearestPointUnderPosition=function(a,b,c){b=new JSM.Coord2D(b,c);c=-1;var d=JSM.Inf,e,f,g;for(e=0;e<this.projected.length;e++)f=this.projected[e],g=JSM.CoordDistance2D(new JSM.Coord2D(f.position.x,f.position.y),b),JSM.IsLower(g,a)&&JSM.IsLower(g,d)&&(c=f.originalIndex,d=g);return c};JSM.SpriteViewer.prototype.NearestPointUnderMouse=function(a){return this.NearestPointUnderPosition(a,this.navigation.mouse.currX,this.navigation.mouse.currY)};
JSM.SpriteViewer.prototype.NearestPointUnderTouch=function(a){return this.NearestPointUnderPosition(a,this.navigation.touch.currX,this.navigation.touch.currY)};JSM.SpriteViewer.prototype.FitInWindow=function(){var a=this.GetCenter(),b=this.GetBoundingSphereRadius(a);this.navigation.FitInWindow(a,b);this.Draw()};JSM.SpriteViewer.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.SpriteViewer.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d;for(c=0;c<this.points.length;c++)d=this.points[c],a.x=JSM.Minimum(a.x,d.x),a.y=JSM.Minimum(a.y,d.y),a.z=JSM.Minimum(a.z,d.z),b.x=JSM.Maximum(b.x,d.x),b.y=JSM.Maximum(b.y,d.y),b.z=JSM.Maximum(b.z,d.z);return[a,b]};
JSM.SpriteViewer.prototype.GetBoundingSphereRadius=function(a){if(void 0===a||null===a)a=this.GetCenter();var b=0,c,d;for(c=0;c<this.points.length;c++)d=this.points[c],d=JSM.CoordDistance(a,d),JSM.IsGreater(d,b)&&(b=d);return b};
JSM.SpriteViewer.prototype.Draw=function(){if(null!==this.callbacks.onDrawStart)this.callbacks.onDrawStart(this.canvas);var a=this.canvas.width/this.canvas.height,b=[0,0,this.canvas.width,this.canvas.height];this.projected=[];var c,d;for(c=0;c<this.points.length;c++)d=this.points[c],d=JSM.Project(d,this.camera.eye,this.camera.center,this.camera.up,this.camera.fieldOfView*JSM.DegRad,a,this.camera.nearClippingPlane,this.camera.farClippingPlane,b),d.y=this.canvas.height-d.y,null!==d&&this.projected.push({position:d,
originalIndex:c});this.projected.sort(function(a,b){return a.position.z>b.position.z?-1:a.position.z<b.position.z?1:0});for(c=0;c<this.projected.length;c++)if(null!==this.callbacks.onPointDraw)this.callbacks.onPointDraw(this.canvas,this.projected[c].originalIndex,this.projected[c].position);if(null!==this.callbacks.onDrawEnd)this.callbacks.onDrawEnd(this.canvas);return!0};JSM.Viewer=function(){this.navigation=this.renderer=this.canvas=null};
JSM.Viewer.prototype.Init=function(a,b,c){return!this.InitRenderer(a,b,c)||!this.InitNavigation()?!1:!0};JSM.Viewer.prototype.InitRenderer=function(a,b,c){this.renderer=new JSM.Renderer;return!this.renderer.Init(a,b,c)?!1:!0};JSM.Viewer.prototype.InitNavigation=function(){this.navigation=new JSM.Navigation;return!this.navigation.Init(this.renderer.canvas,this.renderer.camera,this.Draw.bind(this),this.Resize.bind(this))?!1:!0};
JSM.Viewer.prototype.SetClearColor=function(a,b,c){this.renderer.SetClearColor(a,b,c);this.Draw()};JSM.Viewer.prototype.AddGeometries=function(a){this.renderer.AddGeometries(a);this.Draw()};JSM.Viewer.prototype.RemoveGeometries=function(){this.renderer.RemoveGeometries();this.Draw()};JSM.Viewer.prototype.FitInWindow=function(){var a=this.GetCenter(),b=this.GetBoundingSphereRadius(a);this.navigation.FitInWindow(a,b);this.Draw()};
JSM.Viewer.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.Viewer.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d,e,f;for(c=0;c<this.renderer.geometries.length;c++){e=this.renderer.geometries[c];for(d=0;d<e.VertexCount();d+=1)f=e.GetTransformedVertex(d),a.x=JSM.Minimum(a.x,f.x),a.y=JSM.Minimum(a.y,f.y),a.z=JSM.Minimum(a.z,f.z),b.x=JSM.Maximum(b.x,f.x),b.y=JSM.Maximum(b.y,f.y),b.z=JSM.Maximum(b.z,f.z)}return[a,b]};
JSM.Viewer.prototype.GetBoundingSphereRadius=function(a){if(void 0===a||null===a)a=this.GetCenter();var b=0,c,d,e,f;for(c=0;c<this.renderer.geometries.length;c++){e=this.renderer.geometries[c];for(d=0;d<e.VertexCount();d+=1)f=e.GetTransformedVertex(d),f=JSM.CoordDistance(a,f),JSM.IsGreater(f,b)&&(b=f)}return b};JSM.Viewer.prototype.Resize=function(){this.renderer.Resize();this.Draw()};JSM.Viewer.prototype.Draw=function(){this.renderer.Render()};
JSM.PointCloudViewer=function(){this.navigation=this.renderer=this.canvas=null};JSM.PointCloudViewer.prototype.Init=function(a,b){return!this.InitRenderer(a,b)||!this.InitNavigation()?!1:!0};JSM.PointCloudViewer.prototype.InitRenderer=function(a,b){this.renderer=new JSM.PointCloudRenderer;return!this.renderer.Init(a,b)?!1:!0};
JSM.PointCloudViewer.prototype.InitNavigation=function(){this.navigation=new JSM.Navigation;return!this.navigation.Init(this.renderer.canvas,this.renderer.camera,this.Draw.bind(this),this.Resize.bind(this))?!1:!0};JSM.PointCloudViewer.prototype.SetClearColor=function(a,b,c){this.renderer.SetClearColor(a,b,c)};JSM.PointCloudViewer.prototype.SetPointSize=function(a){this.renderer.SetPointSize(a)};JSM.PointCloudViewer.prototype.AddPoints=function(a,b){this.renderer.AddPoints(a,b)};
JSM.PointCloudViewer.prototype.RemovePoints=function(){this.renderer.RemovePoints()};JSM.PointCloudViewer.prototype.FitInWindow=function(){var a=this.GetCenter(),b=this.GetBoundingSphereRadius(a);this.navigation.FitInWindow(a,b);this.Draw()};JSM.PointCloudViewer.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.PointCloudViewer.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d,e,f;for(c=0;c<this.renderer.points.length;c++){e=this.renderer.points[c].pointArray;for(d=0;d<e.length;d+=3)f=new JSM.Coord(e[d],e[d+1],e[d+2]),a.x=JSM.Minimum(a.x,f.x),a.y=JSM.Minimum(a.y,f.y),a.z=JSM.Minimum(a.z,f.z),b.x=JSM.Maximum(b.x,f.x),b.y=JSM.Maximum(b.y,f.y),b.z=JSM.Maximum(b.z,f.z)}return[a,b]};
JSM.PointCloudViewer.prototype.GetBoundingSphereRadius=function(a){if(void 0===a||null===a)a=this.GetCenter();var b=0,c,d,e,f;for(c=0;c<this.renderer.points.length;c++){e=this.renderer.points[c].pointArray;for(d=0;d<e.length;d+=3)f=new JSM.Coord(e[d],e[d+1],e[d+2]),f=JSM.CoordDistance(a,f),JSM.IsGreater(f,b)&&(b=f)}return b};JSM.PointCloudViewer.prototype.Resize=function(){this.renderer.Resize();this.Draw()};JSM.PointCloudViewer.prototype.Draw=function(){this.renderer.Render()};
JSM.ConvertBodyToThreeMeshes=function(a,b,c){var d={textureLoadedCallback:null,hasConvexPolygons:!1,doubleSided:!0};void 0!==c&&null!==c&&(d.textureLoadedCallback=JSM.ValueOrDefault(c.textureLoadedCallback,d.textureLoadedCallback),d.hasConvexPolygons=JSM.ValueOrDefault(c.hasConvexPolygons,d.hasConvexPolygons),d.doubleSided=JSM.ValueOrDefault(c.doubleSided,d.doubleSided));var e=[],f=null;JSM.ExplodeBodyToTriangles(a,b,{hasConvexPolygons:d.hasConvexPolygons,onGeometryStart:function(){f=new THREE.Geometry},
onGeometryEnd:function(a){var b=null!==a.texture,c=1!==a.opacity,k=new THREE.MeshPhongMaterial({ambient:a.ambient,color:a.diffuse,specular:a.specular});d.doubleSided&&(k.side=THREE.DoubleSide);c&&(k.opacity=a.opacity,k.transparent=!0);b&&(a=THREE.ImageUtils.loadTexture(a.texture,new THREE.UVMapping,function(){null!==d.textureLoadedCallback&&d.textureLoadedCallback()}),a.wrapS=THREE.RepeatWrapping,a.wrapT=THREE.RepeatWrapping,k.map=a);f.computeFaceNormals();k=new THREE.Mesh(f,k);e.push(k)},onTriangle:function(a,
b,c,d,e,n,p,q,r){var s=f.vertices.length;f.vertices.push(new THREE.Vector3(a.x,a.y,a.z));f.vertices.push(new THREE.Vector3(b.x,b.y,b.z));f.vertices.push(new THREE.Vector3(c.x,c.y,c.z));a=new THREE.Face3(s+0,s+1,s+2);f.faces.push(a);null!==d&&(null!==e&&null!==n)&&(a=[],a.push(new THREE.Vector3(d.x,d.y,d.z)),a.push(new THREE.Vector3(e.x,e.y,e.z)),a.push(new THREE.Vector3(n.x,n.y,n.z)),f.faces[f.faces.length-1].vertexNormals=a);null!==p&&(null!==q&&null!==r)&&(d=[],d.push(new THREE.Vector2(p.x,-p.y)),
d.push(new THREE.Vector2(q.x,-q.y)),d.push(new THREE.Vector2(r.x,-r.y)),f.faceVertexUvs[0].push(d))}});return e};JSM.ConvertModelToThreeMeshes=function(a,b,c){var d=[],e=[],f,g;for(f=0;f<a.BodyCount();f++){e=a.GetBody(f);e=JSM.ConvertBodyToThreeMeshes(e,b,c);for(g=0;g<e.length;g++)d.push(e[g])}return d};
JSM.ConvertJSONDataToThreeMeshes=function(a,b,c){function d(a,c){function d(a){var l=a.parameters,m=f[a.material];a=m.texture;var r=m.offset,s=m.scale,C=new THREE.Color,u=new THREE.Color,H=new THREE.Color;C.setRGB(m.ambient[0],m.ambient[1],m.ambient[2]);u.setRGB(m.diffuse[0],m.diffuse[1],m.diffuse[2]);H.setRGB(m.specular[0],m.specular[1],m.specular[2]);void 0!==a&&(C.setRGB(1,1,1),u.setRGB(1,1,1),H.setRGB(1,1,1),void 0===r&&(r=[0,0]),void 0===s&&(s=[1,1]));C=new THREE.MeshPhongMaterial({ambient:u.getHex(),
color:u.getHex(),specular:H.getHex(),side:THREE.DoubleSide});1!==m.opacity&&(C.opacity=m.opacity,C.transparent=!0);void 0!==a&&(m=THREE.ImageUtils.loadTexture(a,new THREE.UVMapping,function(){void 0!==b&&null!==b&&b()}),m.wrapS=THREE.RepeatWrapping,m.wrapT=THREE.RepeatWrapping,C.map=m);var m=new THREE.Geometry,z,I,J,D,A,B,K,L,M,w;for(w=0;w<l.length;w+=9)z=3*l[w+0],I=3*l[w+1],J=3*l[w+2],D=3*l[w+3],A=3*l[w+4],B=3*l[w+5],u=2*l[w+6],H=2*l[w+7],K=2*l[w+8],L=m.vertices.length,M=m.faces.length,m.vertices.push(new THREE.Vector3(g[z+
0],g[z+1],g[z+2])),m.vertices.push(new THREE.Vector3(g[I+0],g[I+1],g[I+2])),m.vertices.push(new THREE.Vector3(g[J+0],g[J+1],g[J+2])),m.faces.push(new THREE.Face3(L+0,L+1,L+2)),z=[],z.push(new THREE.Vector3(h[D+0],h[D+1],h[D+2])),z.push(new THREE.Vector3(h[A+0],h[A+1],h[A+2])),z.push(new THREE.Vector3(h[B+0],h[B+1],h[B+2])),m.faces[M].vertexNormals=z,void 0!==a&&(D=[],D.push(new THREE.Vector2(r[0]+q[u+0]*s[0],r[1]+q[u+1]*s[1])),D.push(new THREE.Vector2(r[0]+q[H+0]*s[0],r[1]+q[H+1]*s[1])),D.push(new THREE.Vector2(r[0]+
q[K+0]*s[0],r[1]+q[K+1]*s[1])),m.faceVertexUvs[0].push(D));l=new THREE.Mesh(m,C);l.originalJsonIndex=c;e.push(l)}var g=a.vertices;if(void 0!==g){var h=a.normals;if(void 0!==h){var q=a.uvs;if(void 0!==q){var r=a.triangles,s;for(s=0;s<r.length;s++)d(r[s])}}}}var e=[],f=a.materials;if(void 0===f)return e;var g=a.meshes;if(void 0===g)return e;var h=0;JSM.AsyncRunTask(function(){d(g[h],h);h+=1;return!0},c,g.length,0,e);return e};JSM.JSONFileConverter=function(a,b){this.onReady=a;this.onTextureLoaded=b};
JSM.JSONFileConverter.prototype.Convert=function(a){(new JSM.JSONFileLoader(this.OnReady.bind(this))).Load(a)};JSM.JSONFileConverter.prototype.OnReady=function(a){null!==this.onReady&&(a=JSM.ConvertJSONDataToThreeMeshes(a,this.onTextureLoaded),this.onReady(a))};JSM.ThreeViewer=function(){this.enableDraw=this.drawLoop=this.settings=this.navigation=this.cameraMove=this.runAfterRender=this.runBeforeRender=this.directionalLight=this.ambientLight=this.renderer=this.camera=this.scene=this.canvas=null};
JSM.ThreeViewer.prototype.Start=function(a,b){if(!this.IsWebGLEnabled()||!this.InitSettings(b)||!this.InitThree(a)||!this.InitCamera(b)||!this.InitLights())return!1;this.drawLoop=!1;this.enableDraw=!0;this.DrawIfNeeded();return!0};JSM.ThreeViewer.prototype.IsWebGLEnabled=function(){return!window.WebGLRenderingContext||!document.createElement("canvas").getContext("experimental-webgl")?!1:!0};
JSM.ThreeViewer.prototype.InitSettings=function(a){this.settings={cameraEyePosition:new JSM.Coord(1,1,1),cameraCenterPosition:new JSM.Coord(0,0,0),cameraUpVector:new JSM.Coord(0,0,1),lightAmbientColor:[0.5,0.5,0.5],lightDiffuseColor:[0.5,0.5,0.5]};void 0!==a&&(void 0!==a.cameraEyePosition&&(this.settings.cameraEyePosition=JSM.CoordFromArray(a.cameraEyePosition)),void 0!==a.cameraCenterPosition&&(this.settings.cameraCenterPosition=JSM.CoordFromArray(a.cameraCenterPosition)),void 0!==a.cameraUpVector&&
(this.settings.cameraUpVector=JSM.CoordFromArray(a.cameraUpVector)),void 0!==a.lightAmbientColor&&(this.settings.lightAmbientColor=a.lightAmbientColor),void 0!==a.lightDiffuseColor&&(this.settings.lightDiffuseColor=a.lightDiffuseColor));return!0};
JSM.ThreeViewer.prototype.InitThree=function(a){this.canvas=document.getElementById(a);if(!this.canvas||!this.canvas.getContext)return!1;this.scene=new THREE.Scene;if(!this.scene)return!1;this.renderer=new THREE.WebGLRenderer({canvas:this.canvas,antialias:!0});if(!this.renderer)return!1;this.renderer.setClearColor(new THREE.Color(16777215));this.renderer.setSize(this.canvas.width,this.canvas.height);return!0};
JSM.ThreeViewer.prototype.InitCamera=function(a){this.cameraMove=new JSM.Camera(JSM.CoordFromArray(a.cameraEyePosition),JSM.CoordFromArray(a.cameraCenterPosition),JSM.CoordFromArray(a.cameraUpVector),a.fieldOfView,a.nearClippingPlane,a.farClippingPlane);if(!this.cameraMove)return!1;this.navigation=new JSM.Navigation;if(!this.navigation.Init(this.canvas,this.cameraMove,this.DrawIfNeeded.bind(this),this.Resize.bind(this)))return!1;this.camera=new THREE.PerspectiveCamera(this.cameraMove.fieldOfView,
this.canvas.width/this.canvas.height,this.cameraMove.nearClippingPlane,this.cameraMove.farClippingPlane);if(!this.camera)return!1;this.scene.add(this.camera);return!0};
JSM.ThreeViewer.prototype.InitLights=function(){var a=new THREE.Color,b=new THREE.Color;a.setRGB(this.settings.lightAmbientColor[0],this.settings.lightAmbientColor[1],this.settings.lightAmbientColor[2]);b.setRGB(this.settings.lightDiffuseColor[0],this.settings.lightDiffuseColor[1],this.settings.lightDiffuseColor[2]);this.ambientLight=new THREE.AmbientLight(a.getHex());if(!this.ambientLight)return!1;this.scene.add(this.ambientLight);this.directionalLight=new THREE.DirectionalLight(b.getHex());if(!this.directionalLight)return!1;
a=(new THREE.Vector3).subVectors(this.cameraMove.eye,this.cameraMove.center);this.directionalLight.position.set(a.x,a.y,a.z);this.scene.add(this.directionalLight);return!0};JSM.ThreeViewer.prototype.SetRunBeforeRender=function(a){this.runBeforeRender=a};JSM.ThreeViewer.prototype.SetRunAfterRender=function(a){this.runAfterRender=a};JSM.ThreeViewer.prototype.SetClearColor=function(a){this.renderer.setClearColor(new THREE.Color(a));this.DrawIfNeeded()};
JSM.ThreeViewer.prototype.AddMesh=function(a){this.scene.add(a);this.DrawIfNeeded()};JSM.ThreeViewer.prototype.AddMeshes=function(a){var b;for(b=0;b<a.length;b++)this.scene.add(a[b]);this.DrawIfNeeded()};JSM.ThreeViewer.prototype.MeshCount=function(){var a=0;this.scene.traverse(function(b){b instanceof THREE.Mesh&&(a+=1)});return a};JSM.ThreeViewer.prototype.VertexCount=function(){var a=0;this.scene.traverse(function(b){b instanceof THREE.Mesh&&(a+=b.geometry.vertices.length)});return a};
JSM.ThreeViewer.prototype.FaceCount=function(){var a=0;this.scene.traverse(function(b){b instanceof THREE.Mesh&&(a+=b.geometry.faces.length)});return a};JSM.ThreeViewer.prototype.GetMesh=function(a){var b=null,c=0,d;for(d=0;d<this.scene.children.length;d++)if(b=this.scene.children[d],b instanceof THREE.Mesh){if(c==a)return b;c+=1}return null};JSM.ThreeViewer.prototype.RemoveMesh=function(a){this.scene.remove(a);this.DrawIfNeeded()};
JSM.ThreeViewer.prototype.RemoveMeshes=function(){var a,b;for(b=0;b<this.scene.children.length;b++)a=this.scene.children[b],a instanceof THREE.Mesh&&(this.scene.remove(a),b--);this.DrawIfNeeded()};JSM.ThreeViewer.prototype.RemoveLastMesh=function(){var a=null;this.scene.traverse(function(b){b instanceof THREE.Mesh&&(a=b)});null!==a&&this.scene.remove(a);this.DrawIfNeeded()};
JSM.ThreeViewer.prototype.SetCamera=function(a,b,c){this.navigation.SetCamera(a,b,c);this.navigation.SetOrbitCenter(b.Clone());this.DrawIfNeeded()};JSM.ThreeViewer.prototype.Resize=function(){this.camera.aspect=this.canvas.width/this.canvas.height;this.camera.updateProjectionMatrix();this.renderer.setSize(this.canvas.width,this.canvas.height);this.DrawIfNeeded()};
JSM.ThreeViewer.prototype.FitInWindow=function(){if(0!==this.MeshCount()){var a=this.GetCenter(),b=this.GetBoundingSphereRadius(a);this.navigation.FitInWindow(a,b);this.DrawIfNeeded()}};JSM.ThreeViewer.prototype.AdjustClippingPlanes=function(a){var b=this.GetCenter();this.GetBoundingSphereRadius(b)<a?(this.camera.near=0.1,this.camera.far=1E3):(this.camera.near=10,this.camera.far=1E6);this.camera.updateProjectionMatrix();this.Draw()};
JSM.ThreeViewer.prototype.GetCenter=function(){var a=this.GetBoundingBox();return JSM.MidCoord(a[0],a[1])};
JSM.ThreeViewer.prototype.GetBoundingBox=function(){var a=new JSM.Coord(JSM.Inf,JSM.Inf,JSM.Inf),b=new JSM.Coord(-JSM.Inf,-JSM.Inf,-JSM.Inf),c,d;this.scene.traverse(function(e){if(e instanceof THREE.Mesh){c=e.geometry;var f;for(f=0;f<c.vertices.length;f++)d=c.vertices[f].clone(),d.add(e.position),a.x=JSM.Minimum(a.x,d.x),a.y=JSM.Minimum(a.y,d.y),a.z=JSM.Minimum(a.z,d.z),b.x=JSM.Maximum(b.x,d.x),b.y=JSM.Maximum(b.y,d.y),b.z=JSM.Maximum(b.z,d.z)}});return[a,b]};
JSM.ThreeViewer.prototype.GetBoundingSphereRadius=function(a){if(void 0===a||null===a)a=this.GetCenter();var b=0,c,d,e;this.scene.traverse(function(f){if(f instanceof THREE.Mesh){c=f.geometry;var g;for(g=0;g<c.vertices.length;g++)d=c.vertices[g].clone(),d.add(f.position),e=JSM.CoordDistance(a,new JSM.Coord(d.x,d.y,d.z)),JSM.IsGreater(e,b)&&(b=e)}});return b};
JSM.ThreeViewer.prototype.GetObjectsUnderPosition=function(a,b){var c=2*(a/this.canvas.width)-1,d=2*-(b/this.canvas.height)+1,e=new THREE.Projector,f=this.camera.position,c=new THREE.Vector3(c,d,0.5);e.unprojectVector(c,this.camera);c.sub(f);c.normalize();return(new THREE.Raycaster(f,c)).intersectObjects(this.scene.children)};JSM.ThreeViewer.prototype.GetObjectsUnderMouse=function(){return this.GetObjectsUnderPosition(this.navigation.mouse.currX,this.navigation.mouse.currY)};
JSM.ThreeViewer.prototype.GetObjectsUnderTouch=function(){return this.GetObjectsUnderPosition(this.navigation.touch.currX,this.navigation.touch.currY)};JSM.ThreeViewer.prototype.ProjectVector=function(a,b,c){var d=this.canvas.width/2,e=this.canvas.height/2,f=new THREE.Projector;a=new THREE.Vector3(a,b,c);f.projectVector(a,this.camera);a.x=a.x*d+d;a.y=-(a.y*e)+e;return a};JSM.ThreeViewer.prototype.EnableDraw=function(a){this.enableDraw=a};
JSM.ThreeViewer.prototype.Draw=function(){if(this.enableDraw){null!==this.runBeforeRender&&this.runBeforeRender();this.camera.position.set(this.cameraMove.eye.x,this.cameraMove.eye.y,this.cameraMove.eye.z);this.camera.up.set(this.cameraMove.up.x,this.cameraMove.up.y,this.cameraMove.up.z);this.camera.lookAt(new THREE.Vector3(this.cameraMove.center.x,this.cameraMove.center.y,this.cameraMove.center.z));var a=(new THREE.Vector3).subVectors(this.cameraMove.eye,this.cameraMove.center);this.directionalLight.position.set(a.x,
a.y,a.z);this.renderer.render(this.scene,this.camera);null!==this.runAfterRender&&this.runAfterRender();this.drawLoop&&requestAnimationFrame(this.Draw.bind(this))}};JSM.ThreeViewer.prototype.DrawIfNeeded=function(){this.drawLoop||this.Draw()};JSM.ThreeViewer.prototype.StartDrawLoop=function(){this.drawLoop=!0;this.Draw()};

827
src/frameworks/three.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
src/images/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

BIN
src/images/bottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

BIN
src/images/closed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

BIN
src/images/fitinwindow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

BIN
src/images/fixup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

BIN
src/images/front.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

BIN
src/images/githublogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/images/hidden.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

BIN
src/images/info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

BIN
src/images/left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

BIN
src/images/opened.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

BIN
src/images/openfile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
src/images/right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

BIN
src/images/top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

BIN
src/images/visible.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

View File

@ -0,0 +1,39 @@
div.dialog
{
color : #222222;
background : #ffffff;
position : absolute;
top : 0px;
left : 0px;
box-shadow: 0px 0px 5px #000000;
}
div.dialogtitle
{
color : #ffffff;
background : linear-gradient(#333333, #111111) #222222;
padding : 10px;
overflow : auto;
}
div.dialogcontent
{
padding : 10px;
overflow : auto;
}
div.dialogbuttons
{
overflow : auto;
}
div.dialogbutton
{
color : #ffffff;
background : linear-gradient(#333333, #111111) #222222;
margin : 5px 5px 5px 0px;
padding : 5px 10px;
cursor : pointer;
border-radius : 3px;
float : right;
}

View File

@ -0,0 +1,91 @@
FloatingDialog = function ()
{
this.dialogDiv = null;
this.mouseClick = this.MouseClick.bind (this);
};
FloatingDialog.prototype.Open = function (parameters)
{
function AddButton (dialog, parent, button)
{
var buttonDiv = document.createElement ('div');
buttonDiv.className = 'dialogbutton';
buttonDiv.innerHTML = button.text;
buttonDiv.onclick = function () {
button.callback (dialog);
};
buttonsDiv.appendChild (buttonDiv);
}
if (this.dialogDiv !== null) {
this.dialogDiv.Close ();
}
this.dialogDiv = document.createElement ('div');
this.dialogDiv.className = 'dialog';
var titleDiv = document.createElement ('div');
titleDiv.className = 'dialogtitle';
titleDiv.innerHTML = parameters.title;
this.dialogDiv.appendChild (titleDiv);
var contentDiv = document.createElement ('div');
contentDiv.className = 'dialogcontent';
contentDiv.innerHTML = parameters.text;
this.dialogDiv.appendChild (contentDiv);
var buttonsDiv = document.createElement ('div');
buttonsDiv.className = 'dialogbuttons';
this.dialogDiv.appendChild (buttonsDiv);
var i, button;
for (i = 0; i < parameters.buttons.length; i++) {
button = parameters.buttons[i];
AddButton (this, buttonsDiv, button);
}
document.body.appendChild (this.dialogDiv);
document.addEventListener ('click', this.mouseClick, true);
this.Resize ();
};
FloatingDialog.prototype.Close = function ()
{
if (this.dialogDiv === null) {
return;
}
document.body.removeChild (this.dialogDiv);
document.removeEventListener ('click', this.mouseClick, true);
this.dialogDiv = null;
};
FloatingDialog.prototype.Resize = function ()
{
if (this.dialogDiv === null) {
return;
}
this.dialogDiv.style.left = ((document.body.clientWidth - this.dialogDiv.clientWidth) / 2.0) + 'px';
this.dialogDiv.style.top = ((document.body.clientHeight - this.dialogDiv.clientHeight) / 3.0) + 'px';
};
FloatingDialog.prototype.MouseClick = function (clickEvent)
{
if (this.dialogDiv === null) {
return;
}
var dialogClicked = false;
var target = clickEvent.target;
while (target !== null) {
if (target === this.dialogDiv) {
dialogClicked = true;
}
target = target.parentElement;
}
if (!dialogClicked) {
this.Close ();
}
};

167
src/include/importer.css Normal file
View File

@ -0,0 +1,167 @@
html, body
{
color : #222222;
background : #dddddd;
font-size : 12px;
font-family : Arial, cursive;
margin : 0px;
padding : 0px;
width : 100%;
height : 100%;
}
#top
{
color : #dddddd;
background : linear-gradient(#333333, #111111) #222222;
overflow : auto;
}
#logo
{
color : #ffffff;
background : linear-gradient(#0095c6, #006d91) #008ab8;
font-size : 14px;
text-align : center;
text-decoration : none;
width : 240px;
padding : 5px 0px;
margin : 8px;
border-radius : 5px;
box-shadow: 0px 0px 5px #000000;
cursor : pointer;
float : left;
}
span.version
{
margin-left : 5px;
font-size : 10px;
}
img.topbutton
{
width : 25px;
height : 25px;
margin : 9px 5px 0px 5px;
border : 0px;
cursor : pointer;
}
#left
{
color : #222222;
background : #cccccc;
width : 250px;
float : left;
overflow : auto;
}
#menu
{
margin : 5px;
}
div.menuitem
{
padding : 2px;
overflow : auto;
}
div.menugroup
{
margin-left : 15px;
}
div.menutext
{
padding : 2px;
margin-left : 3px;
float : left;
}
img.menubutton
{
padding : 2px;
float : left;
cursor : pointer;
border : 0px;
display : block;
}
div.colorbutton
{
width : 14px;
height : 14px;
border : 1px solid #222222;
float : left;
}
div.progressbarborder
{
height : 20px;
border : 1px solid #222222;
}
div.progressbarcontent
{
color : #ffffff;
background : #279b61;
height : 20px;
}
table.infotable td
{
padding : 1px 5px;
}
div.importerdialog
{
width : 450px;
}
div.welcometitle
{
font-size : 19px;
text-align : center;
margin : 20px 0px;
}
div.welcometext
{
text-align : center;
margin : 20px 0px;
}
div.welcometextformats
{
text-align : center;
margin : 30px 0px;
}
span.welcomeformat
{
color : #222222;
background : #eeeeee;
margin : 3px;
padding : 5px 15px;
border : 1px solid #dddddd;
border-radius : 5px;
}
canvas
{
display : block;
}
a
{
color : #225588;
background : transparent;
text-decoration : none;
}
a:hover
{
text-decoration : underline;
}

404
src/include/importerapp.js Normal file
View File

@ -0,0 +1,404 @@
ImporterApp = function ()
{
this.viewer = null;
this.fileNames = null;
this.inGenerate = false;
this.dialog = null;
};
ImporterApp.prototype.Init = function ()
{
var myThis = this;
var top = document.getElementById ('top');
var importerButtons = new ImporterButtons (top);
importerButtons.AddLogo ('Online 3D Viewer <span class="version">0.1</span>', function () { myThis.WelcomeDialog (); });
importerButtons.AddButton ('images/openfile.png', 'Open File', function () { myThis.OpenFile (); });
importerButtons.AddButton ('images/fitinwindow.png', 'Fit In Window', function () { myThis.FitInWindow (); });
importerButtons.AddButton ('images/fixup.png', 'Enable/Disable Fixed Up Vector', function () { myThis.SetFixUp (); });
importerButtons.AddButton ('images/top.png', 'Set Up Vector (Z)', function () { myThis.SetNamedView ('z'); });
importerButtons.AddButton ('images/bottom.png', 'Set Up Vector (-Z)', function () { myThis.SetNamedView ('-z'); });
importerButtons.AddButton ('images/front.png', 'Set Up Vector (Y)', function () { myThis.SetNamedView ('y'); });
importerButtons.AddButton ('images/back.png', 'Set Up Vector (-Y)', function () { myThis.SetNamedView ('-y'); });
importerButtons.AddButton ('images/left.png', 'Set Up Vector (X)', function () { myThis.SetNamedView ('x'); });
importerButtons.AddButton ('images/right.png', 'Set Up Vector (-X)', function () { myThis.SetNamedView ('-x'); });
this.dialog = new FloatingDialog ();
window.addEventListener ('resize', this.Resize.bind (this), false);
this.Resize ();
this.viewer = new ImporterViewer ();
this.viewer.Init ('example');
window.addEventListener ('dragover', this.DragOver.bind (this), false);
window.addEventListener ('drop', this.Drop.bind (this), false);
var fileInput = document.getElementById ('file');
fileInput.addEventListener ('change', this.FileSelected.bind (this), false);
this.WelcomeDialog ();
};
ImporterApp.prototype.WelcomeDialog = function ()
{
var dialogText = [
'<div class="importerdialog">',
'<div class="welcometitle">Welcome to Online 3D Viewer!</div>',
'<div class="welcometext">Here you can view 3D models online. Just simply drag and drop 3D files to this browser window or use the open button above. The supported file formats are:</div>',
'<div class="welcometextformats"><span class="welcomeformat">3ds</span><span class="welcomeformat">obj</span><span class="welcomeformat">stl</span></div>',
'<div class="welcometext">Powered by <a target="_blank" href="https://github.com/mrdoob/three.js/">Three.js</a> and <a target="_blank" href="https://github.com/kovacsv/JSModeler">JSModeler</a>.</div>',
'<div class="welcometext"><a target="_blank" href="https://github.com/kovacsv/JSModeler"><img src="images/githublogo.png"/></a></div>',
'</div>',
].join ('');
this.dialog.Open ({
title : 'Welcome',
text : dialogText,
buttons : [
{
text : 'ok',
callback : function (dialog) {
dialog.Close ();
}
}
]
});
};
ImporterApp.prototype.Resize = function ()
{
function SetWidth (elem, value)
{
elem.width = value;
elem.style.width = value + 'px';
}
function SetHeight (elem, value)
{
elem.height = value;
elem.style.height = value + 'px';
}
var top = document.getElementById ('top');
var left = document.getElementById ('left');
var canvas = document.getElementById ('example');
var height = document.body.clientHeight - top.offsetHeight;
SetHeight (canvas, 0);
SetWidth (canvas, 0);
SetHeight (left, height);
SetHeight (canvas, height);
SetWidth (canvas, document.body.clientWidth - left.offsetWidth);
this.dialog.Resize ();
};
ImporterApp.prototype.JsonLoaded = function (progressBar)
{
var jsonData = this.viewer.GetJsonData ();
this.meshVisibility = {};
var i;
for (i = 0; i < jsonData.meshes.length; i++) {
this.meshVisibility[i] = true;
}
this.Generate (progressBar);
};
ImporterApp.prototype.GenerateMenu = function ()
{
function AddDefaultGroup (menu, name)
{
var group = menu.AddGroup (name, {
openCloseButton : {
visible : false,
open : 'images/opened.png',
close : 'images/closed.png',
title : 'Show/Hide ' + name
}
});
return group;
}
function AddMaterial (importerMenu, material)
{
importerMenu.AddSubItem (materialsGroup, material.name, {
openCloseButton : {
visible : false,
open : 'images/info.png',
close : 'images/info.png',
onOpen : function (content, material) {
var table = new InfoTable (content);
table.AddColorRow ('Ambient', material.ambient);
table.AddColorRow ('Diffuse', material.diffuse);
table.AddColorRow ('Specular', material.specular);
table.AddRow ('Opacity', material.opacity.toFixed (2));
},
title : 'Show/Hide Information',
userData : material
}
});
}
function AddMesh (importerApp, importerMenu, mesh, meshIndex)
{
importerMenu.AddSubItem (meshesGroup, mesh.name, {
openCloseButton : {
visible : false,
open : 'images/info.png',
close : 'images/info.png',
onOpen : function (content, mesh) {
var table = new InfoTable (content);
var min = new JSM.Coord (JSM.Inf, JSM.Inf, JSM.Inf);
var max = new JSM.Coord (-JSM.Inf, -JSM.Inf, -JSM.Inf);
var i, vertex;
for (i = 0; i < mesh.vertices.length; i = i + 3) {
vertex = new JSM.Coord (mesh.vertices[i], mesh.vertices[i + 1], mesh.vertices[i + 2]);
min.x = JSM.Minimum (min.x, vertex.x);
min.y = JSM.Minimum (min.y, vertex.y);
min.z = JSM.Minimum (min.z, vertex.z);
max.x = JSM.Maximum (max.x, vertex.x);
max.y = JSM.Maximum (max.y, vertex.y);
max.z = JSM.Maximum (max.z, vertex.z);
}
table.AddRow ('X Size', (max.x - min.x).toFixed (2));
table.AddRow ('Y Size', (max.y - min.y).toFixed (2));
table.AddRow ('Z Size', (max.z - min.z).toFixed (2));
var triangleCount = 0;
var triangles;
for (i = 0; i < mesh.triangles.length; i++) {
triangles = mesh.triangles[i];
triangleCount += triangles.parameters.length / 9;
}
table.AddRow ('Vertex count', mesh.vertices.length / 3);
table.AddRow ('Triangle count', triangleCount);
},
title : 'Show/Hide Information',
userData : mesh
},
userButton : {
visible : true,
onCreate : function (image) {
image.src = 'images/visible.png';
},
onClick : function (image, meshIndex) {
var visible = importerApp.ShowHideMesh (meshIndex);
image.src = visible ? 'images/visible.png' : 'images/hidden.png';
},
title : 'Show/Hide Mesh',
userData : meshIndex
}
});
}
var jsonData = this.viewer.GetJsonData ();
var menu = document.getElementById ('menu');
var importerMenu = new ImporterMenu (menu);
var filesGroup = AddDefaultGroup (importerMenu, 'Files');
importerMenu.AddSubItem (filesGroup, this.fileNames.main);
var i;
for (i = 0; i < this.fileNames.requested.length; i++) {
importerMenu.AddSubItem (filesGroup, this.fileNames.requested[i]);
}
if (this.fileNames.missing.length > 0) {
var missingFilesGroup = AddDefaultGroup (importerMenu, 'Missing Files');
for (i = 0; i < this.fileNames.missing.length; i++) {
importerMenu.AddSubItem (missingFilesGroup, this.fileNames.missing[i]);
}
}
var materialsGroup = AddDefaultGroup (importerMenu, 'Materials');
var material;
for (i = 0; i < jsonData.materials.length; i++) {
material = jsonData.materials[i];
AddMaterial (importerMenu, material);
}
var meshesGroup = AddDefaultGroup (importerMenu, 'Meshes');
var mesh;
for (i = 0; i < jsonData.meshes.length; i++) {
mesh = jsonData.meshes[i];
AddMesh (this, importerMenu, mesh, i);
}
};
ImporterApp.prototype.GenerateError = function (errorMessage)
{
this.viewer.RemoveMeshes ();
var menu = document.getElementById ('menu');
while (menu.lastChild) {
menu.removeChild (menu.lastChild);
}
this.dialog.Open ({
title : 'Error',
text : '<div class="importerdialog">' + errorMessage + '</div>',
buttons : [
{
text : 'ok',
callback : function (dialog) {
dialog.Close ();
}
}
]
});
};
ImporterApp.prototype.Generate = function (progressBar)
{
function ShowMeshes (importerApp, progressBar, merge)
{
importerApp.inGenerate = true;
var environment = new JSM.AsyncEnvironment ({
onStart : function (taskCount) {
progressBar.Init (taskCount);
},
onProcess : function (currentTask) {
progressBar.Step (currentTask + 1);
},
onFinish : function () {
importerApp.GenerateMenu ();
importerApp.inGenerate = false;
}
});
if (merge) {
var jsonData = importerApp.viewer.GetJsonData ();
importerApp.viewer.SetJsonData (JSM.MergeJsonDataMeshes (jsonData));
}
importerApp.viewer.ShowAllMeshes (environment);
}
var jsonData = this.viewer.GetJsonData ();
if (jsonData.materials.length === 0 || jsonData.meshes.length === 0) {
this.GenerateError ('Failed to open file. Maybe something is wrong with your file.');
return;
}
var myThis = this;
if (jsonData.meshes.length > 250) {
this.dialog.Open ({
title : 'Information',
text : '<div class="importerdialog">The model contains a large number of meshes. It can cause performance problems. Would you like to merge meshes?</div>',
buttons : [
{
text : 'yes',
callback : function (dialog) {
ShowMeshes (myThis, progressBar, true);
dialog.Close ();
}
},
{
text : 'no',
callback : function (dialog) {
ShowMeshes (myThis, progressBar, false);
dialog.Close ();
}
}
]
});
} else {
ShowMeshes (myThis, progressBar, false);
}
};
ImporterApp.prototype.FitInWindow = function ()
{
this.viewer.FitInWindow ();
};
ImporterApp.prototype.SetFixUp = function ()
{
this.viewer.SetFixUp ();
};
ImporterApp.prototype.SetNamedView = function (viewName)
{
this.viewer.SetNamedView (viewName);
};
ImporterApp.prototype.SetView = function (viewType)
{
this.viewer.SetView (viewType);
};
ImporterApp.prototype.ShowHideMesh = function (meshIndex)
{
this.meshVisibility[meshIndex] = !this.meshVisibility[meshIndex];
if (this.meshVisibility[meshIndex]) {
this.viewer.ShowMesh (meshIndex);
} else {
this.viewer.HideMesh (meshIndex);
}
return this.meshVisibility[meshIndex];
};
ImporterApp.prototype.ProcessFiles = function (fileList)
{
this.dialog.Close ();
if (this.inGenerate) {
return;
}
var userFiles = fileList;
if (userFiles.length === 0) {
return;
}
this.fileNames = null;
var myThis = this;
JSM.ConvertFileListToJsonData (userFiles, {
onError : function () {
myThis.GenerateError ('No readable file found. You can open 3ds, obj and stl files.');
return;
},
onReady : function (fileNames, jsonData) {
myThis.fileNames = fileNames;
myThis.viewer.SetJsonData (jsonData);
var menu = document.getElementById ('menu');
var progressBar = new ImporterProgressBar (menu);
myThis.JsonLoaded (progressBar);
}
});
};
ImporterApp.prototype.DragOver = function (event)
{
event.stopPropagation ();
event.preventDefault ();
event.dataTransfer.dropEffect = 'copy';
};
ImporterApp.prototype.Drop = function (event)
{
event.stopPropagation ();
event.preventDefault ();
this.ProcessFiles (event.dataTransfer.files);
};
ImporterApp.prototype.FileSelected = function (event)
{
event.stopPropagation ();
event.preventDefault ();
this.ProcessFiles (event.target.files);
};
ImporterApp.prototype.OpenFile = function ()
{
var fileInput = document.getElementById('file');
fileInput.click ();
};
window.onload = function ()
{
var importerApp = new ImporterApp ();
importerApp.Init ();
};

210
src/include/importermenu.js Normal file
View File

@ -0,0 +1,210 @@
InfoTable = function (parent)
{
this.table = document.createElement ('table');
this.table.className = 'infotable';
while (parent.lastChild) {
parent.removeChild (parent.lastChild);
}
parent.appendChild (this.table);
};
InfoTable.prototype.AddRow = function (name, value)
{
var tableRow = document.createElement ('tr');
var nameColumn = document.createElement ('td');
nameColumn.innerHTML = name;
tableRow.appendChild (nameColumn);
var valueColumn = document.createElement ('td');
valueColumn.innerHTML = value;
tableRow.appendChild (valueColumn);
this.table.appendChild (tableRow);
};
InfoTable.prototype.AddColorRow = function (name, color)
{
var tableRow = document.createElement ('tr');
var nameColumn = document.createElement ('td');
nameColumn.innerHTML = name;
tableRow.appendChild (nameColumn);
var valueColumn = document.createElement ('td');
tableRow.appendChild (valueColumn);
var colorDiv = document.createElement ('div');
colorDiv.className = 'colorbutton';
colorDiv.title = '(' + color[0] + ', ' + color[1] + ', ' + color[2] + ')';
var hexColor = JSM.RGBComponentsToHexColor (color[0] * 255.0, color[1] * 255.0, color[2] * 255.0);
var colorString = hexColor.toString (16);
while (colorString.length < 6) {
colorString = '0' + colorString;
}
colorDiv.style.background = '#' + colorString;
valueColumn.appendChild (colorDiv);
this.table.appendChild (tableRow);
};
ImporterMenu = function (parent)
{
this.parent = parent;
while (this.parent.lastChild) {
this.parent.removeChild (this.parent.lastChild);
}
};
ImporterMenu.prototype.AddGroup = function (name, parameters)
{
return this.AddSubItem (this.parent, name, parameters);
};
ImporterMenu.prototype.AddSubItem = function (parent, name, parameters)
{
function GetTruncatedName (name)
{
var maxLength = 20;
if (name.length > maxLength) {
return name.substr (0, maxLength) + '...';
}
return name;
}
var menuItem = document.createElement ('div');
menuItem.className = 'menuitem';
var menuText = null;
menuText = document.createElement ('div');
menuText.className = 'menuitem';
menuText.innerHTML = GetTruncatedName (name);
menuText.title = name;
var menuContent = null;
var openCloseImage = null;
var userImage = null;
if (parameters !== undefined && parameters !== null) {
if (parameters.openCloseButton !== undefined && parameters.openCloseButton !== null) {
menuContent = document.createElement ('div');
menuContent.className = 'menugroup';
menuContent.style.display = parameters.openCloseButton.visible ? 'block' : 'none';
openCloseImage = document.createElement ('img');
openCloseImage.className = 'menubutton';
openCloseImage.title = parameters.openCloseButton.title;
openCloseImage.src = parameters.openCloseButton.visible ? parameters.openCloseButton.open : parameters.openCloseButton.close;
openCloseImage.onclick = function () {
if (menuContent.style.display == 'none') {
menuContent.style.display = 'block';
openCloseImage.src = parameters.openCloseButton.open;
if (parameters.openCloseButton.onOpen !== undefined && parameters.openCloseButton.onOpen !== null) {
parameters.openCloseButton.onOpen (menuContent, parameters.openCloseButton.userData);
}
} else {
menuContent.style.display = 'none';
openCloseImage.src = parameters.openCloseButton.close;
if (parameters.openCloseButton.onClose !== undefined && parameters.openCloseButton.onClose !== null) {
parameters.openCloseButton.onClose (menuContent, parameters.openCloseButton.userData);
}
}
};
menuText.onclick = openCloseImage.onclick;
menuText.style.cursor = 'pointer';
}
if (parameters.userButton !== undefined && parameters.userButton !== null) {
userImage = document.createElement ('img');
userImage.className = 'menubutton';
userImage.title = parameters.userButton.title;
if (parameters.userButton.onCreate !== undefined && parameters.userButton.onCreate !== null) {
parameters.userButton.onCreate (userImage, parameters.userButton.userData);
}
userImage.onclick = function () {
if (parameters.userButton.onClick !== undefined && parameters.userButton.onClick !== null) {
parameters.userButton.onClick (userImage, parameters.userButton.userData);
}
};
}
}
if (openCloseImage !== null) {
menuItem.appendChild (openCloseImage);
}
if (userImage !== null) {
menuItem.appendChild (userImage);
}
menuItem.appendChild (menuText);
parent.appendChild (menuItem);
if (menuContent !== null) {
parent.appendChild (menuContent);
}
return menuContent;
};
ImporterButtons = function (parent)
{
this.parent = parent;
};
ImporterButtons.prototype.AddLogo = function (title, onClick)
{
var logoDiv = document.createElement ('div');
logoDiv.id = 'logo';
logoDiv.innerHTML = title;
logoDiv.onclick = onClick;
this.parent.appendChild (logoDiv);
};
ImporterButtons.prototype.AddButton = function (image, title, onClick)
{
var buttonImage = document.createElement ('img');
buttonImage.className = 'topbutton';
buttonImage.src = image;
buttonImage.title = title;
buttonImage.onclick = onClick;
this.parent.appendChild (buttonImage);
};
ImporterProgressBar = function (parent)
{
this.parent = parent;
while (this.parent.lastChild) {
this.parent.removeChild (this.parent.lastChild);
}
this.borderDiv = null;
this.contentDiv = null;
this.maxCount = null;
this.maxWidth = null;
};
ImporterProgressBar.prototype.Init = function (maxCount)
{
this.borderDiv = document.createElement ('div');
this.borderDiv.className = 'progressbarborder';
this.contentDiv = document.createElement ('div');
this.contentDiv.className = 'progressbarcontent';
this.borderDiv.appendChild (this.contentDiv);
this.parent.appendChild (this.borderDiv);
this.maxCount = maxCount;
this.maxWidth = this.borderDiv.offsetWidth;
this.Step (0);
};
ImporterProgressBar.prototype.Step = function (count)
{
var step = this.maxWidth / this.maxCount;
var width = count * step;
if (count == this.maxCount) {
width = this.maxWidth - 2;
}
this.contentDiv.style.width = width + 'px';
};

View File

@ -0,0 +1,163 @@
ImporterViewer = function ()
{
this.viewer = null;
this.jsonData = null;
};
ImporterViewer.prototype.Init = function (canvasName)
{
var viewerSettings = {
cameraEyePosition : [8.0, -6.0, 4.0],
cameraCenterPosition : [0.0, 0.0, 0.0],
cameraUpVector : [0, 0, 1]
};
this.viewer = new JSM.ThreeViewer ();
if (!this.viewer.Start (canvasName, viewerSettings)) {
return false;
}
this.viewer.SetClearColor (0xdddddd);
this.viewer.Draw ();
return true;
};
ImporterViewer.prototype.GetJsonData = function ()
{
return this.jsonData;
};
ImporterViewer.prototype.SetJsonData = function (jsonData)
{
this.jsonData = jsonData;
};
ImporterViewer.prototype.RemoveMeshes = function ()
{
this.viewer.RemoveMeshes ();
};
ImporterViewer.prototype.ShowAllMeshes = function (inEnvironment)
{
this.RemoveMeshes ();
var myThis = this;
var currentMeshIndex = 0;
var environment = new JSM.AsyncEnvironment ({
onStart : function (taskCount/*, meshes*/) {
inEnvironment.OnStart (taskCount);
myThis.viewer.EnableDraw (false);
},
onProcess : function (currentTask, meshes) {
while (currentMeshIndex < meshes.length) {
myThis.viewer.AddMesh (meshes[currentMeshIndex]);
currentMeshIndex = currentMeshIndex + 1;
}
inEnvironment.OnProcess (currentTask);
},
onFinish : function (meshes) {
myThis.AdjustClippingPlanes (50.0);
myThis.FitInWindow ();
myThis.viewer.EnableDraw (true);
myThis.viewer.Draw ();
inEnvironment.OnFinish (meshes);
}
});
JSM.ConvertJSONDataToThreeMeshes (this.jsonData, null, environment);
};
ImporterViewer.prototype.ShowMesh = function (index)
{
var i, mesh;
var workJsonData = {
version : this.jsonData.version,
materials : this.jsonData.materials,
meshes : [this.jsonData.meshes[index]]
};
var meshes = JSM.ConvertJSONDataToThreeMeshes (workJsonData);
for (i = 0; i < meshes.length; i++) {
mesh = meshes[i];
mesh.originalJsonIndex = index;
this.viewer.AddMesh (mesh);
}
this.viewer.Draw ();
};
ImporterViewer.prototype.HideMesh = function (index)
{
var meshesToRemove = [];
var currentIndex = 0;
this.viewer.scene.traverse (function (current) {
if (current instanceof THREE.Mesh) {
if (current.originalJsonIndex == index) {
meshesToRemove.push (current);
}
currentIndex = currentIndex + 1;
}
});
var i, mesh;
for (i = 0; i < meshesToRemove.length; i++) {
mesh = meshesToRemove[i];
this.viewer.scene.remove (mesh);
}
this.viewer.Draw ();
};
ImporterViewer.prototype.FitInWindow = function ()
{
if (this.viewer.MeshCount () > 0) {
this.viewer.FitInWindow ();
}
};
ImporterViewer.prototype.AdjustClippingPlanes = function ()
{
if (this.viewer.MeshCount () > 0) {
this.viewer.AdjustClippingPlanes (50.0);
}
};
ImporterViewer.prototype.SetFixUp = function ()
{
this.viewer.navigation.EnableFixUp (!this.viewer.navigation.cameraFixUp);
};
ImporterViewer.prototype.SetNamedView = function (viewName)
{
var eye, center, up;
if (viewName == 'z') {
eye = new JSM.Coord (1.0, 0.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (0.0, 0.0, 1.0);
} else if (viewName == '-z') {
eye = new JSM.Coord (-1.0, 0.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (0.0, 0.0, -1.0);
} else if (viewName == 'y') {
eye = new JSM.Coord (1.0, 0.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (0.0, 1.0, 0.0);
} else if (viewName == '-y') {
eye = new JSM.Coord (-1.0, 0.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (0.0, -1.0, 0.0);
} else if (viewName == 'x') {
eye = new JSM.Coord (0.0, 1.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (1.0, 0.0, 0.0);
} else if (viewName == '-x') {
eye = new JSM.Coord (0.0, -1.0, 0.0);
center = new JSM.Coord (0.0, 0.0, 0.0);
up = new JSM.Coord (-1.0, 0.0, 0.0);
} else {
return;
}
this.viewer.cameraMove.Set (eye, center, up);
this.viewer.FitInWindow ();
};

34
src/index.html Normal file
View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script type="text/javascript" src="../../build/three.min.js"></script>
<link rel="stylesheet" type="text/css" href="include/importer.css">
<link rel="stylesheet" type="text/css" href="include/floatingdialog.css">
<script type="text/javascript" src="frameworks/three.min.js"></script>
<script type="text/javascript" src="frameworks/jsmodeler.js"></script>
<script type="text/javascript" src="include/floatingdialog.js"></script>
<script type="text/javascript" src="include/importerviewer.js"></script>
<script type="text/javascript" src="include/importermenu.js"></script>
<script type="text/javascript" src="include/importerapp.js"></script>
<title>Model Viewer</title>
</head>
<body>
<div id="top">
</div>
<div id="left">
<div id="menu"></div>
</div>
<canvas id="example" width="0" height="0"></canvas>
<input type="file" id="file" style="display:none" multiple></input>
</body>
</html>

34
tools/jshint.py Normal file
View File

@ -0,0 +1,34 @@
import os
import sys
import re
currentPath = os.path.dirname (os.path.abspath (__file__))
os.chdir (currentPath)
configFilePath = 'jshintconfig.json'
sourcesFolderName = '../src/include'
def PrintInfo (message):
print ('Info: ' + message)
def PrintError (error):
print ('Error: ' + error)
def JSHintFolder (folderPath):
result = os.system ('jshint --config ' + configFilePath + ' ' + folderPath)
if result != 0:
return False
return True
def Main ():
sourcesPath = os.path.abspath (sourcesFolderName)
PrintInfo ('JSHint folder <' + sourcesPath + '>.')
succeeded = JSHintFolder (sourcesPath)
if not succeeded:
PrintError ('Found JSHint errors.');
return 1
return 0
sys.exit (Main ())

12
tools/jshintconfig.json Normal file
View File

@ -0,0 +1,12 @@
{
"globals" : {
"JSM" : true,
"ImporterApp" :true,
"ImporterMenu" : true,
"ImporterViewer" : true,
"ImporterButtons" : true,
"ImporterProgressBar" : true,
"InfoTable" : true,
"THREE" : false
}
}