diff --git a/docs/api/extras/geometries/TorusKnotBufferGeometry.html b/docs/api/extras/geometries/TorusKnotBufferGeometry.html new file mode 100644 index 0000000000000000000000000000000000000000..292536bcd41fcaab8c2c94261a478d3bf28d566f --- /dev/null +++ b/docs/api/extras/geometries/TorusKnotBufferGeometry.html @@ -0,0 +1,59 @@ + + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +
This is the [page:BufferGeometry] port of [page:TorusKnotGeometry].
+ + + + +

Example

+ + var geometry = new THREE.TorusKnotBufferGeometry( 10, 3, 100, 16 ); + var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + var torusKnot = new THREE.Mesh( geometry, material ); + scene.add( torusKnot ); + + + +

Constructor

+ + +

[name]([page:Float radius], [page:Float tube], [page:Integer radialSegments], [page:Integer tubularSegments], [page:Integer p], [page:Integer q], [page:Float heightScale], [page:Float arc])

+
+ +
+ + +

Properties

+ + +
+ Each of the contructor parameters is accessible as a property of the same name. Any modification of these properties after instantiation does not change the geometry. +
+ + +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] + + diff --git a/docs/api/extras/geometries/TorusKnotGeometry.html b/docs/api/extras/geometries/TorusKnotGeometry.html index 82cade9500646d6e39af170e0ace36a40642077f..be2878328aa9f8d863192a4c2a613f770fcd9f88 100644 --- a/docs/api/extras/geometries/TorusKnotGeometry.html +++ b/docs/api/extras/geometries/TorusKnotGeometry.html @@ -29,15 +29,18 @@

Constructor

-

[name]([page:Float radius], [page:Float tube], [page:Integer radialSegments], [page:Integer tubularSegments], [page:Integer p], [page:Integer q], [page:Float heightScale])

+

[name]([page:Float radius], [page:Float tube], [page:Integer radialSegments], [page:Integer tubularSegments], [page:Integer p], [page:Integer q], [page:Float heightScale], [page:Float arc])

- radius — Default is 100.
- tube — Default is 40.
- radialSegments — Default is 64.
- tubularSegments — Default is 8.
- p — Default is 2.
- q — Default is 3.
- heightScale — Default is 1. +
diff --git a/docs/list.js b/docs/list.js index 5cf09a0c5dde3f05f3fa30aba5adc975869fcb6b..c72eeb5b22c02ded6fd28d451d04a1d7e605dc41 100644 --- a/docs/list.js +++ b/docs/list.js @@ -215,6 +215,7 @@ var list = { [ "TextGeometry", "api/extras/geometries/TextGeometry" ], [ "TorusBufferGeometry", "api/extras/geometries/TorusBufferGeometry" ], [ "TorusGeometry", "api/extras/geometries/TorusGeometry" ], + [ "TorusKnotBufferGeometry", "api/extras/geometries/TorusKnotBufferGeometry" ], [ "TorusKnotGeometry", "api/extras/geometries/TorusKnotGeometry" ], [ "TubeGeometry", "api/extras/geometries/TubeGeometry" ] ], diff --git a/docs/scenes/js/geometry.js b/docs/scenes/js/geometry.js index 68fe8e0c4186921aad17ea40f52e29d9c551c289..fd34e508db53a98d4e1e19bbb5060772a6f0d7ea 100644 --- a/docs/scenes/js/geometry.js +++ b/docs/scenes/js/geometry.js @@ -747,6 +747,45 @@ var guis = { }, + TorusKnotBufferGeometry : function( mesh ) { + + var data = { + radius : 10, + tube : 3, + radialSegments : 64, + tubularSegments : 8, + p : 2, + q : 3, + heightScale : 1, + arc : twoPi + }; + + function generateGeometry() { + + updateGroupGeometry( mesh, + new THREE.TorusKnotBufferGeometry( + data.radius, data.tube, data.radialSegments, data.tubularSegments, + data.p, data.q, data.heightScale, data.arc + ) + ); + + } + + var folder = gui.addFolder( 'THREE.TorusKnotBufferGeometry' ); + + folder.add( data, 'radius', 1, 20 ).onChange( generateGeometry ); + folder.add( data, 'tube', 0.1, 10 ).onChange( generateGeometry ); + folder.add( data, 'radialSegments', 3, 300 ).step( 1 ).onChange( generateGeometry ); + folder.add( data, 'tubularSegments', 3, 20 ).step( 1 ).onChange( generateGeometry ); + folder.add( data, 'p', 1, 20 ).step( 1 ).onChange( generateGeometry ); + folder.add( data, 'q', 1, 20 ).step( 1 ).onChange( generateGeometry ); + folder.add( data, 'heightScale', 1, 20 ).onChange( generateGeometry ); + folder.add( data, 'arc', 0.1, twoPi ).onChange( generateGeometry ); + + generateGeometry(); + + }, + TorusKnotGeometry : function( mesh ) { var data = { @@ -756,7 +795,8 @@ var guis = { tubularSegments : 8, p : 2, q : 3, - heightScale : 1 + heightScale : 1, + arc : twoPi }; function generateGeometry() { @@ -764,13 +804,13 @@ var guis = { updateGroupGeometry( mesh, new THREE.TorusKnotGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, - data.p, data.q, data.heightScale + data.p, data.q, data.heightScale, data.arc ) ); } - var folder = gui.addFolder( 'THREE.TorusGeometry' ); + var folder = gui.addFolder( 'THREE.TorusKnotGeometry' ); folder.add( data, 'radius', 1, 20 ).onChange( generateGeometry ); folder.add( data, 'tube', 0.1, 10 ).onChange( generateGeometry ); @@ -779,6 +819,7 @@ var guis = { folder.add( data, 'p', 1, 20 ).step( 1 ).onChange( generateGeometry ); folder.add( data, 'q', 1, 20 ).step( 1 ).onChange( generateGeometry ); folder.add( data, 'heightScale', 1, 20 ).onChange( generateGeometry ); + folder.add( data, 'arc', 0.1, twoPi ).onChange( generateGeometry ); generateGeometry(); diff --git a/src/extras/geometries/TorusKnotBufferGeometry.js b/src/extras/geometries/TorusKnotBufferGeometry.js new file mode 100644 index 0000000000000000000000000000000000000000..1becf230fd0800fc572b84b35bf6c4c3eecf844f --- /dev/null +++ b/src/extras/geometries/TorusKnotBufferGeometry.js @@ -0,0 +1,168 @@ +/** + * @author Mugen87 / https://github.com/Mugen87 + * + * see: http://www.blackpawn.com/texts/pqtorus/ + */ +THREE.TorusKnotBufferGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale, arc ) { + + THREE.BufferGeometry.call( this ); + + this.type = 'TorusKnotBufferGeometry'; + + this.parameters = { + radius: radius, + tube: tube, + radialSegments: radialSegments, + tubularSegments: tubularSegments, + p: p, + q: q, + heightScale: heightScale, + arc: arc + }; + + radius = radius || 100; + tube = tube || 40; + radialSegments = Math.floor( radialSegments ) || 64; + tubularSegments = Math.floor( tubularSegments ) || 6; + p = p || 2; + q = q || 3; + heightScale = heightScale || 1; + arc = arc || Math.PI * 2; + + // used to calculate buffer length + var vertexCount = ( ( radialSegments + 1 ) * ( tubularSegments + 1 ) ); + var indexCount = radialSegments * tubularSegments * 2 * 3; + + // buffers + var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 ); + var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 ); + var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 ); + var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 ); + + // helper variables + var i, j, index = 0, indexOffset = 0; + + var vertex = new THREE.Vector3(); + var normal = new THREE.Vector3(); + var uv = new THREE.Vector2(); + + var P1 = new THREE.Vector3(); + var P2 = new THREE.Vector3(); + + var B = new THREE.Vector3(); + var T = new THREE.Vector3(); + var N = new THREE.Vector3(); + + // generate vertices, normals and uvs + + for ( i = 0; i <= radialSegments; ++ i ) { + + // the radian "u" is used to calculate the position on the torus curve of the current radial segement + + var u = i / radialSegments * p * arc; + + // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. + // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions + + calculatePositionOnCurve( u, p, q, radius, heightScale, P1 ); + calculatePositionOnCurve( u + 0.01, p, q, radius, heightScale, P2 ); + + // calculate orthonormal basis + + T.subVectors( P2, P1 ); + N.addVectors( P2, P1 ); + B.crossVectors( T, N ); + N.crossVectors( B, T ); + + // normalize B, N. T can be ignored, we don't use it + + B.normalize(); + N.normalize(); + + for ( j = 0; j <= tubularSegments; ++ j ) { + + // now calculate the vertices. they are nothing more than an extrusion of the torus curve. + // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. + + var v = j / tubularSegments * Math.PI * 2; + var cx = - tube * Math.cos( v ); + var cy = tube * Math.sin( v ); + + // now calculate the final vertex position. + // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve + + vertex.x = P1.x + ( cx * N.x + cy * B.x ); + vertex.y = P1.y + ( cx * N.y + cy * B.y ); + vertex.z = P1.z + ( cx * N.z + cy * B.z ); + + // vertex + vertices.setXYZ( index, vertex.x, vertex.y, vertex.z ); + + // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) + normal.subVectors( vertex, P1 ).normalize(); + normals.setXYZ( index, normal.x, normal.y, normal.z ); + + // uv + uv.x = i / radialSegments; + uv.y = j / tubularSegments; + uvs.setXY( index, uv.x, uv.y ); + + // increase index + index ++; + + } + + } + + // generate indices + + for ( j = 1; j <= radialSegments; j ++ ) { + + for ( i = 1; i <= tubularSegments; i ++ ) { + + // indices + var a = ( tubularSegments + 1 ) * ( j - 1 ) + ( i - 1 ); + var b = ( tubularSegments + 1 ) * j + ( i - 1 ); + var c = ( tubularSegments + 1 ) * j + i; + var d = ( tubularSegments + 1 ) * ( j - 1 ) + i; + + // face one + indices.setX( indexOffset, a ); indexOffset++; + indices.setX( indexOffset, b ); indexOffset++; + indices.setX( indexOffset, d ); indexOffset++; + + // face two + indices.setX( indexOffset, b ); indexOffset++; + indices.setX( indexOffset, c ); indexOffset++; + indices.setX( indexOffset, d ); indexOffset++; + + } + + } + + // build geometry + + this.setIndex( indices ); + this.addAttribute( 'position', vertices ); + this.addAttribute( 'normal', normals ); + this.addAttribute( 'uv', uvs ); + + // this function calculates the current position on the torus curve + + function calculatePositionOnCurve( u, p, q, radius, heightScale, position ) { + + var cu = Math.cos( u ); + var su = Math.sin( u ); + var quOverP = q / p * u; + var cs = Math.cos( quOverP ); + + position.x = radius * ( 2 + cs ) * 0.5 * cu; + position.y = radius * ( 2 + cs ) * su * 0.5; + position.z = heightScale * radius * Math.sin( quOverP ) * 0.5; + + } + +}; + +THREE.TorusKnotBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); +THREE.TorusKnotBufferGeometry.prototype.constructor = THREE.TorusKnotBufferGeometry; diff --git a/src/extras/geometries/TorusKnotGeometry.js b/src/extras/geometries/TorusKnotGeometry.js index b823733b9abbc83683efb93b5f414efa44ae772e..93c77118e088dd2ccd65aa9697d46b39068955c2 100644 --- a/src/extras/geometries/TorusKnotGeometry.js +++ b/src/extras/geometries/TorusKnotGeometry.js @@ -1,9 +1,8 @@ /** * @author oosmoxiecode - * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473 */ -THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale ) { +THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale, arc ) { THREE.Geometry.call( this ); @@ -16,97 +15,12 @@ THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegmen tubularSegments: tubularSegments, p: p, q: q, - heightScale: heightScale + heightScale: heightScale, + arc: arc }; - radius = radius || 100; - tube = tube || 40; - radialSegments = radialSegments || 64; - tubularSegments = tubularSegments || 8; - p = p || 2; - q = q || 3; - heightScale = heightScale || 1; - - var grid = new Array( radialSegments ); - var tang = new THREE.Vector3(); - var n = new THREE.Vector3(); - var bitan = new THREE.Vector3(); - - for ( var i = 0; i < radialSegments; ++ i ) { - - grid[ i ] = new Array( tubularSegments ); - var u = i / radialSegments * 2 * p * Math.PI; - var p1 = getPos( u, q, p, radius, heightScale ); - var p2 = getPos( u + 0.01, q, p, radius, heightScale ); - tang.subVectors( p2, p1 ); - n.addVectors( p2, p1 ); - - bitan.crossVectors( tang, n ); - n.crossVectors( bitan, tang ); - bitan.normalize(); - n.normalize(); - - for ( var j = 0; j < tubularSegments; ++ j ) { - - var v = j / tubularSegments * 2 * Math.PI; - var cx = - tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. - var cy = tube * Math.sin( v ); - - var pos = new THREE.Vector3(); - pos.x = p1.x + cx * n.x + cy * bitan.x; - pos.y = p1.y + cx * n.y + cy * bitan.y; - pos.z = p1.z + cx * n.z + cy * bitan.z; - - grid[ i ][ j ] = this.vertices.push( pos ) - 1; - - } - - } - - for ( var i = 0; i < radialSegments; ++ i ) { - - for ( var j = 0; j < tubularSegments; ++ j ) { - - var ip = ( i + 1 ) % radialSegments; - var jp = ( j + 1 ) % tubularSegments; - - var a = grid[ i ][ j ]; - var b = grid[ ip ][ j ]; - var c = grid[ ip ][ jp ]; - var d = grid[ i ][ jp ]; - - var uva = new THREE.Vector2( i / radialSegments, j / tubularSegments ); - var uvb = new THREE.Vector2( ( i + 1 ) / radialSegments, j / tubularSegments ); - var uvc = new THREE.Vector2( ( i + 1 ) / radialSegments, ( j + 1 ) / tubularSegments ); - var uvd = new THREE.Vector2( i / radialSegments, ( j + 1 ) / tubularSegments ); - - this.faces.push( new THREE.Face3( a, b, d ) ); - this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] ); - - this.faces.push( new THREE.Face3( b, c, d ) ); - this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] ); - - } - - } - - this.computeFaceNormals(); - this.computeVertexNormals(); - - function getPos( u, in_q, in_p, radius, heightScale ) { - - var cu = Math.cos( u ); - var su = Math.sin( u ); - var quOverP = in_q / in_p * u; - var cs = Math.cos( quOverP ); - - var tx = radius * ( 2 + cs ) * 0.5 * cu; - var ty = radius * ( 2 + cs ) * su * 0.5; - var tz = heightScale * radius * Math.sin( quOverP ) * 0.5; - - return new THREE.Vector3( tx, ty, tz ); - - } + this.fromBufferGeometry( new THREE.TorusKnotBufferGeometry( radius, tube, radialSegments, tubularSegments, p, q, heightScale, arc ) ); + this.mergeVertices(); }; diff --git a/utils/build/includes/extras.json b/utils/build/includes/extras.json index b072e8f576961f0bce3af78227270fbbf59f2ae4..30538042f4ebd7b228500e2e5969de3e56a0c482 100644 --- a/utils/build/includes/extras.json +++ b/utils/build/includes/extras.json @@ -38,6 +38,7 @@ "src/extras/geometries/TextGeometry.js", "src/extras/geometries/TorusBufferGeometry.js", "src/extras/geometries/TorusGeometry.js", + "src/extras/geometries/TorusKnotBufferGeometry.js", "src/extras/geometries/TorusKnotGeometry.js", "src/extras/geometries/TubeGeometry.js", "src/extras/geometries/PolyhedronGeometry.js",