1 | /**
|
---|
2 | * @author oosmoxiecode
|
---|
3 | * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
|
---|
4 | */
|
---|
5 |
|
---|
6 | THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale ) {
|
---|
7 |
|
---|
8 | THREE.Geometry.call( this );
|
---|
9 |
|
---|
10 | var scope = this;
|
---|
11 |
|
---|
12 | this.radius = radius || 100;
|
---|
13 | this.tube = tube || 40;
|
---|
14 | this.radialSegments = radialSegments || 64;
|
---|
15 | this.tubularSegments = tubularSegments || 8;
|
---|
16 | this.p = p || 2;
|
---|
17 | this.q = q || 3;
|
---|
18 | this.heightScale = heightScale || 1;
|
---|
19 | this.grid = new Array( this.radialSegments );
|
---|
20 |
|
---|
21 | var tang = new THREE.Vector3();
|
---|
22 | var n = new THREE.Vector3();
|
---|
23 | var bitan = new THREE.Vector3();
|
---|
24 |
|
---|
25 | for ( var i = 0; i < this.radialSegments; ++ i ) {
|
---|
26 |
|
---|
27 | this.grid[ i ] = new Array( this.tubularSegments );
|
---|
28 | var u = i / this.radialSegments * 2 * this.p * Math.PI;
|
---|
29 | var p1 = getPos( u, this.q, this.p, this.radius, this.heightScale );
|
---|
30 | var p2 = getPos( u + 0.01, this.q, this.p, this.radius, this.heightScale );
|
---|
31 | tang.subVectors( p2, p1 );
|
---|
32 | n.addVectors( p2, p1 );
|
---|
33 |
|
---|
34 | bitan.crossVectors( tang, n );
|
---|
35 | n.crossVectors( bitan, tang );
|
---|
36 | bitan.normalize();
|
---|
37 | n.normalize();
|
---|
38 |
|
---|
39 | for ( var j = 0; j < this.tubularSegments; ++ j ) {
|
---|
40 |
|
---|
41 | var v = j / this.tubularSegments * 2 * Math.PI;
|
---|
42 | var cx = - this.tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
|
---|
43 | var cy = this.tube * Math.sin( v );
|
---|
44 |
|
---|
45 | var pos = new THREE.Vector3();
|
---|
46 | pos.x = p1.x + cx * n.x + cy * bitan.x;
|
---|
47 | pos.y = p1.y + cx * n.y + cy * bitan.y;
|
---|
48 | pos.z = p1.z + cx * n.z + cy * bitan.z;
|
---|
49 |
|
---|
50 | this.grid[ i ][ j ] = scope.vertices.push( pos ) - 1;
|
---|
51 |
|
---|
52 | }
|
---|
53 |
|
---|
54 | }
|
---|
55 |
|
---|
56 | for ( var i = 0; i < this.radialSegments; ++ i ) {
|
---|
57 |
|
---|
58 | for ( var j = 0; j < this.tubularSegments; ++ j ) {
|
---|
59 |
|
---|
60 | var ip = ( i + 1 ) % this.radialSegments;
|
---|
61 | var jp = ( j + 1 ) % this.tubularSegments;
|
---|
62 |
|
---|
63 | var a = this.grid[ i ][ j ];
|
---|
64 | var b = this.grid[ ip ][ j ];
|
---|
65 | var c = this.grid[ ip ][ jp ];
|
---|
66 | var d = this.grid[ i ][ jp ];
|
---|
67 |
|
---|
68 | var uva = new THREE.Vector2( i / this.radialSegments, j / this.tubularSegments );
|
---|
69 | var uvb = new THREE.Vector2( ( i + 1 ) / this.radialSegments, j / this.tubularSegments );
|
---|
70 | var uvc = new THREE.Vector2( ( i + 1 ) / this.radialSegments, ( j + 1 ) / this.tubularSegments );
|
---|
71 | var uvd = new THREE.Vector2( i / this.radialSegments, ( j + 1 ) / this.tubularSegments );
|
---|
72 |
|
---|
73 | this.faces.push( new THREE.Face3( a, b, d ) );
|
---|
74 | this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
|
---|
75 |
|
---|
76 | this.faces.push( new THREE.Face3( b, c, d ) );
|
---|
77 | this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
|
---|
78 |
|
---|
79 | }
|
---|
80 | }
|
---|
81 |
|
---|
82 | this.computeCentroids();
|
---|
83 | this.computeFaceNormals();
|
---|
84 | this.computeVertexNormals();
|
---|
85 |
|
---|
86 | function getPos( u, in_q, in_p, radius, heightScale ) {
|
---|
87 |
|
---|
88 | var cu = Math.cos( u );
|
---|
89 | var su = Math.sin( u );
|
---|
90 | var quOverP = in_q / in_p * u;
|
---|
91 | var cs = Math.cos( quOverP );
|
---|
92 |
|
---|
93 | var tx = radius * ( 2 + cs ) * 0.5 * cu;
|
---|
94 | var ty = radius * ( 2 + cs ) * su * 0.5;
|
---|
95 | var tz = heightScale * radius * Math.sin( quOverP ) * 0.5;
|
---|
96 |
|
---|
97 | return new THREE.Vector3( tx, ty, tz );
|
---|
98 |
|
---|
99 | }
|
---|
100 |
|
---|
101 | };
|
---|
102 |
|
---|
103 | THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
---|