initial commit
This commit is contained in:
203
lib/geometries/BoxGeometry.js
Normal file
203
lib/geometries/BoxGeometry.js
Normal file
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// BoxGeometry
|
||||
|
||||
function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'BoxGeometry';
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
depth: depth,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
depthSegments: depthSegments
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
BoxGeometry.prototype = Object.create( Geometry.prototype );
|
||||
BoxGeometry.prototype.constructor = BoxGeometry;
|
||||
|
||||
// BoxBufferGeometry
|
||||
|
||||
function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'BoxBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
depth: depth,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
depthSegments: depthSegments
|
||||
};
|
||||
|
||||
var scope = this;
|
||||
|
||||
width = width || 1;
|
||||
height = height || 1;
|
||||
depth = depth || 1;
|
||||
|
||||
// segments
|
||||
|
||||
widthSegments = Math.floor( widthSegments ) || 1;
|
||||
heightSegments = Math.floor( heightSegments ) || 1;
|
||||
depthSegments = Math.floor( depthSegments ) || 1;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var numberOfVertices = 0;
|
||||
var groupStart = 0;
|
||||
|
||||
// build each side of the box geometry
|
||||
|
||||
buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
|
||||
buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
|
||||
buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
|
||||
buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
|
||||
buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
|
||||
buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
|
||||
|
||||
var segmentWidth = width / gridX;
|
||||
var segmentHeight = height / gridY;
|
||||
|
||||
var widthHalf = width / 2;
|
||||
var heightHalf = height / 2;
|
||||
var depthHalf = depth / 2;
|
||||
|
||||
var gridX1 = gridX + 1;
|
||||
var gridY1 = gridY + 1;
|
||||
|
||||
var vertexCounter = 0;
|
||||
var groupCount = 0;
|
||||
|
||||
var ix, iy;
|
||||
|
||||
var vector = new Vector3();
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( iy = 0; iy < gridY1; iy ++ ) {
|
||||
|
||||
var y = iy * segmentHeight - heightHalf;
|
||||
|
||||
for ( ix = 0; ix < gridX1; ix ++ ) {
|
||||
|
||||
var x = ix * segmentWidth - widthHalf;
|
||||
|
||||
// set values to correct vector component
|
||||
|
||||
vector[ u ] = x * udir;
|
||||
vector[ v ] = y * vdir;
|
||||
vector[ w ] = depthHalf;
|
||||
|
||||
// now apply vector to vertex buffer
|
||||
|
||||
vertices.push( vector.x, vector.y, vector.z );
|
||||
|
||||
// set values to correct vector component
|
||||
|
||||
vector[ u ] = 0;
|
||||
vector[ v ] = 0;
|
||||
vector[ w ] = depth > 0 ? 1 : - 1;
|
||||
|
||||
// now apply vector to normal buffer
|
||||
|
||||
normals.push( vector.x, vector.y, vector.z );
|
||||
|
||||
// uvs
|
||||
|
||||
uvs.push( ix / gridX );
|
||||
uvs.push( 1 - ( iy / gridY ) );
|
||||
|
||||
// counters
|
||||
|
||||
vertexCounter += 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
// 1. you need three indices to draw a single face
|
||||
// 2. a single segment consists of two faces
|
||||
// 3. so we need to generate six (2*3) indices per segment
|
||||
|
||||
for ( iy = 0; iy < gridY; iy ++ ) {
|
||||
|
||||
for ( ix = 0; ix < gridX; ix ++ ) {
|
||||
|
||||
var a = numberOfVertices + ix + gridX1 * iy;
|
||||
var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
|
||||
var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
|
||||
var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
// increase counter
|
||||
|
||||
groupCount += 6;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add a group to the geometry. this will ensure multi material support
|
||||
|
||||
scope.addGroup( groupStart, groupCount, materialIndex );
|
||||
|
||||
// calculate new start value for groups
|
||||
|
||||
groupStart += groupCount;
|
||||
|
||||
// update total number of vertices
|
||||
|
||||
numberOfVertices += vertexCounter;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
|
||||
|
||||
|
||||
export { BoxGeometry, BoxBufferGeometry };
|
121
lib/geometries/CircleGeometry.js
Normal file
121
lib/geometries/CircleGeometry.js
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @author benaadams / https://twitter.com/ben_a_adams
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
* @author hughes
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
|
||||
// CircleGeometry
|
||||
|
||||
function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'CircleGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
segments: segments,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
CircleGeometry.prototype = Object.create( Geometry.prototype );
|
||||
CircleGeometry.prototype.constructor = CircleGeometry;
|
||||
|
||||
// CircleBufferGeometry
|
||||
|
||||
function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'CircleBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
segments: segments,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
radius = radius || 1;
|
||||
segments = segments !== undefined ? Math.max( 3, segments ) : 8;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var i, s;
|
||||
var vertex = new Vector3();
|
||||
var uv = new Vector2();
|
||||
|
||||
// center point
|
||||
|
||||
vertices.push( 0, 0, 0 );
|
||||
normals.push( 0, 0, 1 );
|
||||
uvs.push( 0.5, 0.5 );
|
||||
|
||||
for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
|
||||
|
||||
var segment = thetaStart + s / segments * thetaLength;
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = radius * Math.cos( segment );
|
||||
vertex.y = radius * Math.sin( segment );
|
||||
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
normals.push( 0, 0, 1 );
|
||||
|
||||
// uvs
|
||||
|
||||
uv.x = ( vertices[ i ] / radius + 1 ) / 2;
|
||||
uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
|
||||
|
||||
uvs.push( uv.x, uv.y );
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for ( i = 1; i <= segments; i ++ ) {
|
||||
|
||||
indices.push( i, i + 1, 0 );
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
|
||||
|
||||
|
||||
export { CircleGeometry, CircleBufferGeometry };
|
55
lib/geometries/ConeGeometry.js
Normal file
55
lib/geometries/ConeGeometry.js
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @author abelnation / http://github.com/abelnation
|
||||
*/
|
||||
|
||||
import { CylinderGeometry } from './CylinderGeometry.js';
|
||||
import { CylinderBufferGeometry } from './CylinderGeometry.js';
|
||||
|
||||
// ConeGeometry
|
||||
|
||||
function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
|
||||
|
||||
CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
|
||||
|
||||
this.type = 'ConeGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
height: height,
|
||||
radialSegments: radialSegments,
|
||||
heightSegments: heightSegments,
|
||||
openEnded: openEnded,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
|
||||
ConeGeometry.prototype.constructor = ConeGeometry;
|
||||
|
||||
// ConeBufferGeometry
|
||||
|
||||
function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
|
||||
|
||||
CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
|
||||
|
||||
this.type = 'ConeBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
height: height,
|
||||
radialSegments: radialSegments,
|
||||
heightSegments: heightSegments,
|
||||
openEnded: openEnded,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
|
||||
ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
|
||||
|
||||
|
||||
export { ConeGeometry, ConeBufferGeometry };
|
316
lib/geometries/CylinderGeometry.js
Normal file
316
lib/geometries/CylinderGeometry.js
Normal file
@ -0,0 +1,316 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
|
||||
// CylinderGeometry
|
||||
|
||||
function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'CylinderGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radiusTop: radiusTop,
|
||||
radiusBottom: radiusBottom,
|
||||
height: height,
|
||||
radialSegments: radialSegments,
|
||||
heightSegments: heightSegments,
|
||||
openEnded: openEnded,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
CylinderGeometry.prototype = Object.create( Geometry.prototype );
|
||||
CylinderGeometry.prototype.constructor = CylinderGeometry;
|
||||
|
||||
// CylinderBufferGeometry
|
||||
|
||||
function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'CylinderBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radiusTop: radiusTop,
|
||||
radiusBottom: radiusBottom,
|
||||
height: height,
|
||||
radialSegments: radialSegments,
|
||||
heightSegments: heightSegments,
|
||||
openEnded: openEnded,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
var scope = this;
|
||||
|
||||
radiusTop = radiusTop !== undefined ? radiusTop : 1;
|
||||
radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
|
||||
height = height || 1;
|
||||
|
||||
radialSegments = Math.floor( radialSegments ) || 8;
|
||||
heightSegments = Math.floor( heightSegments ) || 1;
|
||||
|
||||
openEnded = openEnded !== undefined ? openEnded : false;
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var index = 0;
|
||||
var indexArray = [];
|
||||
var halfHeight = height / 2;
|
||||
var groupStart = 0;
|
||||
|
||||
// generate geometry
|
||||
|
||||
generateTorso();
|
||||
|
||||
if ( openEnded === false ) {
|
||||
|
||||
if ( radiusTop > 0 ) generateCap( true );
|
||||
if ( radiusBottom > 0 ) generateCap( false );
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
function generateTorso() {
|
||||
|
||||
var x, y;
|
||||
var normal = new Vector3();
|
||||
var vertex = new Vector3();
|
||||
|
||||
var groupCount = 0;
|
||||
|
||||
// this will be used to calculate the normal
|
||||
var slope = ( radiusBottom - radiusTop ) / height;
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( y = 0; y <= heightSegments; y ++ ) {
|
||||
|
||||
var indexRow = [];
|
||||
|
||||
var v = y / heightSegments;
|
||||
|
||||
// calculate the radius of the current row
|
||||
|
||||
var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
|
||||
|
||||
for ( x = 0; x <= radialSegments; x ++ ) {
|
||||
|
||||
var u = x / radialSegments;
|
||||
|
||||
var theta = u * thetaLength + thetaStart;
|
||||
|
||||
var sinTheta = Math.sin( theta );
|
||||
var cosTheta = Math.cos( theta );
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = radius * sinTheta;
|
||||
vertex.y = - v * height + halfHeight;
|
||||
vertex.z = radius * cosTheta;
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
normal.set( sinTheta, slope, cosTheta ).normalize();
|
||||
normals.push( normal.x, normal.y, normal.z );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( u, 1 - v );
|
||||
|
||||
// save index of vertex in respective row
|
||||
|
||||
indexRow.push( index ++ );
|
||||
|
||||
}
|
||||
|
||||
// now save vertices of the row in our index array
|
||||
|
||||
indexArray.push( indexRow );
|
||||
|
||||
}
|
||||
|
||||
// generate indices
|
||||
|
||||
for ( x = 0; x < radialSegments; x ++ ) {
|
||||
|
||||
for ( y = 0; y < heightSegments; y ++ ) {
|
||||
|
||||
// we use the index array to access the correct indices
|
||||
|
||||
var a = indexArray[ y ][ x ];
|
||||
var b = indexArray[ y + 1 ][ x ];
|
||||
var c = indexArray[ y + 1 ][ x + 1 ];
|
||||
var d = indexArray[ y ][ x + 1 ];
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
// update group counter
|
||||
|
||||
groupCount += 6;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add a group to the geometry. this will ensure multi material support
|
||||
|
||||
scope.addGroup( groupStart, groupCount, 0 );
|
||||
|
||||
// calculate new start value for groups
|
||||
|
||||
groupStart += groupCount;
|
||||
|
||||
}
|
||||
|
||||
function generateCap( top ) {
|
||||
|
||||
var x, centerIndexStart, centerIndexEnd;
|
||||
|
||||
var uv = new Vector2();
|
||||
var vertex = new Vector3();
|
||||
|
||||
var groupCount = 0;
|
||||
|
||||
var radius = ( top === true ) ? radiusTop : radiusBottom;
|
||||
var sign = ( top === true ) ? 1 : - 1;
|
||||
|
||||
// save the index of the first center vertex
|
||||
centerIndexStart = index;
|
||||
|
||||
// first we generate the center vertex data of the cap.
|
||||
// because the geometry needs one set of uvs per face,
|
||||
// we must generate a center vertex per face/segment
|
||||
|
||||
for ( x = 1; x <= radialSegments; x ++ ) {
|
||||
|
||||
// vertex
|
||||
|
||||
vertices.push( 0, halfHeight * sign, 0 );
|
||||
|
||||
// normal
|
||||
|
||||
normals.push( 0, sign, 0 );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( 0.5, 0.5 );
|
||||
|
||||
// increase index
|
||||
|
||||
index ++;
|
||||
|
||||
}
|
||||
|
||||
// save the index of the last center vertex
|
||||
|
||||
centerIndexEnd = index;
|
||||
|
||||
// now we generate the surrounding vertices, normals and uvs
|
||||
|
||||
for ( x = 0; x <= radialSegments; x ++ ) {
|
||||
|
||||
var u = x / radialSegments;
|
||||
var theta = u * thetaLength + thetaStart;
|
||||
|
||||
var cosTheta = Math.cos( theta );
|
||||
var sinTheta = Math.sin( theta );
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = radius * sinTheta;
|
||||
vertex.y = halfHeight * sign;
|
||||
vertex.z = radius * cosTheta;
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
normals.push( 0, sign, 0 );
|
||||
|
||||
// uv
|
||||
|
||||
uv.x = ( cosTheta * 0.5 ) + 0.5;
|
||||
uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
|
||||
uvs.push( uv.x, uv.y );
|
||||
|
||||
// increase index
|
||||
|
||||
index ++;
|
||||
|
||||
}
|
||||
|
||||
// generate indices
|
||||
|
||||
for ( x = 0; x < radialSegments; x ++ ) {
|
||||
|
||||
var c = centerIndexStart + x;
|
||||
var i = centerIndexEnd + x;
|
||||
|
||||
if ( top === true ) {
|
||||
|
||||
// face top
|
||||
|
||||
indices.push( i, i + 1, c );
|
||||
|
||||
} else {
|
||||
|
||||
// face bottom
|
||||
|
||||
indices.push( i + 1, i, c );
|
||||
|
||||
}
|
||||
|
||||
groupCount += 3;
|
||||
|
||||
}
|
||||
|
||||
// add a group to the geometry. this will ensure multi material support
|
||||
|
||||
scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
|
||||
|
||||
// calculate new start value for groups
|
||||
|
||||
groupStart += groupCount;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
|
||||
|
||||
|
||||
export { CylinderGeometry, CylinderBufferGeometry };
|
88
lib/geometries/DodecahedronGeometry.js
Normal file
88
lib/geometries/DodecahedronGeometry.js
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @author Abe Pazos / https://hamoid.com
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { PolyhedronBufferGeometry } from './PolyhedronGeometry.js';
|
||||
|
||||
// DodecahedronGeometry
|
||||
|
||||
function DodecahedronGeometry( radius, detail ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'DodecahedronGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
|
||||
DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
|
||||
|
||||
// DodecahedronBufferGeometry
|
||||
|
||||
function DodecahedronBufferGeometry( radius, detail ) {
|
||||
|
||||
var t = ( 1 + Math.sqrt( 5 ) ) / 2;
|
||||
var r = 1 / t;
|
||||
|
||||
var vertices = [
|
||||
|
||||
// (±1, ±1, ±1)
|
||||
- 1, - 1, - 1, - 1, - 1, 1,
|
||||
- 1, 1, - 1, - 1, 1, 1,
|
||||
1, - 1, - 1, 1, - 1, 1,
|
||||
1, 1, - 1, 1, 1, 1,
|
||||
|
||||
// (0, ±1/φ, ±φ)
|
||||
0, - r, - t, 0, - r, t,
|
||||
0, r, - t, 0, r, t,
|
||||
|
||||
// (±1/φ, ±φ, 0)
|
||||
- r, - t, 0, - r, t, 0,
|
||||
r, - t, 0, r, t, 0,
|
||||
|
||||
// (±φ, 0, ±1/φ)
|
||||
- t, 0, - r, t, 0, - r,
|
||||
- t, 0, r, t, 0, r
|
||||
];
|
||||
|
||||
var indices = [
|
||||
3, 11, 7, 3, 7, 15, 3, 15, 13,
|
||||
7, 19, 17, 7, 17, 6, 7, 6, 15,
|
||||
17, 4, 8, 17, 8, 10, 17, 10, 6,
|
||||
8, 0, 16, 8, 16, 2, 8, 2, 10,
|
||||
0, 12, 1, 0, 1, 18, 0, 18, 16,
|
||||
6, 10, 2, 6, 2, 13, 6, 13, 15,
|
||||
2, 16, 18, 2, 18, 3, 2, 3, 13,
|
||||
18, 1, 9, 18, 9, 11, 18, 11, 3,
|
||||
4, 14, 12, 4, 12, 0, 4, 0, 8,
|
||||
11, 9, 5, 11, 5, 19, 11, 19, 7,
|
||||
19, 5, 14, 19, 14, 4, 19, 4, 17,
|
||||
1, 12, 14, 1, 14, 5, 1, 5, 9
|
||||
];
|
||||
|
||||
PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
this.type = 'DodecahedronBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
|
||||
DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
|
||||
|
||||
|
||||
export { DodecahedronGeometry, DodecahedronBufferGeometry };
|
113
lib/geometries/EdgesGeometry.js
Normal file
113
lib/geometries/EdgesGeometry.js
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { _Math } from '../math/Math.js';
|
||||
|
||||
function EdgesGeometry( geometry, thresholdAngle ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'EdgesGeometry';
|
||||
|
||||
this.parameters = {
|
||||
thresholdAngle: thresholdAngle
|
||||
};
|
||||
|
||||
thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
|
||||
|
||||
// buffer
|
||||
|
||||
var vertices = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
|
||||
var edge = [ 0, 0 ], edges = {}, edge1, edge2;
|
||||
var key, keys = [ 'a', 'b', 'c' ];
|
||||
|
||||
// prepare source geometry
|
||||
|
||||
var geometry2;
|
||||
|
||||
if ( geometry.isBufferGeometry ) {
|
||||
|
||||
geometry2 = new Geometry();
|
||||
geometry2.fromBufferGeometry( geometry );
|
||||
|
||||
} else {
|
||||
|
||||
geometry2 = geometry.clone();
|
||||
|
||||
}
|
||||
|
||||
geometry2.mergeVertices();
|
||||
geometry2.computeFaceNormals();
|
||||
|
||||
var sourceVertices = geometry2.vertices;
|
||||
var faces = geometry2.faces;
|
||||
|
||||
// now create a data structure where each entry represents an edge with its adjoining faces
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge1 = face[ keys[ j ] ];
|
||||
edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
|
||||
edge[ 0 ] = Math.min( edge1, edge2 );
|
||||
edge[ 1 ] = Math.max( edge1, edge2 );
|
||||
|
||||
key = edge[ 0 ] + ',' + edge[ 1 ];
|
||||
|
||||
if ( edges[ key ] === undefined ) {
|
||||
|
||||
edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
|
||||
|
||||
} else {
|
||||
|
||||
edges[ key ].face2 = i;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate vertices
|
||||
|
||||
for ( key in edges ) {
|
||||
|
||||
var e = edges[ key ];
|
||||
|
||||
// an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
|
||||
|
||||
if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
|
||||
|
||||
var vertex = sourceVertices[ e.index1 ];
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
vertex = sourceVertices[ e.index2 ];
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
|
||||
}
|
||||
|
||||
EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
EdgesGeometry.prototype.constructor = EdgesGeometry;
|
||||
|
||||
|
||||
export { EdgesGeometry };
|
832
lib/geometries/ExtrudeGeometry.js
Normal file
832
lib/geometries/ExtrudeGeometry.js
Normal file
@ -0,0 +1,832 @@
|
||||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
*
|
||||
* Creates extruded geometry from a path shape.
|
||||
*
|
||||
* parameters = {
|
||||
*
|
||||
* curveSegments: <int>, // number of points on the curves
|
||||
* steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
|
||||
* depth: <float>, // Depth to extrude the shape
|
||||
*
|
||||
* bevelEnabled: <bool>, // turn on bevel
|
||||
* bevelThickness: <float>, // how deep into the original shape bevel goes
|
||||
* bevelSize: <float>, // how far from shape outline is bevel
|
||||
* bevelSegments: <int>, // number of bevel layers
|
||||
*
|
||||
* extrudePath: <THREE.Curve> // curve to extrude shape along
|
||||
*
|
||||
* UVGenerator: <Object> // object that provides UV generator functions
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { ShapeUtils } from '../extras/ShapeUtils.js';
|
||||
|
||||
// ExtrudeGeometry
|
||||
|
||||
function ExtrudeGeometry( shapes, options ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'ExtrudeGeometry';
|
||||
|
||||
this.parameters = {
|
||||
shapes: shapes,
|
||||
options: options
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
|
||||
ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
|
||||
|
||||
ExtrudeGeometry.prototype.toJSON = function () {
|
||||
|
||||
var data = Geometry.prototype.toJSON.call( this );
|
||||
|
||||
var shapes = this.parameters.shapes;
|
||||
var options = this.parameters.options;
|
||||
|
||||
return toJSON( shapes, options, data );
|
||||
|
||||
};
|
||||
|
||||
// ExtrudeBufferGeometry
|
||||
|
||||
function ExtrudeBufferGeometry( shapes, options ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'ExtrudeBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
shapes: shapes,
|
||||
options: options
|
||||
};
|
||||
|
||||
shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
|
||||
|
||||
var scope = this;
|
||||
|
||||
var verticesArray = [];
|
||||
var uvArray = [];
|
||||
|
||||
for ( var i = 0, l = shapes.length; i < l; i ++ ) {
|
||||
|
||||
var shape = shapes[ i ];
|
||||
addShape( shape );
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
|
||||
|
||||
this.computeVertexNormals();
|
||||
|
||||
// functions
|
||||
|
||||
function addShape( shape ) {
|
||||
|
||||
var placeholder = [];
|
||||
|
||||
// options
|
||||
|
||||
var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
|
||||
var steps = options.steps !== undefined ? options.steps : 1;
|
||||
var depth = options.depth !== undefined ? options.depth : 100;
|
||||
|
||||
var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
|
||||
var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
|
||||
var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
|
||||
var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
|
||||
|
||||
var extrudePath = options.extrudePath;
|
||||
|
||||
var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
|
||||
|
||||
// deprecated options
|
||||
|
||||
if ( options.amount !== undefined ) {
|
||||
|
||||
console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
|
||||
depth = options.amount;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var extrudePts, extrudeByPath = false;
|
||||
var splineTube, binormal, normal, position2;
|
||||
|
||||
if ( extrudePath ) {
|
||||
|
||||
extrudePts = extrudePath.getSpacedPoints( steps );
|
||||
|
||||
extrudeByPath = true;
|
||||
bevelEnabled = false; // bevels not supported for path extrusion
|
||||
|
||||
// SETUP TNB variables
|
||||
|
||||
// TODO1 - have a .isClosed in spline?
|
||||
|
||||
splineTube = extrudePath.computeFrenetFrames( steps, false );
|
||||
|
||||
// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
|
||||
|
||||
binormal = new Vector3();
|
||||
normal = new Vector3();
|
||||
position2 = new Vector3();
|
||||
|
||||
}
|
||||
|
||||
// Safeguards if bevels are not enabled
|
||||
|
||||
if ( ! bevelEnabled ) {
|
||||
|
||||
bevelSegments = 0;
|
||||
bevelThickness = 0;
|
||||
bevelSize = 0;
|
||||
|
||||
}
|
||||
|
||||
// Variables initialization
|
||||
|
||||
var ahole, h, hl; // looping of holes
|
||||
|
||||
var shapePoints = shape.extractPoints( curveSegments );
|
||||
|
||||
var vertices = shapePoints.shape;
|
||||
var holes = shapePoints.holes;
|
||||
|
||||
var reverse = ! ShapeUtils.isClockWise( vertices );
|
||||
|
||||
if ( reverse ) {
|
||||
|
||||
vertices = vertices.reverse();
|
||||
|
||||
// Maybe we should also check if holes are in the opposite direction, just to be safe ...
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
if ( ShapeUtils.isClockWise( ahole ) ) {
|
||||
|
||||
holes[ h ] = ahole.reverse();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
var faces = ShapeUtils.triangulateShape( vertices, holes );
|
||||
|
||||
/* Vertices */
|
||||
|
||||
var contour = vertices; // vertices has all points but contour has only points of circumference
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
vertices = vertices.concat( ahole );
|
||||
|
||||
}
|
||||
|
||||
|
||||
function scalePt2( pt, vec, size ) {
|
||||
|
||||
if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
|
||||
|
||||
return vec.clone().multiplyScalar( size ).add( pt );
|
||||
|
||||
}
|
||||
|
||||
var b, bs, t, z,
|
||||
vert, vlen = vertices.length,
|
||||
face, flen = faces.length;
|
||||
|
||||
|
||||
// Find directions for point movement
|
||||
|
||||
|
||||
function getBevelVec( inPt, inPrev, inNext ) {
|
||||
|
||||
// computes for inPt the corresponding point inPt' on a new contour
|
||||
// shifted by 1 unit (length of normalized vector) to the left
|
||||
// if we walk along contour clockwise, this new contour is outside the old one
|
||||
//
|
||||
// inPt' is the intersection of the two lines parallel to the two
|
||||
// adjacent edges of inPt at a distance of 1 unit on the left side.
|
||||
|
||||
var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
|
||||
|
||||
// good reading for geometry algorithms (here: line-line intersection)
|
||||
// http://geomalgorithms.com/a05-_intersect-1.html
|
||||
|
||||
var v_prev_x = inPt.x - inPrev.x,
|
||||
v_prev_y = inPt.y - inPrev.y;
|
||||
var v_next_x = inNext.x - inPt.x,
|
||||
v_next_y = inNext.y - inPt.y;
|
||||
|
||||
var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
|
||||
|
||||
// check for collinear edges
|
||||
var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
|
||||
|
||||
if ( Math.abs( collinear0 ) > Number.EPSILON ) {
|
||||
|
||||
// not collinear
|
||||
|
||||
// length of vectors for normalizing
|
||||
|
||||
var v_prev_len = Math.sqrt( v_prev_lensq );
|
||||
var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
|
||||
|
||||
// shift adjacent points by unit vectors to the left
|
||||
|
||||
var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
|
||||
var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
|
||||
|
||||
var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
|
||||
var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
|
||||
|
||||
// scaling factor for v_prev to intersection point
|
||||
|
||||
var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
|
||||
( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
|
||||
( v_prev_x * v_next_y - v_prev_y * v_next_x );
|
||||
|
||||
// vector from inPt to intersection point
|
||||
|
||||
v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
|
||||
v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
|
||||
|
||||
// Don't normalize!, otherwise sharp corners become ugly
|
||||
// but prevent crazy spikes
|
||||
var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
|
||||
if ( v_trans_lensq <= 2 ) {
|
||||
|
||||
return new Vector2( v_trans_x, v_trans_y );
|
||||
|
||||
} else {
|
||||
|
||||
shrink_by = Math.sqrt( v_trans_lensq / 2 );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// handle special case of collinear edges
|
||||
|
||||
var direction_eq = false; // assumes: opposite
|
||||
if ( v_prev_x > Number.EPSILON ) {
|
||||
|
||||
if ( v_next_x > Number.EPSILON ) {
|
||||
|
||||
direction_eq = true;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( v_prev_x < - Number.EPSILON ) {
|
||||
|
||||
if ( v_next_x < - Number.EPSILON ) {
|
||||
|
||||
direction_eq = true;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
|
||||
|
||||
direction_eq = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( direction_eq ) {
|
||||
|
||||
// console.log("Warning: lines are a straight sequence");
|
||||
v_trans_x = - v_prev_y;
|
||||
v_trans_y = v_prev_x;
|
||||
shrink_by = Math.sqrt( v_prev_lensq );
|
||||
|
||||
} else {
|
||||
|
||||
// console.log("Warning: lines are a straight spike");
|
||||
v_trans_x = v_prev_x;
|
||||
v_trans_y = v_prev_y;
|
||||
shrink_by = Math.sqrt( v_prev_lensq / 2 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
|
||||
|
||||
}
|
||||
|
||||
|
||||
var contourMovements = [];
|
||||
|
||||
for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
||||
|
||||
if ( j === il ) j = 0;
|
||||
if ( k === il ) k = 0;
|
||||
|
||||
// (j)---(i)---(k)
|
||||
// console.log('i,j,k', i, j , k)
|
||||
|
||||
contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
|
||||
|
||||
}
|
||||
|
||||
var holesMovements = [],
|
||||
oneHoleMovements, verticesMovements = contourMovements.concat();
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
oneHoleMovements = [];
|
||||
|
||||
for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
||||
|
||||
if ( j === il ) j = 0;
|
||||
if ( k === il ) k = 0;
|
||||
|
||||
// (j)---(i)---(k)
|
||||
oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
|
||||
|
||||
}
|
||||
|
||||
holesMovements.push( oneHoleMovements );
|
||||
verticesMovements = verticesMovements.concat( oneHoleMovements );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Loop bevelSegments, 1 for the front, 1 for the back
|
||||
|
||||
for ( b = 0; b < bevelSegments; b ++ ) {
|
||||
|
||||
//for ( b = bevelSegments; b > 0; b -- ) {
|
||||
|
||||
t = b / bevelSegments;
|
||||
z = bevelThickness * Math.cos( t * Math.PI / 2 );
|
||||
bs = bevelSize * Math.sin( t * Math.PI / 2 );
|
||||
|
||||
// contract shape
|
||||
|
||||
for ( i = 0, il = contour.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
||||
|
||||
v( vert.x, vert.y, - z );
|
||||
|
||||
}
|
||||
|
||||
// expand holes
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
oneHoleMovements = holesMovements[ h ];
|
||||
|
||||
for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
||||
|
||||
v( vert.x, vert.y, - z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bs = bevelSize;
|
||||
|
||||
// Back facing vertices
|
||||
|
||||
for ( i = 0; i < vlen; i ++ ) {
|
||||
|
||||
vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, 0 );
|
||||
|
||||
} else {
|
||||
|
||||
// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
|
||||
|
||||
normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
|
||||
binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
|
||||
|
||||
position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
|
||||
|
||||
v( position2.x, position2.y, position2.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add stepped vertices...
|
||||
// Including front facing vertices
|
||||
|
||||
var s;
|
||||
|
||||
for ( s = 1; s <= steps; s ++ ) {
|
||||
|
||||
for ( i = 0; i < vlen; i ++ ) {
|
||||
|
||||
vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, depth / steps * s );
|
||||
|
||||
} else {
|
||||
|
||||
// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
|
||||
|
||||
normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
|
||||
binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
|
||||
|
||||
position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
|
||||
|
||||
v( position2.x, position2.y, position2.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Add bevel segments planes
|
||||
|
||||
//for ( b = 1; b <= bevelSegments; b ++ ) {
|
||||
for ( b = bevelSegments - 1; b >= 0; b -- ) {
|
||||
|
||||
t = b / bevelSegments;
|
||||
z = bevelThickness * Math.cos( t * Math.PI / 2 );
|
||||
bs = bevelSize * Math.sin( t * Math.PI / 2 );
|
||||
|
||||
// contract shape
|
||||
|
||||
for ( i = 0, il = contour.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
||||
v( vert.x, vert.y, depth + z );
|
||||
|
||||
}
|
||||
|
||||
// expand holes
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
oneHoleMovements = holesMovements[ h ];
|
||||
|
||||
for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, depth + z );
|
||||
|
||||
} else {
|
||||
|
||||
v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Faces */
|
||||
|
||||
// Top and bottom faces
|
||||
|
||||
buildLidFaces();
|
||||
|
||||
// Sides faces
|
||||
|
||||
buildSideFaces();
|
||||
|
||||
|
||||
///// Internal functions
|
||||
|
||||
function buildLidFaces() {
|
||||
|
||||
var start = verticesArray.length / 3;
|
||||
|
||||
if ( bevelEnabled ) {
|
||||
|
||||
var layer = 0; // steps + 1
|
||||
var offset = vlen * layer;
|
||||
|
||||
// Bottom faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
|
||||
|
||||
}
|
||||
|
||||
layer = steps + bevelSegments * 2;
|
||||
offset = vlen * layer;
|
||||
|
||||
// Top faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Bottom faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 2 ], face[ 1 ], face[ 0 ] );
|
||||
|
||||
}
|
||||
|
||||
// Top faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scope.addGroup( start, verticesArray.length / 3 - start, 0 );
|
||||
|
||||
}
|
||||
|
||||
// Create faces for the z-sides of the shape
|
||||
|
||||
function buildSideFaces() {
|
||||
|
||||
var start = verticesArray.length / 3;
|
||||
var layeroffset = 0;
|
||||
sidewalls( contour, layeroffset );
|
||||
layeroffset += contour.length;
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
sidewalls( ahole, layeroffset );
|
||||
|
||||
//, true
|
||||
layeroffset += ahole.length;
|
||||
|
||||
}
|
||||
|
||||
|
||||
scope.addGroup( start, verticesArray.length / 3 - start, 1 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
function sidewalls( contour, layeroffset ) {
|
||||
|
||||
var j, k;
|
||||
i = contour.length;
|
||||
|
||||
while ( -- i >= 0 ) {
|
||||
|
||||
j = i;
|
||||
k = i - 1;
|
||||
if ( k < 0 ) k = contour.length - 1;
|
||||
|
||||
//console.log('b', i,j, i-1, k,vertices.length);
|
||||
|
||||
var s = 0,
|
||||
sl = steps + bevelSegments * 2;
|
||||
|
||||
for ( s = 0; s < sl; s ++ ) {
|
||||
|
||||
var slen1 = vlen * s;
|
||||
var slen2 = vlen * ( s + 1 );
|
||||
|
||||
var a = layeroffset + j + slen1,
|
||||
b = layeroffset + k + slen1,
|
||||
c = layeroffset + k + slen2,
|
||||
d = layeroffset + j + slen2;
|
||||
|
||||
f4( a, b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function v( x, y, z ) {
|
||||
|
||||
placeholder.push( x );
|
||||
placeholder.push( y );
|
||||
placeholder.push( z );
|
||||
|
||||
}
|
||||
|
||||
|
||||
function f3( a, b, c ) {
|
||||
|
||||
addVertex( a );
|
||||
addVertex( b );
|
||||
addVertex( c );
|
||||
|
||||
var nextIndex = verticesArray.length / 3;
|
||||
var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
|
||||
|
||||
addUV( uvs[ 0 ] );
|
||||
addUV( uvs[ 1 ] );
|
||||
addUV( uvs[ 2 ] );
|
||||
|
||||
}
|
||||
|
||||
function f4( a, b, c, d ) {
|
||||
|
||||
addVertex( a );
|
||||
addVertex( b );
|
||||
addVertex( d );
|
||||
|
||||
addVertex( b );
|
||||
addVertex( c );
|
||||
addVertex( d );
|
||||
|
||||
|
||||
var nextIndex = verticesArray.length / 3;
|
||||
var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
|
||||
|
||||
addUV( uvs[ 0 ] );
|
||||
addUV( uvs[ 1 ] );
|
||||
addUV( uvs[ 3 ] );
|
||||
|
||||
addUV( uvs[ 1 ] );
|
||||
addUV( uvs[ 2 ] );
|
||||
addUV( uvs[ 3 ] );
|
||||
|
||||
}
|
||||
|
||||
function addVertex( index ) {
|
||||
|
||||
verticesArray.push( placeholder[ index * 3 + 0 ] );
|
||||
verticesArray.push( placeholder[ index * 3 + 1 ] );
|
||||
verticesArray.push( placeholder[ index * 3 + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
function addUV( vector2 ) {
|
||||
|
||||
uvArray.push( vector2.x );
|
||||
uvArray.push( vector2.y );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
|
||||
|
||||
ExtrudeBufferGeometry.prototype.toJSON = function () {
|
||||
|
||||
var data = BufferGeometry.prototype.toJSON.call( this );
|
||||
|
||||
var shapes = this.parameters.shapes;
|
||||
var options = this.parameters.options;
|
||||
|
||||
return toJSON( shapes, options, data );
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
var WorldUVGenerator = {
|
||||
|
||||
generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
|
||||
|
||||
var a_x = vertices[ indexA * 3 ];
|
||||
var a_y = vertices[ indexA * 3 + 1 ];
|
||||
var b_x = vertices[ indexB * 3 ];
|
||||
var b_y = vertices[ indexB * 3 + 1 ];
|
||||
var c_x = vertices[ indexC * 3 ];
|
||||
var c_y = vertices[ indexC * 3 + 1 ];
|
||||
|
||||
return [
|
||||
new Vector2( a_x, a_y ),
|
||||
new Vector2( b_x, b_y ),
|
||||
new Vector2( c_x, c_y )
|
||||
];
|
||||
|
||||
},
|
||||
|
||||
generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
|
||||
|
||||
var a_x = vertices[ indexA * 3 ];
|
||||
var a_y = vertices[ indexA * 3 + 1 ];
|
||||
var a_z = vertices[ indexA * 3 + 2 ];
|
||||
var b_x = vertices[ indexB * 3 ];
|
||||
var b_y = vertices[ indexB * 3 + 1 ];
|
||||
var b_z = vertices[ indexB * 3 + 2 ];
|
||||
var c_x = vertices[ indexC * 3 ];
|
||||
var c_y = vertices[ indexC * 3 + 1 ];
|
||||
var c_z = vertices[ indexC * 3 + 2 ];
|
||||
var d_x = vertices[ indexD * 3 ];
|
||||
var d_y = vertices[ indexD * 3 + 1 ];
|
||||
var d_z = vertices[ indexD * 3 + 2 ];
|
||||
|
||||
if ( Math.abs( a_y - b_y ) < 0.01 ) {
|
||||
|
||||
return [
|
||||
new Vector2( a_x, 1 - a_z ),
|
||||
new Vector2( b_x, 1 - b_z ),
|
||||
new Vector2( c_x, 1 - c_z ),
|
||||
new Vector2( d_x, 1 - d_z )
|
||||
];
|
||||
|
||||
} else {
|
||||
|
||||
return [
|
||||
new Vector2( a_y, 1 - a_z ),
|
||||
new Vector2( b_y, 1 - b_z ),
|
||||
new Vector2( c_y, 1 - c_z ),
|
||||
new Vector2( d_y, 1 - d_z )
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function toJSON( shapes, options, data ) {
|
||||
|
||||
//
|
||||
|
||||
data.shapes = [];
|
||||
|
||||
if ( Array.isArray( shapes ) ) {
|
||||
|
||||
for ( var i = 0, l = shapes.length; i < l; i ++ ) {
|
||||
|
||||
var shape = shapes[ i ];
|
||||
|
||||
data.shapes.push( shape.uuid );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
data.shapes.push( shapes.uuid );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export { ExtrudeGeometry, ExtrudeBufferGeometry };
|
22
lib/geometries/Geometries.js
Normal file
22
lib/geometries/Geometries.js
Normal file
@ -0,0 +1,22 @@
|
||||
export { WireframeGeometry } from './WireframeGeometry.js';
|
||||
export { ParametricGeometry, ParametricBufferGeometry } from './ParametricGeometry.js';
|
||||
export { TetrahedronGeometry, TetrahedronBufferGeometry } from './TetrahedronGeometry.js';
|
||||
export { OctahedronGeometry, OctahedronBufferGeometry } from './OctahedronGeometry.js';
|
||||
export { IcosahedronGeometry, IcosahedronBufferGeometry } from './IcosahedronGeometry.js';
|
||||
export { DodecahedronGeometry, DodecahedronBufferGeometry } from './DodecahedronGeometry.js';
|
||||
export { PolyhedronGeometry, PolyhedronBufferGeometry } from './PolyhedronGeometry.js';
|
||||
export { TubeGeometry, TubeBufferGeometry } from './TubeGeometry.js';
|
||||
export { TorusKnotGeometry, TorusKnotBufferGeometry } from './TorusKnotGeometry.js';
|
||||
export { TorusGeometry, TorusBufferGeometry } from './TorusGeometry.js';
|
||||
export { TextGeometry, TextBufferGeometry } from './TextGeometry.js';
|
||||
export { SphereGeometry, SphereBufferGeometry } from './SphereGeometry.js';
|
||||
export { RingGeometry, RingBufferGeometry } from './RingGeometry.js';
|
||||
export { PlaneGeometry, PlaneBufferGeometry } from './PlaneGeometry.js';
|
||||
export { LatheGeometry, LatheBufferGeometry } from './LatheGeometry.js';
|
||||
export { ShapeGeometry, ShapeBufferGeometry } from './ShapeGeometry.js';
|
||||
export { ExtrudeGeometry, ExtrudeBufferGeometry } from './ExtrudeGeometry.js';
|
||||
export { EdgesGeometry } from './EdgesGeometry.js';
|
||||
export { ConeGeometry, ConeBufferGeometry } from './ConeGeometry.js';
|
||||
export { CylinderGeometry, CylinderBufferGeometry } from './CylinderGeometry.js';
|
||||
export { CircleGeometry, CircleBufferGeometry } from './CircleGeometry.js';
|
||||
export { BoxGeometry, BoxBufferGeometry } from './BoxGeometry.js';
|
64
lib/geometries/IcosahedronGeometry.js
Normal file
64
lib/geometries/IcosahedronGeometry.js
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { PolyhedronBufferGeometry } from './PolyhedronGeometry.js';
|
||||
|
||||
// IcosahedronGeometry
|
||||
|
||||
function IcosahedronGeometry( radius, detail ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'IcosahedronGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
|
||||
IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
|
||||
|
||||
// IcosahedronBufferGeometry
|
||||
|
||||
function IcosahedronBufferGeometry( radius, detail ) {
|
||||
|
||||
var t = ( 1 + Math.sqrt( 5 ) ) / 2;
|
||||
|
||||
var vertices = [
|
||||
- 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
|
||||
0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
|
||||
t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
|
||||
1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
|
||||
3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
|
||||
4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
|
||||
];
|
||||
|
||||
PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
this.type = 'IcosahedronBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
|
||||
IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
|
||||
|
||||
|
||||
export { IcosahedronGeometry, IcosahedronBufferGeometry };
|
186
lib/geometries/LatheGeometry.js
Normal file
186
lib/geometries/LatheGeometry.js
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* @author bhouston / http://clara.io
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { _Math } from '../math/Math.js';
|
||||
|
||||
// LatheGeometry
|
||||
|
||||
function LatheGeometry( points, segments, phiStart, phiLength ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'LatheGeometry';
|
||||
|
||||
this.parameters = {
|
||||
points: points,
|
||||
segments: segments,
|
||||
phiStart: phiStart,
|
||||
phiLength: phiLength
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
LatheGeometry.prototype = Object.create( Geometry.prototype );
|
||||
LatheGeometry.prototype.constructor = LatheGeometry;
|
||||
|
||||
// LatheBufferGeometry
|
||||
|
||||
function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'LatheBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
points: points,
|
||||
segments: segments,
|
||||
phiStart: phiStart,
|
||||
phiLength: phiLength
|
||||
};
|
||||
|
||||
segments = Math.floor( segments ) || 12;
|
||||
phiStart = phiStart || 0;
|
||||
phiLength = phiLength || Math.PI * 2;
|
||||
|
||||
// clamp phiLength so it's in range of [ 0, 2PI ]
|
||||
|
||||
phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
|
||||
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var base;
|
||||
var inverseSegments = 1.0 / segments;
|
||||
var vertex = new Vector3();
|
||||
var uv = new Vector2();
|
||||
var i, j;
|
||||
|
||||
// generate vertices and uvs
|
||||
|
||||
for ( i = 0; i <= segments; i ++ ) {
|
||||
|
||||
var phi = phiStart + i * inverseSegments * phiLength;
|
||||
|
||||
var sin = Math.sin( phi );
|
||||
var cos = Math.cos( phi );
|
||||
|
||||
for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = points[ j ].x * sin;
|
||||
vertex.y = points[ j ].y;
|
||||
vertex.z = points[ j ].x * cos;
|
||||
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// uv
|
||||
|
||||
uv.x = i / segments;
|
||||
uv.y = j / ( points.length - 1 );
|
||||
|
||||
uvs.push( uv.x, uv.y );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for ( i = 0; i < segments; i ++ ) {
|
||||
|
||||
for ( j = 0; j < ( points.length - 1 ); j ++ ) {
|
||||
|
||||
base = j + i * points.length;
|
||||
|
||||
var a = base;
|
||||
var b = base + points.length;
|
||||
var c = base + points.length + 1;
|
||||
var d = base + 1;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
// generate normals
|
||||
|
||||
this.computeVertexNormals();
|
||||
|
||||
// if the geometry is closed, we need to average the normals along the seam.
|
||||
// because the corresponding vertices are identical (but still have different UVs).
|
||||
|
||||
if ( phiLength === Math.PI * 2 ) {
|
||||
|
||||
var normals = this.attributes.normal.array;
|
||||
var n1 = new Vector3();
|
||||
var n2 = new Vector3();
|
||||
var n = new Vector3();
|
||||
|
||||
// this is the buffer offset for the last line of vertices
|
||||
|
||||
base = segments * points.length * 3;
|
||||
|
||||
for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
|
||||
|
||||
// select the normal of the vertex in the first line
|
||||
|
||||
n1.x = normals[ j + 0 ];
|
||||
n1.y = normals[ j + 1 ];
|
||||
n1.z = normals[ j + 2 ];
|
||||
|
||||
// select the normal of the vertex in the last line
|
||||
|
||||
n2.x = normals[ base + j + 0 ];
|
||||
n2.y = normals[ base + j + 1 ];
|
||||
n2.z = normals[ base + j + 2 ];
|
||||
|
||||
// average normals
|
||||
|
||||
n.addVectors( n1, n2 ).normalize();
|
||||
|
||||
// assign the new values to both normals
|
||||
|
||||
normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
|
||||
normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
|
||||
normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
|
||||
|
||||
|
||||
export { LatheGeometry, LatheBufferGeometry };
|
60
lib/geometries/OctahedronGeometry.js
Normal file
60
lib/geometries/OctahedronGeometry.js
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { PolyhedronBufferGeometry } from './PolyhedronGeometry.js';
|
||||
|
||||
// OctahedronGeometry
|
||||
|
||||
function OctahedronGeometry( radius, detail ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'OctahedronGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
OctahedronGeometry.prototype = Object.create( Geometry.prototype );
|
||||
OctahedronGeometry.prototype.constructor = OctahedronGeometry;
|
||||
|
||||
// OctahedronBufferGeometry
|
||||
|
||||
function OctahedronBufferGeometry( radius, detail ) {
|
||||
|
||||
var vertices = [
|
||||
1, 0, 0, - 1, 0, 0, 0, 1, 0,
|
||||
0, - 1, 0, 0, 0, 1, 0, 0, - 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
0, 2, 4, 0, 4, 3, 0, 3, 5,
|
||||
0, 5, 2, 1, 2, 5, 1, 5, 3,
|
||||
1, 3, 4, 1, 4, 2
|
||||
];
|
||||
|
||||
PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
this.type = 'OctahedronBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
|
||||
OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
|
||||
|
||||
|
||||
export { OctahedronGeometry, OctahedronBufferGeometry };
|
163
lib/geometries/ParametricGeometry.js
Normal file
163
lib/geometries/ParametricGeometry.js
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*
|
||||
* Parametric Surfaces Geometry
|
||||
* based on the brilliant article by @prideout http://prideout.net/blog/?p=44
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// ParametricGeometry
|
||||
|
||||
function ParametricGeometry( func, slices, stacks ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'ParametricGeometry';
|
||||
|
||||
this.parameters = {
|
||||
func: func,
|
||||
slices: slices,
|
||||
stacks: stacks
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
ParametricGeometry.prototype = Object.create( Geometry.prototype );
|
||||
ParametricGeometry.prototype.constructor = ParametricGeometry;
|
||||
|
||||
// ParametricBufferGeometry
|
||||
|
||||
function ParametricBufferGeometry( func, slices, stacks ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'ParametricBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
func: func,
|
||||
slices: slices,
|
||||
stacks: stacks
|
||||
};
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
var EPS = 0.00001;
|
||||
|
||||
var normal = new Vector3();
|
||||
|
||||
var p0 = new Vector3(), p1 = new Vector3();
|
||||
var pu = new Vector3(), pv = new Vector3();
|
||||
|
||||
var i, j;
|
||||
|
||||
if ( func.length < 3 ) {
|
||||
|
||||
console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
|
||||
|
||||
}
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
var sliceCount = slices + 1;
|
||||
|
||||
for ( i = 0; i <= stacks; i ++ ) {
|
||||
|
||||
var v = i / stacks;
|
||||
|
||||
for ( j = 0; j <= slices; j ++ ) {
|
||||
|
||||
var u = j / slices;
|
||||
|
||||
// vertex
|
||||
|
||||
func( u, v, p0 );
|
||||
vertices.push( p0.x, p0.y, p0.z );
|
||||
|
||||
// normal
|
||||
|
||||
// approximate tangent vectors via finite differences
|
||||
|
||||
if ( u - EPS >= 0 ) {
|
||||
|
||||
func( u - EPS, v, p1 );
|
||||
pu.subVectors( p0, p1 );
|
||||
|
||||
} else {
|
||||
|
||||
func( u + EPS, v, p1 );
|
||||
pu.subVectors( p1, p0 );
|
||||
|
||||
}
|
||||
|
||||
if ( v - EPS >= 0 ) {
|
||||
|
||||
func( u, v - EPS, p1 );
|
||||
pv.subVectors( p0, p1 );
|
||||
|
||||
} else {
|
||||
|
||||
func( u, v + EPS, p1 );
|
||||
pv.subVectors( p1, p0 );
|
||||
|
||||
}
|
||||
|
||||
// cross product of tangent vectors returns surface normal
|
||||
|
||||
normal.crossVectors( pu, pv ).normalize();
|
||||
normals.push( normal.x, normal.y, normal.z );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( u, v );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate indices
|
||||
|
||||
for ( i = 0; i < stacks; i ++ ) {
|
||||
|
||||
for ( j = 0; j < slices; j ++ ) {
|
||||
|
||||
var a = i * sliceCount + j;
|
||||
var b = i * sliceCount + j + 1;
|
||||
var c = ( i + 1 ) * sliceCount + j + 1;
|
||||
var d = ( i + 1 ) * sliceCount + j;
|
||||
|
||||
// faces one and two
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
|
||||
|
||||
|
||||
export { ParametricGeometry, ParametricBufferGeometry };
|
126
lib/geometries/PlaneGeometry.js
Normal file
126
lib/geometries/PlaneGeometry.js
Normal file
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
|
||||
// PlaneGeometry
|
||||
|
||||
function PlaneGeometry( width, height, widthSegments, heightSegments ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'PlaneGeometry';
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
PlaneGeometry.prototype = Object.create( Geometry.prototype );
|
||||
PlaneGeometry.prototype.constructor = PlaneGeometry;
|
||||
|
||||
// PlaneBufferGeometry
|
||||
|
||||
function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'PlaneBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments
|
||||
};
|
||||
|
||||
width = width || 1;
|
||||
height = height || 1;
|
||||
|
||||
var width_half = width / 2;
|
||||
var height_half = height / 2;
|
||||
|
||||
var gridX = Math.floor( widthSegments ) || 1;
|
||||
var gridY = Math.floor( heightSegments ) || 1;
|
||||
|
||||
var gridX1 = gridX + 1;
|
||||
var gridY1 = gridY + 1;
|
||||
|
||||
var segment_width = width / gridX;
|
||||
var segment_height = height / gridY;
|
||||
|
||||
var ix, iy;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( iy = 0; iy < gridY1; iy ++ ) {
|
||||
|
||||
var y = iy * segment_height - height_half;
|
||||
|
||||
for ( ix = 0; ix < gridX1; ix ++ ) {
|
||||
|
||||
var x = ix * segment_width - width_half;
|
||||
|
||||
vertices.push( x, - y, 0 );
|
||||
|
||||
normals.push( 0, 0, 1 );
|
||||
|
||||
uvs.push( ix / gridX );
|
||||
uvs.push( 1 - ( iy / gridY ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for ( iy = 0; iy < gridY; iy ++ ) {
|
||||
|
||||
for ( ix = 0; ix < gridX; ix ++ ) {
|
||||
|
||||
var a = ix + gridX1 * iy;
|
||||
var b = ix + gridX1 * ( iy + 1 );
|
||||
var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
|
||||
var d = ( ix + 1 ) + gridX1 * iy;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
|
||||
|
||||
|
||||
export { PlaneGeometry, PlaneBufferGeometry };
|
341
lib/geometries/PolyhedronGeometry.js
Normal file
341
lib/geometries/PolyhedronGeometry.js
Normal file
@ -0,0 +1,341 @@
|
||||
/**
|
||||
* @author clockworkgeek / https://github.com/clockworkgeek
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
|
||||
// PolyhedronGeometry
|
||||
|
||||
function PolyhedronGeometry( vertices, indices, radius, detail ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'PolyhedronGeometry';
|
||||
|
||||
this.parameters = {
|
||||
vertices: vertices,
|
||||
indices: indices,
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
|
||||
PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
|
||||
|
||||
// PolyhedronBufferGeometry
|
||||
|
||||
function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'PolyhedronBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
vertices: vertices,
|
||||
indices: indices,
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
radius = radius || 1;
|
||||
detail = detail || 0;
|
||||
|
||||
// default buffer data
|
||||
|
||||
var vertexBuffer = [];
|
||||
var uvBuffer = [];
|
||||
|
||||
// the subdivision creates the vertex buffer data
|
||||
|
||||
subdivide( detail );
|
||||
|
||||
// all vertices should lie on a conceptual sphere with a given radius
|
||||
|
||||
appplyRadius( radius );
|
||||
|
||||
// finally, create the uv data
|
||||
|
||||
generateUVs();
|
||||
|
||||
// build non-indexed geometry
|
||||
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
|
||||
|
||||
if ( detail === 0 ) {
|
||||
|
||||
this.computeVertexNormals(); // flat normals
|
||||
|
||||
} else {
|
||||
|
||||
this.normalizeNormals(); // smooth normals
|
||||
|
||||
}
|
||||
|
||||
// helper functions
|
||||
|
||||
function subdivide( detail ) {
|
||||
|
||||
var a = new Vector3();
|
||||
var b = new Vector3();
|
||||
var c = new Vector3();
|
||||
|
||||
// iterate over all faces and apply a subdivison with the given detail value
|
||||
|
||||
for ( var i = 0; i < indices.length; i += 3 ) {
|
||||
|
||||
// get the vertices of the face
|
||||
|
||||
getVertexByIndex( indices[ i + 0 ], a );
|
||||
getVertexByIndex( indices[ i + 1 ], b );
|
||||
getVertexByIndex( indices[ i + 2 ], c );
|
||||
|
||||
// perform subdivision
|
||||
|
||||
subdivideFace( a, b, c, detail );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function subdivideFace( a, b, c, detail ) {
|
||||
|
||||
var cols = Math.pow( 2, detail );
|
||||
|
||||
// we use this multidimensional array as a data structure for creating the subdivision
|
||||
|
||||
var v = [];
|
||||
|
||||
var i, j;
|
||||
|
||||
// construct all of the vertices for this subdivision
|
||||
|
||||
for ( i = 0; i <= cols; i ++ ) {
|
||||
|
||||
v[ i ] = [];
|
||||
|
||||
var aj = a.clone().lerp( c, i / cols );
|
||||
var bj = b.clone().lerp( c, i / cols );
|
||||
|
||||
var rows = cols - i;
|
||||
|
||||
for ( j = 0; j <= rows; j ++ ) {
|
||||
|
||||
if ( j === 0 && i === cols ) {
|
||||
|
||||
v[ i ][ j ] = aj;
|
||||
|
||||
} else {
|
||||
|
||||
v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// construct all of the faces
|
||||
|
||||
for ( i = 0; i < cols; i ++ ) {
|
||||
|
||||
for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
|
||||
|
||||
var k = Math.floor( j / 2 );
|
||||
|
||||
if ( j % 2 === 0 ) {
|
||||
|
||||
pushVertex( v[ i ][ k + 1 ] );
|
||||
pushVertex( v[ i + 1 ][ k ] );
|
||||
pushVertex( v[ i ][ k ] );
|
||||
|
||||
} else {
|
||||
|
||||
pushVertex( v[ i ][ k + 1 ] );
|
||||
pushVertex( v[ i + 1 ][ k + 1 ] );
|
||||
pushVertex( v[ i + 1 ][ k ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function appplyRadius( radius ) {
|
||||
|
||||
var vertex = new Vector3();
|
||||
|
||||
// iterate over the entire buffer and apply the radius to each vertex
|
||||
|
||||
for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
|
||||
|
||||
vertex.x = vertexBuffer[ i + 0 ];
|
||||
vertex.y = vertexBuffer[ i + 1 ];
|
||||
vertex.z = vertexBuffer[ i + 2 ];
|
||||
|
||||
vertex.normalize().multiplyScalar( radius );
|
||||
|
||||
vertexBuffer[ i + 0 ] = vertex.x;
|
||||
vertexBuffer[ i + 1 ] = vertex.y;
|
||||
vertexBuffer[ i + 2 ] = vertex.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function generateUVs() {
|
||||
|
||||
var vertex = new Vector3();
|
||||
|
||||
for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
|
||||
|
||||
vertex.x = vertexBuffer[ i + 0 ];
|
||||
vertex.y = vertexBuffer[ i + 1 ];
|
||||
vertex.z = vertexBuffer[ i + 2 ];
|
||||
|
||||
var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
|
||||
var v = inclination( vertex ) / Math.PI + 0.5;
|
||||
uvBuffer.push( u, 1 - v );
|
||||
|
||||
}
|
||||
|
||||
correctUVs();
|
||||
|
||||
correctSeam();
|
||||
|
||||
}
|
||||
|
||||
function correctSeam() {
|
||||
|
||||
// handle case when face straddles the seam, see #3269
|
||||
|
||||
for ( var i = 0; i < uvBuffer.length; i += 6 ) {
|
||||
|
||||
// uv data of a single face
|
||||
|
||||
var x0 = uvBuffer[ i + 0 ];
|
||||
var x1 = uvBuffer[ i + 2 ];
|
||||
var x2 = uvBuffer[ i + 4 ];
|
||||
|
||||
var max = Math.max( x0, x1, x2 );
|
||||
var min = Math.min( x0, x1, x2 );
|
||||
|
||||
// 0.9 is somewhat arbitrary
|
||||
|
||||
if ( max > 0.9 && min < 0.1 ) {
|
||||
|
||||
if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
|
||||
if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
|
||||
if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function pushVertex( vertex ) {
|
||||
|
||||
vertexBuffer.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
function getVertexByIndex( index, vertex ) {
|
||||
|
||||
var stride = index * 3;
|
||||
|
||||
vertex.x = vertices[ stride + 0 ];
|
||||
vertex.y = vertices[ stride + 1 ];
|
||||
vertex.z = vertices[ stride + 2 ];
|
||||
|
||||
}
|
||||
|
||||
function correctUVs() {
|
||||
|
||||
var a = new Vector3();
|
||||
var b = new Vector3();
|
||||
var c = new Vector3();
|
||||
|
||||
var centroid = new Vector3();
|
||||
|
||||
var uvA = new Vector2();
|
||||
var uvB = new Vector2();
|
||||
var uvC = new Vector2();
|
||||
|
||||
for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
|
||||
|
||||
a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
|
||||
b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
|
||||
c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
|
||||
|
||||
uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
|
||||
uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
|
||||
uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
|
||||
|
||||
centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
|
||||
|
||||
var azi = azimuth( centroid );
|
||||
|
||||
correctUV( uvA, j + 0, a, azi );
|
||||
correctUV( uvB, j + 2, b, azi );
|
||||
correctUV( uvC, j + 4, c, azi );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function correctUV( uv, stride, vector, azimuth ) {
|
||||
|
||||
if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
|
||||
|
||||
uvBuffer[ stride ] = uv.x - 1;
|
||||
|
||||
}
|
||||
|
||||
if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
|
||||
|
||||
uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Angle around the Y axis, counter-clockwise when looking from above.
|
||||
|
||||
function azimuth( vector ) {
|
||||
|
||||
return Math.atan2( vector.z, - vector.x );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Angle above the XZ plane.
|
||||
|
||||
function inclination( vector ) {
|
||||
|
||||
return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
|
||||
|
||||
|
||||
export { PolyhedronGeometry, PolyhedronBufferGeometry };
|
152
lib/geometries/RingGeometry.js
Normal file
152
lib/geometries/RingGeometry.js
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @author Kaleb Murphy
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// RingGeometry
|
||||
|
||||
function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'RingGeometry';
|
||||
|
||||
this.parameters = {
|
||||
innerRadius: innerRadius,
|
||||
outerRadius: outerRadius,
|
||||
thetaSegments: thetaSegments,
|
||||
phiSegments: phiSegments,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
RingGeometry.prototype = Object.create( Geometry.prototype );
|
||||
RingGeometry.prototype.constructor = RingGeometry;
|
||||
|
||||
// RingBufferGeometry
|
||||
|
||||
function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'RingBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
innerRadius: innerRadius,
|
||||
outerRadius: outerRadius,
|
||||
thetaSegments: thetaSegments,
|
||||
phiSegments: phiSegments,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
innerRadius = innerRadius || 0.5;
|
||||
outerRadius = outerRadius || 1;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
|
||||
|
||||
thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
|
||||
phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// some helper variables
|
||||
|
||||
var segment;
|
||||
var radius = innerRadius;
|
||||
var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
|
||||
var vertex = new Vector3();
|
||||
var uv = new Vector2();
|
||||
var j, i;
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( j = 0; j <= phiSegments; j ++ ) {
|
||||
|
||||
for ( i = 0; i <= thetaSegments; i ++ ) {
|
||||
|
||||
// values are generate from the inside of the ring to the outside
|
||||
|
||||
segment = thetaStart + i / thetaSegments * thetaLength;
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = radius * Math.cos( segment );
|
||||
vertex.y = radius * Math.sin( segment );
|
||||
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
normals.push( 0, 0, 1 );
|
||||
|
||||
// uv
|
||||
|
||||
uv.x = ( vertex.x / outerRadius + 1 ) / 2;
|
||||
uv.y = ( vertex.y / outerRadius + 1 ) / 2;
|
||||
|
||||
uvs.push( uv.x, uv.y );
|
||||
|
||||
}
|
||||
|
||||
// increase the radius for next row of vertices
|
||||
|
||||
radius += radiusStep;
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for ( j = 0; j < phiSegments; j ++ ) {
|
||||
|
||||
var thetaSegmentLevel = j * ( thetaSegments + 1 );
|
||||
|
||||
for ( i = 0; i < thetaSegments; i ++ ) {
|
||||
|
||||
segment = i + thetaSegmentLevel;
|
||||
|
||||
var a = segment;
|
||||
var b = segment + thetaSegments + 1;
|
||||
var c = segment + thetaSegments + 2;
|
||||
var d = segment + 1;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
RingBufferGeometry.prototype.constructor = RingBufferGeometry;
|
||||
|
||||
|
||||
export { RingGeometry, RingBufferGeometry };
|
222
lib/geometries/ShapeGeometry.js
Normal file
222
lib/geometries/ShapeGeometry.js
Normal file
@ -0,0 +1,222 @@
|
||||
/**
|
||||
* @author jonobr1 / http://jonobr1.com
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { ShapeUtils } from '../extras/ShapeUtils.js';
|
||||
|
||||
// ShapeGeometry
|
||||
|
||||
function ShapeGeometry( shapes, curveSegments ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'ShapeGeometry';
|
||||
|
||||
if ( typeof curveSegments === 'object' ) {
|
||||
|
||||
console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
|
||||
|
||||
curveSegments = curveSegments.curveSegments;
|
||||
|
||||
}
|
||||
|
||||
this.parameters = {
|
||||
shapes: shapes,
|
||||
curveSegments: curveSegments
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
ShapeGeometry.prototype = Object.create( Geometry.prototype );
|
||||
ShapeGeometry.prototype.constructor = ShapeGeometry;
|
||||
|
||||
ShapeGeometry.prototype.toJSON = function () {
|
||||
|
||||
var data = Geometry.prototype.toJSON.call( this );
|
||||
|
||||
var shapes = this.parameters.shapes;
|
||||
|
||||
return toJSON( shapes, data );
|
||||
|
||||
};
|
||||
|
||||
// ShapeBufferGeometry
|
||||
|
||||
function ShapeBufferGeometry( shapes, curveSegments ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'ShapeBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
shapes: shapes,
|
||||
curveSegments: curveSegments
|
||||
};
|
||||
|
||||
curveSegments = curveSegments || 12;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var groupStart = 0;
|
||||
var groupCount = 0;
|
||||
|
||||
// allow single and array values for "shapes" parameter
|
||||
|
||||
if ( Array.isArray( shapes ) === false ) {
|
||||
|
||||
addShape( shapes );
|
||||
|
||||
} else {
|
||||
|
||||
for ( var i = 0; i < shapes.length; i ++ ) {
|
||||
|
||||
addShape( shapes[ i ] );
|
||||
|
||||
this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
|
||||
|
||||
groupStart += groupCount;
|
||||
groupCount = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
|
||||
// helper functions
|
||||
|
||||
function addShape( shape ) {
|
||||
|
||||
var i, l, shapeHole;
|
||||
|
||||
var indexOffset = vertices.length / 3;
|
||||
var points = shape.extractPoints( curveSegments );
|
||||
|
||||
var shapeVertices = points.shape;
|
||||
var shapeHoles = points.holes;
|
||||
|
||||
// check direction of vertices
|
||||
|
||||
if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
|
||||
|
||||
shapeVertices = shapeVertices.reverse();
|
||||
|
||||
// also check if holes are in the opposite direction
|
||||
|
||||
for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
|
||||
|
||||
shapeHole = shapeHoles[ i ];
|
||||
|
||||
if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
|
||||
|
||||
shapeHoles[ i ] = shapeHole.reverse();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
|
||||
|
||||
// join vertices of inner and outer paths to a single array
|
||||
|
||||
for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
|
||||
|
||||
shapeHole = shapeHoles[ i ];
|
||||
shapeVertices = shapeVertices.concat( shapeHole );
|
||||
|
||||
}
|
||||
|
||||
// vertices, normals, uvs
|
||||
|
||||
for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
|
||||
|
||||
var vertex = shapeVertices[ i ];
|
||||
|
||||
vertices.push( vertex.x, vertex.y, 0 );
|
||||
normals.push( 0, 0, 1 );
|
||||
uvs.push( vertex.x, vertex.y ); // world uvs
|
||||
|
||||
}
|
||||
|
||||
// incides
|
||||
|
||||
for ( i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
var a = face[ 0 ] + indexOffset;
|
||||
var b = face[ 1 ] + indexOffset;
|
||||
var c = face[ 2 ] + indexOffset;
|
||||
|
||||
indices.push( a, b, c );
|
||||
groupCount += 3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
|
||||
|
||||
ShapeBufferGeometry.prototype.toJSON = function () {
|
||||
|
||||
var data = BufferGeometry.prototype.toJSON.call( this );
|
||||
|
||||
var shapes = this.parameters.shapes;
|
||||
|
||||
return toJSON( shapes, data );
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
function toJSON( shapes, data ) {
|
||||
|
||||
data.shapes = [];
|
||||
|
||||
if ( Array.isArray( shapes ) ) {
|
||||
|
||||
for ( var i = 0, l = shapes.length; i < l; i ++ ) {
|
||||
|
||||
var shape = shapes[ i ];
|
||||
|
||||
data.shapes.push( shape.uuid );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
data.shapes.push( shapes.uuid );
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export { ShapeGeometry, ShapeBufferGeometry };
|
152
lib/geometries/SphereGeometry.js
Normal file
152
lib/geometries/SphereGeometry.js
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author benaadams / https://twitter.com/ben_a_adams
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// SphereGeometry
|
||||
|
||||
function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'SphereGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
phiStart: phiStart,
|
||||
phiLength: phiLength,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
SphereGeometry.prototype = Object.create( Geometry.prototype );
|
||||
SphereGeometry.prototype.constructor = SphereGeometry;
|
||||
|
||||
// SphereBufferGeometry
|
||||
|
||||
function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'SphereBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
phiStart: phiStart,
|
||||
phiLength: phiLength,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
radius = radius || 1;
|
||||
|
||||
widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
|
||||
heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
|
||||
|
||||
phiStart = phiStart !== undefined ? phiStart : 0;
|
||||
phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
|
||||
|
||||
var thetaEnd = thetaStart + thetaLength;
|
||||
|
||||
var ix, iy;
|
||||
|
||||
var index = 0;
|
||||
var grid = [];
|
||||
|
||||
var vertex = new Vector3();
|
||||
var normal = new Vector3();
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( iy = 0; iy <= heightSegments; iy ++ ) {
|
||||
|
||||
var verticesRow = [];
|
||||
|
||||
var v = iy / heightSegments;
|
||||
|
||||
for ( ix = 0; ix <= widthSegments; ix ++ ) {
|
||||
|
||||
var u = ix / widthSegments;
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
|
||||
vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
|
||||
vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
|
||||
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
normal.set( vertex.x, vertex.y, vertex.z ).normalize();
|
||||
normals.push( normal.x, normal.y, normal.z );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( u, 1 - v );
|
||||
|
||||
verticesRow.push( index ++ );
|
||||
|
||||
}
|
||||
|
||||
grid.push( verticesRow );
|
||||
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for ( iy = 0; iy < heightSegments; iy ++ ) {
|
||||
|
||||
for ( ix = 0; ix < widthSegments; ix ++ ) {
|
||||
|
||||
var a = grid[ iy ][ ix + 1 ];
|
||||
var b = grid[ iy ][ ix ];
|
||||
var c = grid[ iy + 1 ][ ix ];
|
||||
var d = grid[ iy + 1 ][ ix + 1 ];
|
||||
|
||||
if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
|
||||
if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
|
||||
|
||||
|
||||
export { SphereGeometry, SphereBufferGeometry };
|
57
lib/geometries/TetrahedronGeometry.js
Normal file
57
lib/geometries/TetrahedronGeometry.js
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { PolyhedronBufferGeometry } from './PolyhedronGeometry.js';
|
||||
|
||||
// TetrahedronGeometry
|
||||
|
||||
function TetrahedronGeometry( radius, detail ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'TetrahedronGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
|
||||
TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
|
||||
|
||||
// TetrahedronBufferGeometry
|
||||
|
||||
function TetrahedronBufferGeometry( radius, detail ) {
|
||||
|
||||
var vertices = [
|
||||
1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
|
||||
];
|
||||
|
||||
PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
this.type = 'TetrahedronBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
|
||||
TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
|
||||
|
||||
|
||||
export { TetrahedronGeometry, TetrahedronBufferGeometry };
|
81
lib/geometries/TextGeometry.js
Normal file
81
lib/geometries/TextGeometry.js
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*
|
||||
* Text = 3D Text
|
||||
*
|
||||
* parameters = {
|
||||
* font: <THREE.Font>, // font
|
||||
*
|
||||
* size: <float>, // size of the text
|
||||
* height: <float>, // thickness to extrude text
|
||||
* curveSegments: <int>, // number of points on the curves
|
||||
*
|
||||
* bevelEnabled: <bool>, // turn on bevel
|
||||
* bevelThickness: <float>, // how deep into text bevel goes
|
||||
* bevelSize: <float> // how far from text outline is bevel
|
||||
* }
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { ExtrudeBufferGeometry } from './ExtrudeGeometry.js';
|
||||
|
||||
// TextGeometry
|
||||
|
||||
function TextGeometry( text, parameters ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'TextGeometry';
|
||||
|
||||
this.parameters = {
|
||||
text: text,
|
||||
parameters: parameters
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
TextGeometry.prototype = Object.create( Geometry.prototype );
|
||||
TextGeometry.prototype.constructor = TextGeometry;
|
||||
|
||||
// TextBufferGeometry
|
||||
|
||||
function TextBufferGeometry( text, parameters ) {
|
||||
|
||||
parameters = parameters || {};
|
||||
|
||||
var font = parameters.font;
|
||||
|
||||
if ( ! ( font && font.isFont ) ) {
|
||||
|
||||
console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
|
||||
return new Geometry();
|
||||
|
||||
}
|
||||
|
||||
var shapes = font.generateShapes( text, parameters.size );
|
||||
|
||||
// translate parameters to ExtrudeGeometry API
|
||||
|
||||
parameters.depth = parameters.height !== undefined ? parameters.height : 50;
|
||||
|
||||
// defaults
|
||||
|
||||
if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
|
||||
if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
|
||||
if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
|
||||
|
||||
ExtrudeBufferGeometry.call( this, shapes, parameters );
|
||||
|
||||
this.type = 'TextBufferGeometry';
|
||||
|
||||
}
|
||||
|
||||
TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
|
||||
TextBufferGeometry.prototype.constructor = TextBufferGeometry;
|
||||
|
||||
|
||||
export { TextGeometry, TextBufferGeometry };
|
142
lib/geometries/TorusGeometry.js
Normal file
142
lib/geometries/TorusGeometry.js
Normal file
@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @author oosmoxiecode
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// TorusGeometry
|
||||
|
||||
function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'TorusGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
radialSegments: radialSegments,
|
||||
tubularSegments: tubularSegments,
|
||||
arc: arc
|
||||
};
|
||||
|
||||
this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
TorusGeometry.prototype = Object.create( Geometry.prototype );
|
||||
TorusGeometry.prototype.constructor = TorusGeometry;
|
||||
|
||||
// TorusBufferGeometry
|
||||
|
||||
function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'TorusBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
radialSegments: radialSegments,
|
||||
tubularSegments: tubularSegments,
|
||||
arc: arc
|
||||
};
|
||||
|
||||
radius = radius || 1;
|
||||
tube = tube || 0.4;
|
||||
radialSegments = Math.floor( radialSegments ) || 8;
|
||||
tubularSegments = Math.floor( tubularSegments ) || 6;
|
||||
arc = arc || Math.PI * 2;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var center = new Vector3();
|
||||
var vertex = new Vector3();
|
||||
var normal = new Vector3();
|
||||
|
||||
var j, i;
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( j = 0; j <= radialSegments; j ++ ) {
|
||||
|
||||
for ( i = 0; i <= tubularSegments; i ++ ) {
|
||||
|
||||
var u = i / tubularSegments * arc;
|
||||
var v = j / radialSegments * Math.PI * 2;
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
|
||||
vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
|
||||
vertex.z = tube * Math.sin( v );
|
||||
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
// normal
|
||||
|
||||
center.x = radius * Math.cos( u );
|
||||
center.y = radius * Math.sin( u );
|
||||
normal.subVectors( vertex, center ).normalize();
|
||||
|
||||
normals.push( normal.x, normal.y, normal.z );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( i / tubularSegments );
|
||||
uvs.push( j / radialSegments );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate indices
|
||||
|
||||
for ( j = 1; j <= radialSegments; j ++ ) {
|
||||
|
||||
for ( i = 1; i <= tubularSegments; i ++ ) {
|
||||
|
||||
// indices
|
||||
|
||||
var a = ( tubularSegments + 1 ) * j + i - 1;
|
||||
var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
|
||||
var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
|
||||
var d = ( tubularSegments + 1 ) * j + i;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
|
||||
|
||||
|
||||
export { TorusGeometry, TorusBufferGeometry };
|
194
lib/geometries/TorusKnotGeometry.js
Normal file
194
lib/geometries/TorusKnotGeometry.js
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @author oosmoxiecode
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*
|
||||
* based on http://www.blackpawn.com/texts/pqtorus/
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// TorusKnotGeometry
|
||||
|
||||
function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'TorusKnotGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
tubularSegments: tubularSegments,
|
||||
radialSegments: radialSegments,
|
||||
p: p,
|
||||
q: q
|
||||
};
|
||||
|
||||
if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
|
||||
|
||||
this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
|
||||
TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
|
||||
|
||||
// TorusKnotBufferGeometry
|
||||
|
||||
function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'TorusKnotBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
tubularSegments: tubularSegments,
|
||||
radialSegments: radialSegments,
|
||||
p: p,
|
||||
q: q
|
||||
};
|
||||
|
||||
radius = radius || 1;
|
||||
tube = tube || 0.4;
|
||||
tubularSegments = Math.floor( tubularSegments ) || 64;
|
||||
radialSegments = Math.floor( radialSegments ) || 8;
|
||||
p = p || 2;
|
||||
q = q || 3;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var i, j;
|
||||
|
||||
var vertex = new Vector3();
|
||||
var normal = new Vector3();
|
||||
|
||||
var P1 = new Vector3();
|
||||
var P2 = new Vector3();
|
||||
|
||||
var B = new Vector3();
|
||||
var T = new Vector3();
|
||||
var N = new Vector3();
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( i = 0; i <= tubularSegments; ++ i ) {
|
||||
|
||||
// the radian "u" is used to calculate the position on the torus curve of the current tubular segement
|
||||
|
||||
var u = i / tubularSegments * p * Math.PI * 2;
|
||||
|
||||
// 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, P1 );
|
||||
calculatePositionOnCurve( u + 0.01, p, q, radius, 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 <= radialSegments; ++ 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 / radialSegments * 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 );
|
||||
|
||||
vertices.push( 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.push( normal.x, normal.y, normal.z );
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push( i / tubularSegments );
|
||||
uvs.push( j / radialSegments );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate indices
|
||||
|
||||
for ( j = 1; j <= tubularSegments; j ++ ) {
|
||||
|
||||
for ( i = 1; i <= radialSegments; i ++ ) {
|
||||
|
||||
// indices
|
||||
|
||||
var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
|
||||
var b = ( radialSegments + 1 ) * j + ( i - 1 );
|
||||
var c = ( radialSegments + 1 ) * j + i;
|
||||
var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
// this function calculates the current position on the torus curve
|
||||
|
||||
function calculatePositionOnCurve( u, p, q, radius, 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 = radius * Math.sin( quOverP ) * 0.5;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
|
||||
|
||||
|
||||
export { TorusKnotGeometry, TorusKnotBufferGeometry };
|
223
lib/geometries/TubeGeometry.js
Normal file
223
lib/geometries/TubeGeometry.js
Normal file
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* @author oosmoxiecode / https://github.com/oosmoxiecode
|
||||
* @author WestLangley / https://github.com/WestLangley
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* @author miningold / https://github.com/miningold
|
||||
* @author jonobr1 / https://github.com/jonobr1
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*
|
||||
*/
|
||||
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
// TubeGeometry
|
||||
|
||||
function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
|
||||
|
||||
Geometry.call( this );
|
||||
|
||||
this.type = 'TubeGeometry';
|
||||
|
||||
this.parameters = {
|
||||
path: path,
|
||||
tubularSegments: tubularSegments,
|
||||
radius: radius,
|
||||
radialSegments: radialSegments,
|
||||
closed: closed
|
||||
};
|
||||
|
||||
if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
|
||||
|
||||
var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
|
||||
|
||||
// expose internals
|
||||
|
||||
this.tangents = bufferGeometry.tangents;
|
||||
this.normals = bufferGeometry.normals;
|
||||
this.binormals = bufferGeometry.binormals;
|
||||
|
||||
// create geometry
|
||||
|
||||
this.fromBufferGeometry( bufferGeometry );
|
||||
this.mergeVertices();
|
||||
|
||||
}
|
||||
|
||||
TubeGeometry.prototype = Object.create( Geometry.prototype );
|
||||
TubeGeometry.prototype.constructor = TubeGeometry;
|
||||
|
||||
// TubeBufferGeometry
|
||||
|
||||
function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'TubeBufferGeometry';
|
||||
|
||||
this.parameters = {
|
||||
path: path,
|
||||
tubularSegments: tubularSegments,
|
||||
radius: radius,
|
||||
radialSegments: radialSegments,
|
||||
closed: closed
|
||||
};
|
||||
|
||||
tubularSegments = tubularSegments || 64;
|
||||
radius = radius || 1;
|
||||
radialSegments = radialSegments || 8;
|
||||
closed = closed || false;
|
||||
|
||||
var frames = path.computeFrenetFrames( tubularSegments, closed );
|
||||
|
||||
// expose internals
|
||||
|
||||
this.tangents = frames.tangents;
|
||||
this.normals = frames.normals;
|
||||
this.binormals = frames.binormals;
|
||||
|
||||
// helper variables
|
||||
|
||||
var vertex = new Vector3();
|
||||
var normal = new Vector3();
|
||||
var uv = new Vector2();
|
||||
var P = new Vector3();
|
||||
|
||||
var i, j;
|
||||
|
||||
// buffer
|
||||
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
var indices = [];
|
||||
|
||||
// create buffer data
|
||||
|
||||
generateBufferData();
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex( indices );
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||||
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||||
|
||||
// functions
|
||||
|
||||
function generateBufferData() {
|
||||
|
||||
for ( 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
|
||||
|
||||
var N = frames.normals[ i ];
|
||||
var B = frames.binormals[ i ];
|
||||
|
||||
// generate normals and vertices for the current segment
|
||||
|
||||
for ( j = 0; j <= radialSegments; j ++ ) {
|
||||
|
||||
var v = j / radialSegments * Math.PI * 2;
|
||||
|
||||
var sin = Math.sin( v );
|
||||
var 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 ( j = 1; j <= tubularSegments; j ++ ) {
|
||||
|
||||
for ( i = 1; i <= radialSegments; i ++ ) {
|
||||
|
||||
var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
|
||||
var b = ( radialSegments + 1 ) * j + ( i - 1 );
|
||||
var c = ( radialSegments + 1 ) * j + i;
|
||||
var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function generateUVs() {
|
||||
|
||||
for ( i = 0; i <= tubularSegments; i ++ ) {
|
||||
|
||||
for ( j = 0; j <= radialSegments; j ++ ) {
|
||||
|
||||
uv.x = i / tubularSegments;
|
||||
uv.y = j / radialSegments;
|
||||
|
||||
uvs.push( uv.x, uv.y );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
|
||||
|
||||
|
||||
export { TubeGeometry, TubeBufferGeometry };
|
179
lib/geometries/WireframeGeometry.js
Normal file
179
lib/geometries/WireframeGeometry.js
Normal file
@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Mugen87 / https://github.com/Mugen87
|
||||
*/
|
||||
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
function WireframeGeometry( geometry ) {
|
||||
|
||||
BufferGeometry.call( this );
|
||||
|
||||
this.type = 'WireframeGeometry';
|
||||
|
||||
// buffer
|
||||
|
||||
var vertices = [];
|
||||
|
||||
// helper variables
|
||||
|
||||
var i, j, l, o, ol;
|
||||
var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
|
||||
var key, keys = [ 'a', 'b', 'c' ];
|
||||
var vertex;
|
||||
|
||||
// different logic for Geometry and BufferGeometry
|
||||
|
||||
if ( geometry && geometry.isGeometry ) {
|
||||
|
||||
// create a data structure that contains all edges without duplicates
|
||||
|
||||
var faces = geometry.faces;
|
||||
|
||||
for ( i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge1 = face[ keys[ j ] ];
|
||||
edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
|
||||
edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
|
||||
edge[ 1 ] = Math.max( edge1, edge2 );
|
||||
|
||||
key = edge[ 0 ] + ',' + edge[ 1 ];
|
||||
|
||||
if ( edges[ key ] === undefined ) {
|
||||
|
||||
edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate vertices
|
||||
|
||||
for ( key in edges ) {
|
||||
|
||||
e = edges[ key ];
|
||||
|
||||
vertex = geometry.vertices[ e.index1 ];
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
vertex = geometry.vertices[ e.index2 ];
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
} else if ( geometry && geometry.isBufferGeometry ) {
|
||||
|
||||
var position, indices, groups;
|
||||
var group, start, count;
|
||||
var index1, index2;
|
||||
|
||||
vertex = new Vector3();
|
||||
|
||||
if ( geometry.index !== null ) {
|
||||
|
||||
// indexed BufferGeometry
|
||||
|
||||
position = geometry.attributes.position;
|
||||
indices = geometry.index;
|
||||
groups = geometry.groups;
|
||||
|
||||
if ( groups.length === 0 ) {
|
||||
|
||||
groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
|
||||
|
||||
}
|
||||
|
||||
// create a data structure that contains all eges without duplicates
|
||||
|
||||
for ( o = 0, ol = groups.length; o < ol; ++ o ) {
|
||||
|
||||
group = groups[ o ];
|
||||
|
||||
start = group.start;
|
||||
count = group.count;
|
||||
|
||||
for ( i = start, l = ( start + count ); i < l; i += 3 ) {
|
||||
|
||||
for ( j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge1 = indices.getX( i + j );
|
||||
edge2 = indices.getX( i + ( j + 1 ) % 3 );
|
||||
edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
|
||||
edge[ 1 ] = Math.max( edge1, edge2 );
|
||||
|
||||
key = edge[ 0 ] + ',' + edge[ 1 ];
|
||||
|
||||
if ( edges[ key ] === undefined ) {
|
||||
|
||||
edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate vertices
|
||||
|
||||
for ( key in edges ) {
|
||||
|
||||
e = edges[ key ];
|
||||
|
||||
vertex.fromBufferAttribute( position, e.index1 );
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
vertex.fromBufferAttribute( position, e.index2 );
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// non-indexed BufferGeometry
|
||||
|
||||
position = geometry.attributes.position;
|
||||
|
||||
for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
|
||||
|
||||
for ( j = 0; j < 3; j ++ ) {
|
||||
|
||||
// three edges per triangle, an edge is represented as (index1, index2)
|
||||
// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
|
||||
|
||||
index1 = 3 * i + j;
|
||||
vertex.fromBufferAttribute( position, index1 );
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
index2 = 3 * i + ( ( j + 1 ) % 3 );
|
||||
vertex.fromBufferAttribute( position, index2 );
|
||||
vertices.push( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||||
|
||||
}
|
||||
|
||||
WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||||
WireframeGeometry.prototype.constructor = WireframeGeometry;
|
||||
|
||||
|
||||
export { WireframeGeometry };
|
Reference in New Issue
Block a user