var DEBUG={};if(typeof K3D=="undefined"||!K3D){var K3D={}}(function(){K3D.BaseController=function(){this.objects=[];this.lights=[];this.renderers=[];this.renderers.point=new K3D.PointRenderer();this.renderers.wireframe=new K3D.WireframeRenderer();this.renderers.solid=new K3D.SolidRenderer()};K3D.BaseController.prototype={renderers:null,objects:null,lights:null,sort:true,addK3DObject:function(a){a.setController(this);this.objects.push(a)},addLightSource:function(a){this.lights.push(a)},getRenderer:function(a){return this.renderers[a]},processTick:function(c){var g=this.objects;for(var f=0,a=g.length;f<a;f++){g[f].executePipeline()}var e=this.lights;for(var f=0,a=e.length;f<a;f++){e[f].executePipeline()}if(this.sort){g.forEach(function b(k,j,h){k.averagez=null});g.sort(function d(i,h){if(i.averagez===null){i.calculateAverageZ()}if(h.averagez===null){h.calculateAverageZ()}return(i.averagez<h.averagez?1:-1)})}for(var f=0,a=g.length;f<a;f++){c.save();g[f].executeRenderer(c);c.restore()}}}})();(function(){K3D.Controller=function(b,a){K3D.Controller.superclass.constructor.call(this);this.canvas=b;var c=this;if(!a){b.onclick=function(d){c.paused=!c.paused;if(!c.paused){c.tick()}}}};extend(K3D.Controller,K3D.BaseController,{canvas:null,clearBackground:true,fillStyle:null,paused:true,callback:null,fps:40,lastFrameStart:0,addK3DObject:function(a){a.setController(this,this.canvas.width,this.canvas.height);this.objects.push(a)},tick:function(){var f=new Date().getTime();if(this.callback){this.callback.call(this)}var a=this.canvas.getContext("2d");if(this.clearBackground){if(this.fillStyle!==null){a.fillStyle=this.fillStyle;a.fillRect(0,0,this.canvas.width,this.canvas.height)}else{a.clearRect(0,0,this.canvas.width,this.canvas.height)}}this.processTick(a);var b=1000/this.fps;var e=(new Date().getTime()-f);if(!this.paused){var d=this;setTimeout(function(){d.tick()},b-e<=0?1:b-e)}if(DEBUG&&DEBUG.FPS){a.fillStyle="grey";a.fillText("TPF: "+e,4,48);var c=Math.round(1000/(f-this.lastFrameStart));a.fillText("FPS: "+c,4,64)}this.lastFrameStart=f}})})();(function(){K3D.BaseObject=function(){this.matrix=new Array(3);for(var a=0;a<3;a++){this.matrix[a]=new Array(3)}this.angles=new Array(6);return this};K3D.BaseObject.prototype={matrix:null,angles:null,offx:0,offy:0,offz:0,aboutx:0,abouty:0,aboutz:0,ogamma:0,otheta:0,ophi:0,addgamma:0,addtheta:0,addphi:0,velx:0,vely:0,velz:0,bminx:0,bminy:0,bminz:0,bmaxx:0,bmaxy:0,bmaxz:0,doublesided:false,calcMatrix:function(){var b=this.angles,a=this.matrix;b[0]=Math.sin(this.ogamma*RAD);b[1]=Math.cos(this.ogamma*RAD);b[2]=Math.sin(this.otheta*RAD);b[3]=Math.cos(this.otheta*RAD);b[4]=Math.sin(this.ophi*RAD);b[5]=Math.cos(this.ophi*RAD);a[0][0]=b[5]*b[1];a[1][0]=-(b[5]*b[0]);a[2][0]=b[4];a[0][1]=(b[2]*b[4]*b[1])+(b[3]*b[0]);a[1][1]=(b[3]*b[1])-(b[2]*b[4]*b[0]);a[2][1]=-(b[2]*b[5]);a[0][2]=(b[2]*b[0])-(b[3]*b[4]*b[1]);a[1][2]=(b[2]*b[1])+(b[3]*b[4]*b[0]);a[2][2]=b[3]*b[5]},transformToWorld:function(){},executePipeline:function(){this.ogamma+=this.addgamma;this.otheta+=this.addtheta;this.ophi+=this.addphi;this.offx+=this.velx;this.offy+=this.vely;this.offz+=this.velz;if(this.offx<this.bminx||this.offx>this.bmaxx){this.velx*=-1}if(this.offy<this.bminy||this.offy>this.bmaxy){this.vely*=-1}if(this.offz<this.bminz||this.offz>this.bmaxz){this.velz*=-1}this.calcMatrix();this.transformToWorld()}}})();(function(){K3D.K3DObject=function(){K3D.K3DObject.superclass.constructor.call(this);this.textures=[];return this};extend(K3D.K3DObject,K3D.BaseObject,{controller:null,worldcoords:null,screenx:0,screeny:0,depthscale:0,linescale:2,color:null,drawmode:"point",shademode:"depthcue",sortmode:"sorted",fillstroke:true,perslevel:512,scale:0,recalculateNormals:false,points:null,edges:null,faces:null,screencoords:null,averagez:null,textures:null,depthcueColors:null,init:function(v,l,f){this.points=v;this.edges=l;this.faces=f;this.worldcoords=new Array(v.length+f.length);for(var n=0,k=this.worldcoords.length;n<k;n++){this.worldcoords[n]={x:0,y:0,z:0}}this.screencoords=new Array(v.length);for(var n=0,k=this.screencoords.length;n<k;n++){this.screencoords[n]={x:0,y:0}}if(this.scale!==0){for(var n=0,k=this.points.length;n<k;n++){v[n].x*=this.scale;v[n].y*=this.scale;v[n].z*=this.scale}}if(this.color===null){this.color=[255,255,255]}this.depthcueColors=new Array(256);for(var q=0,a,o,t;q<256;q++){a=this.color[0]*(q/255);o=this.color[1]*(q/255);t=this.color[2]*(q/255);this.depthcueColors[q]="rgb("+Math.ceil(a)+","+Math.ceil(o)+","+Math.ceil(t)+")"}for(var n=0,k=f.length;n<k;n++){var p=f[n].vertices;var e=v[p[1]].x-v[p[0]].x;var u=v[p[1]].y-v[p[0]].y;var m=v[p[1]].z-v[p[0]].z;var d=v[p[2]].x-v[p[0]].x;var s=v[p[2]].y-v[p[0]].y;var h=v[p[2]].z-v[p[0]].z;f[n].normal=calcNormalVector(e,u,m,d,s,h);if(!f[n].color){f[n].color=this.color}if(f[n].texture===undefined){f[n].texture=null}}},setController:function(a,b,c){this.controller=a;if(b){this.screenx=b/2;this.screeny=c/2;this.depthscale=this.screenx;this.bminx=-this.screenx;this.bminy=-this.screeny;this.bminz=-this.screenx;this.bmaxx=this.screenx;this.bmaxy=this.screeny;this.bmaxz=this.screenx}},transformToWorld:function(){var k,h,f;var p=this.points,e=this.worldcoords,b=this.faces,n=this.matrix;var l=this.aboutx,j=this.abouty,g=this.aboutz,d=this.offx,c=this.offy,a=this.offz;var r=n[0],o=n[1],m=n[2];for(var q=0,s=p.length;q<s;q++){k=p[q].x+l;h=p[q].y+j;f=p[q].z+g;e[q].x=(r[0]*k)+(r[1]*h)+(r[2]*f)+d;e[q].y=(o[0]*k)+(o[1]*h)+(o[2]*f)+c;e[q].z=(m[0]*k)+(m[1]*h)+(m[2]*f)+a}for(var q=0,s=b.length,t;q<s;q++){t=b[q].normal;k=t.x;h=t.y;f=t.z;b[q].worldnormal=new Vector3D((r[0]*k)+(r[1]*h)+(r[2]*f)+d,(o[0]*k)+(o[1]*h)+(o[2]*f)+c,(m[0]*k)+(m[1]*h)+(m[2]*f)+a)}},transformToScreen:function(){var h,f,e;var a=this.worldcoords,g=this.screencoords;var k=this.screenx,j=this.screeny,d=this.perslevel;for(var b=0,c=this.points.length;b<c;b++){h=a[b].x;f=a[b].y;e=a[b].z+d;if(e===0){e=1}g[b].x=((h*d)/e)+k;g[b].y=j-((f*d)/e)}},executePipeline:function(){if(this.recalculateNormals){var c=this.faces,m=this.points;for(var g=0,e=c.length;g<e;g++){var h=c[g].vertices;var b=m[h[1]].x-m[h[0]].x;var l=m[h[1]].y-m[h[0]].y;var f=m[h[1]].z-m[h[0]].z;var a=m[h[2]].x-m[h[0]].x;var k=m[h[2]].y-m[h[0]].y;var d=m[h[2]].z-m[h[0]].z;c[g].normal=calcNormalVector(b,l,f,a,k,d)}}K3D.K3DObject.superclass.executePipeline.call(this);this.transformToScreen();this.controller.getRenderer(this.drawmode).sortByDistance(this)},executeRenderer:function(a){this.controller.getRenderer(this.drawmode).renderObject(this,a)},calculateAverageZ:function(){var d=0;var c=this.worldcoords;for(var b=0,a=this.points.length;b<a;b++){d+=c[b].z}this.averagez=d/this.points.length}})})();(function(){K3D.LightSource=function(b,c,a){K3D.LightSource.superclass.constructor.call(this);this.location=b;this.color=c;this.intensity=a;return this};extend(K3D.LightSource,K3D.BaseObject,{color:null,intensity:null,location:null,worldvector:null,transformToWorld:function(){var b=this.matrix;var a=this.location.x+this.aboutx;var d=this.location.y+this.abouty;var c=this.location.z+this.aboutz;this.worldvector=new Vector3D((b[0][0]*a)+(b[0][1]*d)+(b[0][2]*c)+this.offx,(b[1][0]*a)+(b[1][1]*d)+(b[1][2]*c)+this.offy,(b[2][0]*a)+(b[2][1]*d)+(b[2][2]*c)+this.offz)}})})();(function(){K3D.Renderer=function(){};K3D.Renderer.prototype={sortByDistance:function(a){},renderObject:function(b,a){}}})();(function(){K3D.PointRenderer=function(){K3D.PointRenderer.superclass.constructor.call(this);return this};extend(K3D.PointRenderer,K3D.Renderer,{sortByDistance:function(a){if(a.shademode!=="plain"&&a.sortmode==="sorted"){this.quickSortObject(a.screencoords,a.worldcoords,0,a.points.length-1)}},quickSortObject:function(h,c,i,d){var e=i,g=d,f;var b;if(d>i){f=c[(i+d)>>1].z/2;while(e<=g){while(e<d&&c[e].z>f){e++}while(g>i&&c[g].z<f){g--}if(e<=g){b=h[e];h[e]=h[g];h[g]=b;b=c[e];c[e]=c[g];c[g]=b;e++;g--}}if(i<g){this.quickSortObject(h,c,i,g)}if(e<d){this.quickSortObject(h,c,e,d)}}},renderObject:function(f,m){var b,h,k;var j=f.screencoords,d=f.worldcoords,n=f.depthscale,a=n/128,l=f.linescale/255;for(var e=0,g=f.points.length;e<g;e++){h=d[e].z+n;h=h/a;switch(f.shademode){case"lightsource":case"plain":m.fillStyle="rgb("+f.color[0]+","+f.color[1]+","+f.color[2]+")";break;case"depthcue":if(h<0){h=0}if(h>255){h=255}h=255-Math.ceil(h);m.fillStyle=f.depthcueColors[h];break}k=l*h;if(k<0.1){k=0.1}m.beginPath();m.arc(j[e].x,j[e].y,k,0,TWOPI,true);m.closePath();m.fill()}}})})();(function(){K3D.WireframeRenderer=function(){K3D.WireframeRenderer.superclass.constructor.call(this);return this};extend(K3D.WireframeRenderer,K3D.Renderer,{sortByDistance:function(a){if(a.shademode!=="plain"&&a.sortmode==="sorted"){this.quickSortObject(a.worldcoords,a.edges,0,a.edges.length-1)}},quickSortObject:function(i,b,h,c){var d=h,g=c,e;var f;if(c>h){e=((i[(b[(h+c)>>1].a)].z)+(i[(b[(h+c)>>1].b)].z))/2;while(d<=g){while((d<c)&&((i[(b[d].a)].z+i[(b[d].b)].z)/2>e)){d++}while((g>h)&&((i[(b[g].a)].z+i[(b[g].b)].z)/2<e)){g--}if(d<=g){f=b[d];b[d]=b[g];b[g]=f;d++;g--}}if(h<g){this.quickSortObject(i,b,h,g)}if(d<c){this.quickSortObject(i,b,d,c)}}},renderObject:function(h,q){var k,n,m,o;var f=h.edges,l=h.screencoords,e=h.worldcoords;var r=h.depthscale,d=r/128,p=h.linescale/255;q.lineWidth=h.linescale;for(var g=0,j=f.length;g<j;g++){n=f[g].a;m=f[g].b;switch(h.shademode){case"lightsource":case"plain":k=h.color;q.strokeStyle="rgb("+k[0]+","+k[1]+","+k[2]+")";break;case"depthcue":k=((e[n].z+e[m].z)/2)+r;k=k/d;if(k<0){k=0}if(k>255){k=255}k=255-Math.ceil(k);q.strokeStyle=h.depthcueColors[k];o=p*k;q.lineWidth=(o>0.1?o:0.1);break}q.beginPath();q.moveTo(l[n].x,l[n].y);q.lineTo(l[m].x,l[m].y);q.closePath();q.stroke()}}})})();(function(){K3D.SolidRenderer=function(){K3D.SolidRenderer.superclass.constructor.call(this);return this};extend(K3D.SolidRenderer,K3D.Renderer,{sortByDistance:function b(e){if(e.sortmode==="sorted"){this.quickSortObject(e.worldcoords,e.faces,0,e.faces.length-1)}},quickSortObject:function a(h,r,g,s){var q=g,f=s,p,o,n,e;if(s>g){n=r[(g+s)>>1].vertices;for(var l=0,k=n.length,m=0;l<k;l++){m+=h[n[l]].z}p=m/n.length;while(q<=f){while(true){n=r[q].vertices;for(var l=0,k=n.length,m=0;l<k;l++){m+=(h[n[l]].z)}e=m/n.length;if(q<s&&e>p){q++}else{break}}while(true){n=r[f].vertices;for(var l=0,k=n.length,m=0;l<k;l++){m+=h[n[l]].z}e=m/n.length;if(f>g&&e<p){f--}else{break}}if(q<=f){o=r[q];r[q]=r[f];r[f]=o;q++;f--}}if(g<f){this.quickSortObject(h,r,g,f)}if(q<s){this.quickSortObject(h,r,q,s)}}},renderObject:function c(w,A){var h=w.faces,k=w.screencoords,p=w.worldcoords;var m=w.depthscale,I=m/128;var x=new Vector3D(0,0,1);var s,y,E,H,G,v=Math.PI/2,q;var K=w.controller.lights;var J=w.doublesided;for(var z=0,D=h.length,u;z<D;z++){u=h[z];s=u.vertices;var F=x.thetaTo(u.worldnormal);if(J||(F+0.15>v)){switch(w.shademode){case"plain":if(u.texture===null){G=u.color;q="rgb("+G[0]+","+G[1]+","+G[2]+")";this.renderPolygon(A,w,u,q)}else{this.renderPolygon(A,w,u)}break;case"depthcue":for(var C=0,B=s.length,t=0;C<B;C++){t+=p[s[C]].z}var o=((t/s.length)+m)/I;if(o<0){o=0}if(o>255){o=255}if(u.texture===null){o=(255-o)/255;G=u.color;y=Math.ceil(o*G[0]);E=Math.ceil(o*G[1]);H=Math.ceil(o*G[2]);q="rgb("+y+","+E+","+H+")"}else{o=255-Math.ceil(o);q="rgba(0,0,0,"+(1-(o/255))+")"}this.renderPolygon(A,w,u,q);break;case"lightsource":if(K.length===0){G=u.color;y=Math.ceil(F*(G[0]/Math.PI));E=Math.ceil(F*(G[1]/Math.PI));H=Math.ceil(F*(G[2]/Math.PI));if(u.texture===null){q="rgb("+y+","+E+","+H+")"}else{q="rgba(0,0,0,"+(1-F*(1/Math.PI))+")"}this.renderPolygon(A,w,u,q)}else{y=0;E=0;H=0;for(var C=0,B=K.length,l,e;C<B;C++){l=K[C];F=Math.PI-l.worldvector.thetaTo(u.worldnormal);e=F*((1/l.worldvector.distance(u.worldnormal))*l.intensity)/Math.PI;y+=(e*l.color[0]);E+=(e*l.color[1]);H+=(e*l.color[2])}if(y>1){y=1}if(E>1){E=1}if(H>1){H=1}G=u.color;var f=Math.ceil(y*G[0])+","+Math.ceil(E*G[1])+","+Math.ceil(H*G[2]);if(u.texture===null){q="rgb("+f+")"}else{q="rgba("+f+","+(1-(y+E+H)/3)+")"}this.renderPolygon(A,w,u,q)}break}}}},renderPolygon:function d(w,v,p,n){var g=v.screencoords,o=p.vertices;w.save();w.beginPath();w.moveTo(g[o[0]].x,g[o[0]].y);for(var A=1,y=o.length;A<y;A++){w.lineTo(g[o[A]].x,g[o[A]].y)}w.closePath();if(p.texture===null){w.fillStyle=n;w.fill();if(v.fillstroke){w.fill()}}else{w.clip();var H=v.textures[p.texture];var s=16,C=16,r=H.width-16,z=16,q=H.width-16,x=H.height-16;var E=g[o[0]].x,k=g[o[0]].y,D=g[o[1]].x,h=g[o[1]].y,B=g[o[2]].x,f=g[o[2]].y;var e=H.denom;if(e===undefined){e=s*(x-z)-r*x+q*z+(r-q)*C;H.denom=e}var G=-(C*(B-D)-z*B+x*D+(z-x)*E)/e;var F=(z*f+C*(h-f)-x*h+(x-z)*k)/e;var m=(s*(B-D)-r*B+q*D+(r-q)*E)/e;var l=-(r*f+s*(h-f)-q*h+(q-r)*k)/e;var u=(s*(x*D-z*B)+C*(r*B-q*D)+(q*z-r*x)*E)/e;var t=(s*(x*h-z*f)+C*(r*f-q*h)+(q*z-r*x)*k)/e;w.transform(G,F,m,l,u,t);w.drawImage(H,0,0);if(n){w.fillStyle=n;w.fill()}}w.restore()}})})();
