Buckets:
| import { BufferGeometry } from '../core/BufferGeometry.js'; | |
| import { Float32BufferAttribute } from '../core/BufferAttribute.js'; | |
| import * as Curves from '../extras/curves/Curves.js'; | |
| import { Vector2 } from '../math/Vector2.js'; | |
| import { Vector3 } from '../math/Vector3.js'; | |
| class TubeGeometry extends BufferGeometry { | |
| constructor( path = new Curves[ 'QuadraticBezierCurve3' ]( new Vector3( - 1, - 1, 0 ), new Vector3( - 1, 1, 0 ), new Vector3( 1, 1, 0 ) ), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) { | |
| super(); | |
| this.type = 'TubeGeometry'; | |
| this.parameters = { | |
| path: path, | |
| tubularSegments: tubularSegments, | |
| radius: radius, | |
| radialSegments: radialSegments, | |
| closed: closed | |
| }; | |
| const frames = path.computeFrenetFrames( tubularSegments, closed ); | |
| // expose internals | |
| this.tangents = frames.tangents; | |
| this.normals = frames.normals; | |
| this.binormals = frames.binormals; | |
| // helper variables | |
| const vertex = new Vector3(); | |
| const normal = new Vector3(); | |
| const uv = new Vector2(); | |
| let P = new Vector3(); | |
| // buffer | |
| const vertices = []; | |
| const normals = []; | |
| const uvs = []; | |
| const indices = []; | |
| // create buffer data | |
| generateBufferData(); | |
| // build geometry | |
| this.setIndex( indices ); | |
| this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); | |
| this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); | |
| this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); | |
| // functions | |
| function generateBufferData() { | |
| for ( let i = 0; i < tubularSegments; i ++ ) { | |
| generateSegment( i ); | |
| } | |
| // if the geometry is not closed, generate the last row of vertices and normals | |
| // at the regular position on the given path | |
| // | |
| // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) | |
| generateSegment( ( closed === false ) ? tubularSegments : 0 ); | |
| // uvs are generated in a separate function. | |
| // this makes it easy compute correct values for closed geometries | |
| generateUVs(); | |
| // finally create faces | |
| generateIndices(); | |
| } | |
| function generateSegment( i ) { | |
| // we use getPointAt to sample evenly distributed points from the given path | |
| P = path.getPointAt( i / tubularSegments, P ); | |
| // retrieve corresponding normal and binormal | |
| const N = frames.normals[ i ]; | |
| const B = frames.binormals[ i ]; | |
| // generate normals and vertices for the current segment | |
| for ( let j = 0; j <= radialSegments; j ++ ) { | |
| const v = j / radialSegments * Math.PI * 2; | |
| const sin = Math.sin( v ); | |
| const cos = - Math.cos( v ); | |
| // normal | |
| normal.x = ( cos * N.x + sin * B.x ); | |
| normal.y = ( cos * N.y + sin * B.y ); | |
| normal.z = ( cos * N.z + sin * B.z ); | |
| normal.normalize(); | |
| normals.push( normal.x, normal.y, normal.z ); | |
| // vertex | |
| vertex.x = P.x + radius * normal.x; | |
| vertex.y = P.y + radius * normal.y; | |
| vertex.z = P.z + radius * normal.z; | |
| vertices.push( vertex.x, vertex.y, vertex.z ); | |
| } | |
| } | |
| function generateIndices() { | |
| for ( let j = 1; j <= tubularSegments; j ++ ) { | |
| for ( let i = 1; i <= radialSegments; i ++ ) { | |
| const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); | |
| const b = ( radialSegments + 1 ) * j + ( i - 1 ); | |
| const c = ( radialSegments + 1 ) * j + i; | |
| const d = ( radialSegments + 1 ) * ( j - 1 ) + i; | |
| // faces | |
| indices.push( a, b, d ); | |
| indices.push( b, c, d ); | |
| } | |
| } | |
| } | |
| function generateUVs() { | |
| for ( let i = 0; i <= tubularSegments; i ++ ) { | |
| for ( let j = 0; j <= radialSegments; j ++ ) { | |
| uv.x = i / tubularSegments; | |
| uv.y = j / radialSegments; | |
| uvs.push( uv.x, uv.y ); | |
| } | |
| } | |
| } | |
| } | |
| copy( source ) { | |
| super.copy( source ); | |
| this.parameters = Object.assign( {}, source.parameters ); | |
| return this; | |
| } | |
| toJSON() { | |
| const data = super.toJSON(); | |
| data.path = this.parameters.path.toJSON(); | |
| return data; | |
| } | |
| static fromJSON( data ) { | |
| // This only works for built-in curves (e.g. CatmullRomCurve3). | |
| // User defined curves or instances of CurvePath will not be deserialized. | |
| return new TubeGeometry( | |
| new Curves[ data.path.type ]().fromJSON( data.path ), | |
| data.tubularSegments, | |
| data.radius, | |
| data.radialSegments, | |
| data.closed | |
| ); | |
| } | |
| } | |
| export { TubeGeometry }; | |
Xet Storage Details
- Size:
- 4.36 kB
- Xet hash:
- fe458e418aa2a7fb041137ca7583384ef510a985f5c09fc9ba192e3533ddc058
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.