The aim of the project is to create a lightweight 3D library with a very low level of complexity — in other words, for dummies. The library provides <canvas>, <svg> and WebGL renderers.
The aim of the project is to create a lightweight 3D library with a very low level of complexity — in other words, for dummies. The library provides <canvas>, <svg> and WebGL renderers.
-<a href="http://xplsv.com/prods/demos/xplsv_orsotheysay/"><img src="http://mrdoob.github.com/three.js/assets/projects/07_orsotheysay.png" width="102" height="77" alt="Or so they say..."></a>
@@ -90,7 +17,7 @@ Alternatively see [how to build the library yourself](https://github.com/mrdoob/
<script src="js/Three.js"></script>
<script src="js/Three.js"></script>
```
```
-This code creates a camera, then creates a scene, adds a cube on it, creates a <canvas> renderer and adds its viewport in the document.body element.
+This code creates a scene, then creates a camera, adds the camera and cube to the scene, creates a <canvas> renderer and adds its viewport in the document.body element.
+this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1};
-this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b=
-void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(f)}a.updateMatrixWorld();f.matrixWorldInverse.getInverse(f.matrixWorld);G.multiply(f.projectionMatrix,f.matrixWorldInverse);y.setFromMatrix(G);v=this.projectGraph(a,false);a=0;for(P=v.objects.length;a<P;a++){B=v.objects[a].object;J=B.matrixWorld;m=0;if(B instanceof THREE.Mesh){I=B.geometry;K=B.geometry.materials;U=I.vertices;R=I.faces;ja=I.faceVertexUvs;I=B.matrixRotationWorld.extractRotation(J);O=0;for(w=
-c*a+e*g+d*f-b*k;this.z=d*a+e*k+b*g-c*f;this.w=e*a-b*f-c*g-d*k;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,k=this.z,m=this.w,j=m*c+g*e-k*d,h=m*d+k*c-f*e,i=m*e+f*d-g*c,c=-f*c-g*d-k*e;b.x=j*m+c*-f+h*-k-i*-g;b.y=h*m+c*-g+i*-f-j*-k;b.z=i*m+c*-k+j*-g-h*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}};
-THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.0010){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")};
+this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.setEulerFromRotationMatrix(this.matrix,this.eulerOrder)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=
+void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(e)}a.updateMatrixWorld();e.matrixWorldInverse.getInverse(e.matrixWorld);F.multiply(e.projectionMatrix,e.matrixWorldInverse);z.setFromMatrix(F);w=this.projectGraph(a,false);a=0;for(Q=w.objects.length;a<Q;a++){C=w.objects[a].object;J=C.matrixWorld;k=0;if(C instanceof THREE.Mesh){I=C.geometry;K=C.geometry.materials;S=I.vertices;R=I.faces;ja=I.faceVertexUvs;I=C.matrixRotationWorld.extractRotation(J);O=0;for(y=
+this.y=0.5*(d+this.y);this.z=0.5*(f+this.z);return this}g=Math.sin((1-b)*m)/k;m=Math.sin(b*m)/k;this.w=e*g+this.w*m;this.x=c*g+this.x*m;this.y=d*g+this.y*m;this.z=f*g+this.z*m;return this},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}};
+THREE.Quaternion.slerp=function(a,b,c,d){var f=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(f<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;f=-f}else c.copy(b);if(Math.abs(f)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var b=Math.acos(f),e=Math.sqrt(1-f*f);if(Math.abs(e)<0.001){c.w=0.5*(a.w+c.w);c.x=0.5*(a.x+c.x);c.y=0.5*(a.y+c.y);c.z=0.5*(a.z+c.z);return c}f=Math.sin((1-d)*b)/e;d=Math.sin(d*b)/e;c.w=a.w*f+c.w*d;c.x=a.x*f+c.x*d;c.y=a.y*f+c.y*d;c.z=a.z*f+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")};
-THREE.JSONLoader.prototype.loadAjaxJSON=function(a,b,c,d,e){var f=new XMLHttpRequest,g=0;f.onreadystatechange=function(){if(f.readyState===f.DONE)if(f.status===200||f.status===0){if(f.responseText){var k=JSON.parse(f.responseText);a.createModel(k,c,d)}else console.warn("THREE.JSONLoader: ["+b+"] seems to be unreachable or file there is empty");a.onLoadComplete()}else console.error("THREE.JSONLoader: Couldn't load ["+b+"] ["+f.status+"]");else if(f.readyState===f.LOADING){if(e){g===0&&(g=f.getResponseHeader("Content-Length"));
-z[2]);t&&w.scene.scale.set(t[0],t[1],t[2]);if(a||z||t){w.scene.updateMatrix();w.scene.updateMatrixWorld()}}a=function(){H=H-1;k();m.onLoadComplete()};for(p in r.cameras){t=r.cameras[p];t.type=="perspective"?Q=new THREE.PerspectiveCamera(t.fov,t.aspect,t.near,t.far):t.type=="ortho"&&(Q=new THREE.OrthographicCamera(t.left,t.right,t.top,t.bottom,t.near,t.far));v=t.position;z=t.target;t=t.up;Q.position.set(v[0],v[1],v[2]);Q.target=new THREE.Vector3(z[0],z[1],z[2]);t&&Q.up.set(t[0],t[1],t[2]);w.cameras[p]=
-Q}for(n in r.lights){z=r.lights[n];p=z.color!==void 0?z.color:16777215;Q=z.intensity!==void 0?z.intensity:1;if(z.type=="directional"){v=z.direction;A=new THREE.DirectionalLight(p,Q);A.position.set(v[0],v[1],v[2]);A.position.normalize()}else if(z.type=="point"){v=z.position;A=z.distance;A=new THREE.PointLight(p,Q,A);A.position.set(v[0],v[1],v[2])}else z.type=="ambient"&&(A=new THREE.AmbientLight(p));w.scene.add(A);w.lights[n]=A}for(l in r.fogs){n=r.fogs[l];n.type=="linear"?N=new THREE.Fog(0,n.near,
-n.far):n.type=="exp2"&&(N=new THREE.FogExp2(0,n.density));t=n.color;N.color.setRGB(t[0],t[1],t[2]);w.fogs[l]=N}if(w.cameras&&r.defaults.camera)w.currentCamera=w.cameras[r.defaults.camera];if(w.fogs&&r.defaults.fog)w.scene.fog=w.fogs[r.defaults.fog];t=r.defaults.bgcolor;w.bgColor=new THREE.Color;w.bgColor.setRGB(t[0],t[1],t[2]);w.bgColorAlpha=r.defaults.bgalpha;for(h in r.geometries){l=r.geometries[h];if(l.type=="bin_mesh"||l.type=="ascii_mesh"){F=F+1;m.onLoadStart()}}P=F;for(h in r.geometries){l=
-if(THREE[h.magFilter]!=void 0)l.magFilter=THREE[h.magFilter];if(h.repeat){l.repeat.set(h.repeat[0],h.repeat[1]);if(h.repeat[0]!=1)l.wrapS=THREE.RepeatWrapping;if(h.repeat[1]!=1)l.wrapT=THREE.RepeatWrapping}h.offset&&l.offset.set(h.offset[0],h.offset[1]);if(h.wrap){N={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping};if(N[h.wrap[0]]!==void 0)l.wrapS=N[h.wrap[0]];if(N[h.wrap[1]]!==void 0)l.wrapT=N[h.wrap[1]]}}w.textures[q]=l}for(i in r.materials){s=r.materials[i];for(y in s.parameters)if(y==
+THREE.JSONLoader.prototype.loadAjaxJSON=function(a,b,c,d,f){var e=new XMLHttpRequest,g=0;e.onreadystatechange=function(){if(e.readyState===e.DONE)if(e.status===200||e.status===0){if(e.responseText){var m=JSON.parse(e.responseText);a.createModel(m,c,d)}else console.warn("THREE.JSONLoader: ["+b+"] seems to be unreachable or file there is empty");a.onLoadComplete()}else console.error("THREE.JSONLoader: Couldn't load ["+b+"] ["+e.status+"]");else if(e.readyState===e.LOADING){if(f){g===0&&(g=e.getResponseHeader("Content-Length"));
+v[2]);u&&y.scene.scale.set(u[0],u[1],u[2]);if(a||v||u){y.scene.updateMatrix();y.scene.updateMatrixWorld()}}a=function(){N=N-1;m();k.onLoadComplete()};for(q in t.cameras){u=t.cameras[q];u.type=="perspective"?P=new THREE.PerspectiveCamera(u.fov,u.aspect,u.near,u.far):u.type=="ortho"&&(P=new THREE.OrthographicCamera(u.left,u.right,u.top,u.bottom,u.near,u.far));w=u.position;v=u.target;u=u.up;P.position.set(w[0],w[1],w[2]);P.target=new THREE.Vector3(v[0],v[1],v[2]);u&&P.up.set(u[0],u[1],u[2]);y.cameras[q]=
+P}for(o in t.lights){v=t.lights[o];q=v.color!==void 0?v.color:16777215;P=v.intensity!==void 0?v.intensity:1;if(v.type=="directional"){w=v.direction;A=new THREE.DirectionalLight(q,P);A.position.set(w[0],w[1],w[2]);A.position.normalize()}else if(v.type=="point"){w=v.position;A=v.distance;A=new THREE.PointLight(q,P,A);A.position.set(w[0],w[1],w[2])}else v.type=="ambient"&&(A=new THREE.AmbientLight(q));y.scene.add(A);y.lights[o]=A}for(i in t.fogs){o=t.fogs[i];o.type=="linear"?L=new THREE.Fog(0,o.near,
+o.far):o.type=="exp2"&&(L=new THREE.FogExp2(0,o.density));u=o.color;L.color.setRGB(u[0],u[1],u[2]);y.fogs[i]=L}if(y.cameras&&t.defaults.camera)y.currentCamera=y.cameras[t.defaults.camera];if(y.fogs&&t.defaults.fog)y.scene.fog=y.fogs[t.defaults.fog];u=t.defaults.bgcolor;y.bgColor=new THREE.Color;y.bgColor.setRGB(u[0],u[1],u[2]);y.bgColorAlpha=t.defaults.bgalpha;for(h in t.geometries){i=t.geometries[h];if(i.type=="bin_mesh"||i.type=="ascii_mesh"){G=G+1;k.onLoadStart()}}Q=G;for(h in t.geometries){i=
+if(THREE[h.magFilter]!=void 0)i.magFilter=THREE[h.magFilter];if(h.repeat){i.repeat.set(h.repeat[0],h.repeat[1]);if(h.repeat[0]!=1)i.wrapS=THREE.RepeatWrapping;if(h.repeat[1]!=1)i.wrapT=THREE.RepeatWrapping}h.offset&&i.offset.set(h.offset[0],h.offset[1]);if(h.wrap){L={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping};if(L[h.wrap[0]]!==void 0)i.wrapS=L[h.wrap[0]];if(L[h.wrap[1]]!==void 0)i.wrapT=L[h.wrap[1]]}}y.textures[p]=i}for(n in t.materials){s=t.materials[n];for(z in s.parameters)if(z==
new THREE.Vector2(1,1)};THREE.Sprite.prototype=new THREE.Object3D;THREE.Sprite.prototype.constructor=THREE.Sprite;THREE.Sprite.prototype.updateMatrix=function(){this.matrix.setPosition(this.position);this.rotation3d.set(0,0,this.rotation);this.matrix.setRotationFromEuler(this.rotation3d);if(this.scale.x!==1||this.scale.y!==1){this.matrix.scale(this.scale);this.boundRadiusScale=Math.max(this.scale.x,this.scale.y)}this.matrixWorldNeedsUpdate=true};THREE.SpriteAlignment={};
new THREE.Vector2(1,1)};THREE.Sprite.prototype=new THREE.Object3D;THREE.Sprite.prototype.constructor=THREE.Sprite;THREE.Sprite.prototype.updateMatrix=function(){this.matrix.setPosition(this.position);this.rotation3d.set(0,0,this.rotation);this.matrix.setRotationFromEuler(this.rotation3d);if(this.scale.x!==1||this.scale.y!==1){this.matrix.scale(this.scale);this.boundRadiusScale=Math.max(this.scale.x,this.scale.y)}this.matrixWorldNeedsUpdate=true};THREE.SpriteAlignment={};
THREE.CubicBezierCurve=function(b,a,c,d){this.v0=b;this.v1=a;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(b){var a;a=THREE.Shape.Utils.b3(b,this.v0.x,this.v1.x,this.v2.x,this.v3.x);b=THREE.Shape.Utils.b3(b,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(a,b)};
THREE.CubicBezierCurve=function(b,a,c,d){this.v0=b;this.v1=a;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(b){var a;a=THREE.Shape.Utils.b3(b,this.v0.x,this.v1.x,this.v2.x,this.v3.x);b=THREE.Shape.Utils.b3(b,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(a,b)};
-THREE.ArcCurve=function(b,a,c,d,e,f){this.aX=b;this.aY=a;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(b){var a=this.aEndAngle-this.aStartAngle;this.aClockwise||(b=1-b);a=this.aStartAngle+b*a;b=this.aX+this.aRadius*Math.cos(a);a=this.aY+this.aRadius*Math.sin(a);return new THREE.Vector2(b,a)};
+THREE.EllipseCurve=function(b,a,c,d,e,f,g){this.aX=b;this.aY=a;this.xRadius=c;this.yRadius=d;this.aStartAngle=e;this.aEndAngle=f;this.aClockwise=g};THREE.EllipseCurve.prototype=new THREE.Curve;THREE.EllipseCurve.prototype.constructor=THREE.EllipseCurve;THREE.EllipseCurve.prototype.getPoint=function(b){var a=this.aEndAngle-this.aStartAngle;this.aClockwise||(b=1-b);a=this.aStartAngle+b*a;b=this.aX+this.xRadius*Math.cos(a);a=this.aY+this.yRadius*Math.sin(a);return new THREE.Vector2(b,a)};
THREE.QuadraticBezierCurve3=THREE.Curve.create(function(b,a,c){this.v0=b;this.v1=a;this.v2=c},function(b){var a,c;a=THREE.Shape.Utils.b2(b,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(b,this.v0.y,this.v1.y,this.v2.y);b=THREE.Shape.Utils.b2(b,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(a,c,b)});
THREE.QuadraticBezierCurve3=THREE.Curve.create(function(b,a,c){this.v0=b;this.v1=a;this.v2=c},function(b){var a,c;a=THREE.Shape.Utils.b2(b,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(b,this.v0.y,this.v1.y,this.v2.y);b=THREE.Shape.Utils.b2(b,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(a,c,b)});
-THREE.EventTarget=function(){var b={};this.addEventListener=function(a,c){b[a]==void 0&&(b[a]=[]);b[a].indexOf(c)===-1&&b[a].push(c)};this.dispatchEvent=function(a){for(var c in b[a.type])b[a.type][c](a)};this.removeEventListener=function(a,c){var d=b[a].indexOf(c);d!==-1&&b[a].splice(d,1)}};THREE.Gyroscope=function(){THREE.Object3D.call(this)};THREE.Gyroscope.prototype=new THREE.Object3D;THREE.Gyroscope.prototype.constructor=THREE.Gyroscope;
-h;for(d=0;d<b.hierarchy[c].keys.length;d++){var l={};for(j in h){for(i=0;i<b.hierarchy[c].keys[d].morphTargets.length;i++)if(b.hierarchy[c].keys[d].morphTargets[i]===j){l[j]=b.hierarchy[c].keys[d].morphTargetsInfluences[i];break}i===b.hierarchy[c].keys[d].morphTargets.length&&(l[j]=0)}b.hierarchy[c].keys[d].morphTargetsInfluences=l}}for(d=1;d<b.hierarchy[c].keys.length;d++)if(b.hierarchy[c].keys[d].time===b.hierarchy[c].keys[d-1].time){b.hierarchy[c].keys.splice(d,1);d--}for(d=0;d<b.hierarchy[c].keys.length;d++)b.hierarchy[c].keys[d].index=
+{};for(j in h){for(i=0;i<b.hierarchy[c].keys[d].morphTargets.length;i++)if(b.hierarchy[c].keys[d].morphTargets[i]===j){l[j]=b.hierarchy[c].keys[d].morphTargetsInfluences[i];break}i===b.hierarchy[c].keys[d].morphTargets.length&&(l[j]=0)}b.hierarchy[c].keys[d].morphTargetsInfluences=l}}for(d=1;d<b.hierarchy[c].keys.length;d++)if(b.hierarchy[c].keys[d].time===b.hierarchy[c].keys[d-1].time){b.hierarchy[c].keys.splice(d,1);d--}for(d=0;d<b.hierarchy[c].keys.length;d++)b.hierarchy[c].keys[d].index=d}d=parseInt(b.length*
e instanceof THREE.Bone?e.skinMatrix:e.matrix}var f=e.animationCache.prevKey;e=e.animationCache.nextKey;f.pos=this.data.hierarchy[c].keys[0];f.rot=this.data.hierarchy[c].keys[0];f.scl=this.data.hierarchy[c].keys[0];e.pos=this.getNextKeyWith("pos",c,1);e.rot=this.getNextKeyWith("rot",c,1);e.scl=this.getNextKeyWith("scl",c,1)}this.update(0)}this.isPaused=false;THREE.AnimationHandler.addToUpdate(this)};
e instanceof THREE.Bone?e.skinMatrix:e.matrix}var f=e.animationCache.prevKey;e=e.animationCache.nextKey;f.pos=this.data.hierarchy[c].keys[0];f.rot=this.data.hierarchy[c].keys[0];f.scl=this.data.hierarchy[c].keys[0];e.pos=this.getNextKeyWith("pos",c,1);e.rot=this.getNextKeyWith("rot",c,1);e.scl=this.getNextKeyWith("scl",c,1)}this.update(0)}this.isPaused=false;THREE.AnimationHandler.addToUpdate(this)};
[];this.sides={px:true,nx:true,py:true,ny:true,pz:true,nz:true};if(h!=void 0)for(var v in h)this.sides[v]!==void 0&&(this.sides[v]=h[v]);this.sides.px&&i("z","y",-1,-1,c,a,l,m);this.sides.nx&&i("z","y",1,-1,c,a,-l,r);this.sides.py&&i("x","z",1,1,b,c,n,o);this.sides.ny&&i("x","z",1,-1,b,c,-n,s);this.sides.pz&&i("x","y",1,-1,b,a,k,q);this.sides.nz&&i("x","y",-1,-1,b,a,-k,t);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=new THREE.Geometry;
[];this.sides={px:true,nx:true,py:true,ny:true,pz:true,nz:true};if(h!=void 0)for(var v in h)this.sides[v]!==void 0&&(this.sides[v]=h[v]);this.sides.px&&i("z","y",-1,-1,c,a,l,m);this.sides.nx&&i("z","y",1,-1,c,a,-l,r);this.sides.py&&i("x","z",1,1,b,c,n,o);this.sides.ny&&i("x","z",1,-1,b,c,-n,s);this.sides.pz&&i("x","y",1,-1,b,a,k,q);this.sides.nz&&i("x","y",-1,-1,b,a,-k,t);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=new THREE.Geometry;
h.copy(b).addSelf(f);i.copy(c).addSelf(g);f=d.dot(g);g=i.subSelf(h).dot(g);if(f===0){console.log("Either infinite or no solutions!");g===0?console.log("Its finite solutions."):console.log("Too bad, no solutions.")}g=g/f;if(g<0){b=Math.atan2(b.y-a.y,b.x-a.x);a=Math.atan2(c.y-a.y,c.x-a.x);b>a&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);a=new THREE.Vector2(a,c)}else a=d.multiplyScalar(g).addSelf(h).subSelf(a).clone();return a}function e(c,d){var e,f;for(y=c.length;--y>=0;){e=y;f=y-1;f<0&&
h.copy(b).addSelf(f);i.copy(c).addSelf(g);f=d.dot(g);g=i.subSelf(h).dot(g);if(f===0){console.log("Either infinite or no solutions!");g===0?console.log("Its finite solutions."):console.log("Too bad, no solutions.")}g=g/f;if(g<0){b=Math.atan2(b.y-a.y,b.x-a.x);a=Math.atan2(c.y-a.y,c.x-a.x);b>a&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);a=new THREE.Vector2(a,c)}else a=d.multiplyScalar(g).addSelf(h).subSelf(a).clone();return a}function e(c,d){var e,f;for(y=c.length;--y>=0;){e=y;f=y-1;f<0&&
-u,L,p);d(w,r[D],u.a,r[F],u,J,p)}else a("face should be a face!",u)}r=new THREE.Vector3;u=new THREE.Vector3;p=0;for(x=m.length;p<x;p++)if(I[p]!==void 0){r.set(0,0,0);u.set(0,0,0);B=new THREE.Vector3(0,0,0);w=0;for(A in K[p]){r.addSelf(q[A]);w++}z=0;F=I[p].length;for(A=0;A<F;A++)s[e(I[p][A][0],I[p][A][1])]&&z++;if(z!=2){r.divideScalar(w);for(A=0;A<F;A++){w=I[p][A];w=m[w[0]].clone().addSelf(m[w[1]]).divideScalar(2);u.addSelf(w)}u.divideScalar(F);B.addSelf(m[p]);B.multiplyScalar(F-3);B.addSelf(r);B.addSelf(u.multiplyScalar(2));
+w,I,p);d(u,r[D],w.a,r[C],w,M,p)}else a("face should be a face!",w)}r=new THREE.Vector3;w=new THREE.Vector3;p=0;for(x=m.length;p<x;p++)if(G[p]!==void 0){r.set(0,0,0);w.set(0,0,0);E=new THREE.Vector3(0,0,0);u=0;for(z in L[p]){r.addSelf(q[z]);u++}A=0;C=G[p].length;for(z=0;z<C;z++)s[e(G[p][z][0],G[p][z][1])]&&A++;if(A!=2){r.divideScalar(u);for(z=0;z<C;z++){u=G[p][z];u=m[u[0]].clone().addSelf(m[u[1]]).divideScalar(2);w.addSelf(u)}w.divideScalar(C);E.addSelf(m[p]);E.multiplyScalar(C-3);E.addSelf(r);E.addSelf(w.multiplyScalar(2));
-new THREE.Vector3(0, 10, -10), new THREE.Vector3(10, 0, -10), new THREE.Vector3(20, 0, 0), new THREE.Vector3(30, 0, 10), new THREE.Vector3(30, 0, 20), new THREE.Vector3(20, 0, 30), new THREE.Vector3(10, 0, 30), new THREE.Vector3(0, 0, 30), new THREE.Vector3(-10, 10, 30), new THREE.Vector3(-10, 20, 30), new THREE.Vector3(0, 30, 30), new THREE.Vector3(10, 30, 30), new THREE.Vector3(20, 30, 15), new THREE.Vector3(10, 30, 10), new THREE.Vector3(0, 30, 10), new THREE.Vector3(-10, 20, 10), new THREE.Vector3(-10, 10, 10), new THREE.Vector3(0, 0, 10), new THREE.Vector3(10, -10, 10), new THREE.Vector3(20, -15, 10), new THREE.Vector3(30, -15, 10), new THREE.Vector3(40, -15, 10), new THREE.Vector3(50, -15, 10), new THREE.Vector3(60, 0, 10), new THREE.Vector3(70, 0, 0), new THREE.Vector3(80, 0, 0), new THREE.Vector3(90, 0, 0), new THREE.Vector3(100, 0, 0)]);
-
-var sampleClosedSpline = new THREE.ClosedSplineCurve3([
-new THREE.Vector3(0, -40, -40),
-new THREE.Vector3(0, 40, -40),
-new THREE.Vector3(0, 140, -40),
-new THREE.Vector3(0, 40, 40),
-new THREE.Vector3(0, -40, 40),
-]);
+var windowHalfX = window.innerWidth / 2;
+var windowHalfY = window.innerHeight / 2;
+
+var binormal = new THREE.Vector3();
+var normal = new THREE.Vector3();
+
+
+var pipeSpline = new THREE.SplineCurve3([
+new THREE.Vector3(0, 10, -10), new THREE.Vector3(10, 0, -10), new THREE.Vector3(20, 0, 0), new THREE.Vector3(30, 0, 10), new THREE.Vector3(30, 0, 20), new THREE.Vector3(20, 0, 30), new THREE.Vector3(10, 0, 30), new THREE.Vector3(0, 0, 30), new THREE.Vector3(-10, 10, 30), new THREE.Vector3(-10, 20, 30), new THREE.Vector3(0, 30, 30), new THREE.Vector3(10, 30, 30), new THREE.Vector3(20, 30, 15), new THREE.Vector3(10, 30, 10), new THREE.Vector3(0, 30, 10), new THREE.Vector3(-10, 20, 10), new THREE.Vector3(-10, 10, 10), new THREE.Vector3(0, 0, 10), new THREE.Vector3(10, -10, 10), new THREE.Vector3(20, -15, 10), new THREE.Vector3(30, -15, 10), new THREE.Vector3(40, -15, 10), new THREE.Vector3(50, -15, 10), new THREE.Vector3(60, 0, 10), new THREE.Vector3(70, 0, 0), new THREE.Vector3(80, 0, 0), new THREE.Vector3(90, 0, 0), new THREE.Vector3(100, 0, 0)]);
+
+var sampleClosedSpline = new THREE.ClosedSplineCurve3([
+new THREE.Vector3(0, -40, -40),
+new THREE.Vector3(0, 40, -40),
+new THREE.Vector3(0, 140, -40),
+new THREE.Vector3(0, 40, 40),
+new THREE.Vector3(0, -40, 40),
+]);
- // Keep a diction of Curve instances
-var splines = {
-GrannyKnot: new THREE.Curves.GrannyKnot(),
-HeartCurve: new THREE.Curves.HeartCurve(3.5),
-VivianiCurve: new THREE.Curves.VivianiCurve(70),
-KnotCurve: new THREE.Curves.KnotCurve(),
-HelixCurve: new THREE.Curves.HelixCurve(),
-TrefoilKnot: new THREE.Curves.TrefoilKnot(),
-TorusKnot: new THREE.Curves.TorusKnot(20),
-CinquefoilKnot: new THREE.Curves.CinquefoilKnot(20),
-TrefoilPolynomialKnot: new THREE.Curves.TrefoilPolynomialKnot(14),
-FigureEightPolynomialKnot: new THREE.Curves.FigureEightPolynomialKnot(),
-DecoratedTorusKnot4a: new THREE.Curves.DecoratedTorusKnot4a(),
-DecoratedTorusKnot4b: new THREE.Curves.DecoratedTorusKnot4b(),
-DecoratedTorusKnot5a: new THREE.Curves.DecoratedTorusKnot5a(),
-DecoratedTorusKnot5c: new THREE.Curves.DecoratedTorusKnot5c(),
-PipeSpline: pipeSpline,
-SampleClosedSpline: sampleClosedSpline
-};
+ // Keep a dictionary of Curve instances
+var splines = {
+GrannyKnot: new THREE.Curves.GrannyKnot(),
+HeartCurve: new THREE.Curves.HeartCurve(3.5),
+VivianiCurve: new THREE.Curves.VivianiCurve(70),
+KnotCurve: new THREE.Curves.KnotCurve(),
+HelixCurve: new THREE.Curves.HelixCurve(),
+TrefoilKnot: new THREE.Curves.TrefoilKnot(),
+TorusKnot: new THREE.Curves.TorusKnot(20),
+CinquefoilKnot: new THREE.Curves.CinquefoilKnot(20),
+TrefoilPolynomialKnot: new THREE.Curves.TrefoilPolynomialKnot(14),
+FigureEightPolynomialKnot: new THREE.Curves.FigureEightPolynomialKnot(),
+DecoratedTorusKnot4a: new THREE.Curves.DecoratedTorusKnot4a(),
+DecoratedTorusKnot4b: new THREE.Curves.DecoratedTorusKnot4b(),
+DecoratedTorusKnot5a: new THREE.Curves.DecoratedTorusKnot5a(),
+DecoratedTorusKnot5c: new THREE.Curves.DecoratedTorusKnot5c(),
- // from http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m