|
@@ -53,479 +53,455 @@ ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
|
|
|
|
|
|
function ExtrudeBufferGeometry( shapes, options ) {
|
|
|
|
|
|
- if ( typeof ( shapes ) === "undefined" ) {
|
|
|
-
|
|
|
- return;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
BufferGeometry.call( this );
|
|
|
|
|
|
this.type = 'ExtrudeBufferGeometry';
|
|
|
|
|
|
- shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
|
|
|
-
|
|
|
- this.addShapeList( shapes, options );
|
|
|
-
|
|
|
- this.computeVertexNormals();
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
|
|
-ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
|
|
|
-
|
|
|
-ExtrudeBufferGeometry.prototype.getArrays = function () {
|
|
|
-
|
|
|
- var positionAttribute = this.getAttribute( "position" );
|
|
|
- var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : [];
|
|
|
-
|
|
|
- var uvAttribute = this.getAttribute( "uv" );
|
|
|
- var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : [];
|
|
|
-
|
|
|
- return {
|
|
|
- position: verticesArray,
|
|
|
- uv: uvArray
|
|
|
+ this.parameters = {
|
|
|
+ shapes: shapes,
|
|
|
+ options: options
|
|
|
};
|
|
|
|
|
|
-};
|
|
|
+ shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
|
|
|
|
|
|
-ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) {
|
|
|
+ var scope = this;
|
|
|
|
|
|
- var sl = shapes.length;
|
|
|
- options.arrays = this.getArrays();
|
|
|
+ var verticesArray = [];
|
|
|
+ var uvArray = [];
|
|
|
|
|
|
- for ( var s = 0; s < sl; s ++ ) {
|
|
|
+ for ( var i = 0, l = shapes.length; i < l; i ++ ) {
|
|
|
|
|
|
- var shape = shapes[ s ];
|
|
|
- this.addShape( shape, options );
|
|
|
+ var shape = shapes[ i ];
|
|
|
+ addShape( shape, options );
|
|
|
|
|
|
}
|
|
|
|
|
|
- this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) );
|
|
|
- this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) );
|
|
|
+ // build geometry
|
|
|
|
|
|
-};
|
|
|
+ this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
|
|
|
+ this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
|
|
|
|
|
|
-ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) {
|
|
|
+ this.computeVertexNormals();
|
|
|
|
|
|
- var arrays = options.arrays ? options.arrays : this.getArrays();
|
|
|
- var verticesArray = arrays.position;
|
|
|
- var uvArray = arrays.uv;
|
|
|
+ // functions
|
|
|
|
|
|
- var placeholder = [];
|
|
|
+ function addShape( shape ) {
|
|
|
|
|
|
+ var placeholder = [];
|
|
|
|
|
|
- var amount = options.amount !== undefined ? options.amount : 100;
|
|
|
+ // options
|
|
|
|
|
|
- var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
|
|
|
- var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
|
|
|
- var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
|
|
|
+ var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
|
|
|
+ var steps = options.steps !== undefined ? options.steps : 1;
|
|
|
+ var amount = options.amount !== undefined ? options.amount : 100;
|
|
|
|
|
|
- var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
|
|
|
+ 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 curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
|
|
|
+ var extrudePath = options.extrudePath;
|
|
|
|
|
|
- var steps = options.steps !== undefined ? options.steps : 1;
|
|
|
+ var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
|
|
|
|
|
|
- var extrudePath = options.extrudePath;
|
|
|
- var extrudePts, extrudeByPath = false;
|
|
|
+ //
|
|
|
|
|
|
- // Use default WorldUVGenerator if no UV generators are specified.
|
|
|
- var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator;
|
|
|
+ var extrudePts, extrudeByPath = false;
|
|
|
+ var splineTube, binormal, normal, position2;
|
|
|
|
|
|
- var splineTube, binormal, normal, position2;
|
|
|
- if ( extrudePath ) {
|
|
|
+ if ( extrudePath ) {
|
|
|
|
|
|
- extrudePts = extrudePath.getSpacedPoints( steps );
|
|
|
+ extrudePts = extrudePath.getSpacedPoints( steps );
|
|
|
|
|
|
- extrudeByPath = true;
|
|
|
- bevelEnabled = false; // bevels not supported for path extrusion
|
|
|
+ extrudeByPath = true;
|
|
|
+ bevelEnabled = false; // bevels not supported for path extrusion
|
|
|
|
|
|
- // SETUP TNB variables
|
|
|
+ // SETUP TNB variables
|
|
|
|
|
|
- // TODO1 - have a .isClosed in spline?
|
|
|
+ // TODO1 - have a .isClosed in spline?
|
|
|
|
|
|
- splineTube = extrudePath.computeFrenetFrames( steps, false );
|
|
|
+ splineTube = extrudePath.computeFrenetFrames( steps, false );
|
|
|
|
|
|
- // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
|
|
|
+ // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
|
|
|
|
|
|
- binormal = new Vector3();
|
|
|
- normal = new Vector3();
|
|
|
- position2 = new Vector3();
|
|
|
+ binormal = new Vector3();
|
|
|
+ normal = new Vector3();
|
|
|
+ position2 = new Vector3();
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- // Safeguards if bevels are not enabled
|
|
|
+ // Safeguards if bevels are not enabled
|
|
|
|
|
|
- if ( ! bevelEnabled ) {
|
|
|
+ if ( ! bevelEnabled ) {
|
|
|
|
|
|
- bevelSegments = 0;
|
|
|
- bevelThickness = 0;
|
|
|
- bevelSize = 0;
|
|
|
+ bevelSegments = 0;
|
|
|
+ bevelThickness = 0;
|
|
|
+ bevelSize = 0;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- // Variables initialization
|
|
|
+ // Variables initialization
|
|
|
|
|
|
- var ahole, h, hl; // looping of holes
|
|
|
- var scope = this;
|
|
|
+ var ahole, h, hl; // looping of holes
|
|
|
|
|
|
- var shapePoints = shape.extractPoints( curveSegments );
|
|
|
+ var shapePoints = shape.extractPoints( curveSegments );
|
|
|
|
|
|
- var vertices = shapePoints.shape;
|
|
|
- var holes = shapePoints.holes;
|
|
|
+ var vertices = shapePoints.shape;
|
|
|
+ var holes = shapePoints.holes;
|
|
|
|
|
|
- var reverse = ! ShapeUtils.isClockWise( vertices );
|
|
|
+ var reverse = ! ShapeUtils.isClockWise( vertices );
|
|
|
|
|
|
- if ( reverse ) {
|
|
|
+ if ( reverse ) {
|
|
|
|
|
|
- vertices = vertices.reverse();
|
|
|
+ vertices = vertices.reverse();
|
|
|
|
|
|
- // Maybe we should also check if holes are in the opposite direction, just to be safe ...
|
|
|
+ // 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 ++ ) {
|
|
|
+ for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
|
|
|
- ahole = holes[ h ];
|
|
|
+ ahole = holes[ h ];
|
|
|
|
|
|
- if ( ShapeUtils.isClockWise( ahole ) ) {
|
|
|
+ if ( ShapeUtils.isClockWise( ahole ) ) {
|
|
|
|
|
|
- holes[ h ] = ahole.reverse();
|
|
|
+ holes[ h ] = ahole.reverse();
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var faces = ShapeUtils.triangulateShape( vertices, holes );
|
|
|
|
|
|
- var faces = ShapeUtils.triangulateShape( vertices, holes );
|
|
|
+ /* Vertices */
|
|
|
|
|
|
- /* Vertices */
|
|
|
+ var contour = vertices; // vertices has all points but contour has only points of circumference
|
|
|
|
|
|
- var contour = vertices; // vertices has all points but contour has only points of circumference
|
|
|
+ for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
|
|
|
- for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
+ ahole = holes[ h ];
|
|
|
|
|
|
- ahole = holes[ h ];
|
|
|
+ vertices = vertices.concat( ahole );
|
|
|
|
|
|
- vertices = vertices.concat( ahole );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function scalePt2( pt, vec, size ) {
|
|
|
|
|
|
- function scalePt2( pt, vec, size ) {
|
|
|
+ if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
|
|
|
|
|
|
- if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
|
|
|
+ return vec.clone().multiplyScalar( size ).add( pt );
|
|
|
|
|
|
- return vec.clone().multiplyScalar( size ).add( pt );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ var b, bs, t, z,
|
|
|
+ vert, vlen = vertices.length,
|
|
|
+ face, flen = faces.length;
|
|
|
|
|
|
- var b, bs, t, z,
|
|
|
- vert, vlen = vertices.length,
|
|
|
- face, flen = faces.length;
|
|
|
|
|
|
+ // Find directions for point movement
|
|
|
|
|
|
- // Find directions for point movement
|
|
|
|
|
|
+ function getBevelVec( inPt, inPrev, inNext ) {
|
|
|
|
|
|
- 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.
|
|
|
|
|
|
- // 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
|
|
|
|
|
|
- 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
|
|
|
|
|
|
- // 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_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 );
|
|
|
|
|
|
- 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 );
|
|
|
|
|
|
- // check for collinear edges
|
|
|
- var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
|
|
|
+ if ( Math.abs( collinear0 ) > Number.EPSILON ) {
|
|
|
|
|
|
- if ( Math.abs( collinear0 ) > Number.EPSILON ) {
|
|
|
+ // not collinear
|
|
|
|
|
|
- // not collinear
|
|
|
+ // length of vectors for normalizing
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- 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
|
|
|
|
|
|
- // 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 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 );
|
|
|
|
|
|
- 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
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- 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
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- 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 ) {
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- return new Vector2( v_trans_x, v_trans_y );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ shrink_by = Math.sqrt( v_trans_lensq / 2 );
|
|
|
|
|
|
- shrink_by = Math.sqrt( v_trans_lensq / 2 );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ // handle special case of collinear edges
|
|
|
|
|
|
- // handle special case of collinear edges
|
|
|
+ var direction_eq = false; // assumes: opposite
|
|
|
+ if ( v_prev_x > Number.EPSILON ) {
|
|
|
|
|
|
- var direction_eq = false; // assumes: opposite
|
|
|
- if ( v_prev_x > Number.EPSILON ) {
|
|
|
+ if ( v_next_x > Number.EPSILON ) {
|
|
|
|
|
|
- if ( v_next_x > Number.EPSILON ) {
|
|
|
+ direction_eq = true;
|
|
|
|
|
|
- direction_eq = true;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( v_prev_x < - Number.EPSILON ) {
|
|
|
|
|
|
- if ( v_prev_x < - Number.EPSILON ) {
|
|
|
+ if ( v_next_x < - Number.EPSILON ) {
|
|
|
|
|
|
- if ( v_next_x < - Number.EPSILON ) {
|
|
|
+ direction_eq = true;
|
|
|
|
|
|
- direction_eq = true;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
|
|
|
|
|
|
- if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
|
|
|
+ direction_eq = true;
|
|
|
|
|
|
- direction_eq = true;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ if ( direction_eq ) {
|
|
|
|
|
|
- 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 );
|
|
|
|
|
|
- // 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 {
|
|
|
|
|
|
- } 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 );
|
|
|
|
|
|
- // 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 );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- 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 ++ ) {
|
|
|
|
|
|
- var contourMovements = [];
|
|
|
+ if ( j === il ) j = 0;
|
|
|
+ if ( k === il ) k = 0;
|
|
|
|
|
|
- for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
|
|
+ // (j)---(i)---(k)
|
|
|
+ // console.log('i,j,k', i, j , k)
|
|
|
|
|
|
- if ( j === il ) j = 0;
|
|
|
- if ( k === il ) k = 0;
|
|
|
+ contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
|
|
|
|
|
|
- // (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 ++ ) {
|
|
|
|
|
|
- var holesMovements = [],
|
|
|
- oneHoleMovements, verticesMovements = contourMovements.concat();
|
|
|
+ ahole = holes[ h ];
|
|
|
|
|
|
- for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
+ oneHoleMovements = [];
|
|
|
|
|
|
- ahole = holes[ h ];
|
|
|
+ for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
|
|
|
|
|
- oneHoleMovements = [];
|
|
|
+ if ( j === il ) j = 0;
|
|
|
+ if ( k === il ) k = 0;
|
|
|
|
|
|
- for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
|
|
+ // (j)---(i)---(k)
|
|
|
+ oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ 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 );
|
|
|
|
|
|
}
|
|
|
|
|
|
- holesMovements.push( oneHoleMovements );
|
|
|
- verticesMovements = verticesMovements.concat( oneHoleMovements );
|
|
|
|
|
|
- }
|
|
|
+ // Loop bevelSegments, 1 for the front, 1 for the back
|
|
|
|
|
|
+ for ( b = 0; b < bevelSegments; b ++ ) {
|
|
|
|
|
|
- // Loop bevelSegments, 1 for the front, 1 for the back
|
|
|
+ //for ( b = bevelSegments; b > 0; b -- ) {
|
|
|
|
|
|
- for ( b = 0; b < bevelSegments; b ++ ) {
|
|
|
+ t = b / bevelSegments;
|
|
|
+ z = bevelThickness * Math.cos( t * Math.PI / 2 );
|
|
|
+ bs = bevelSize * Math.sin( t * Math.PI / 2 );
|
|
|
|
|
|
- //for ( b = bevelSegments; b > 0; b -- ) {
|
|
|
+ // contract shape
|
|
|
|
|
|
- t = b / bevelSegments;
|
|
|
- z = bevelThickness * Math.cos( t * Math.PI / 2 );
|
|
|
- bs = bevelSize * Math.sin( t * Math.PI / 2 );
|
|
|
+ for ( i = 0, il = contour.length; i < il; i ++ ) {
|
|
|
|
|
|
- // contract shape
|
|
|
+ vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
|
|
|
|
|
- for ( i = 0, il = contour.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
|
|
+ v( vert.x, vert.y, - z );
|
|
|
|
|
|
- v( vert.x, vert.y, - z );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // expand holes
|
|
|
|
|
|
- // expand holes
|
|
|
+ for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
|
|
|
- for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
+ ahole = holes[ h ];
|
|
|
+ oneHoleMovements = holesMovements[ h ];
|
|
|
|
|
|
- ahole = holes[ h ];
|
|
|
- oneHoleMovements = holesMovements[ h ];
|
|
|
+ for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
|
|
|
|
|
- for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
|
|
+ vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
|
|
|
|
|
- vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
|
|
+ v( vert.x, vert.y, - z );
|
|
|
|
|
|
- v( vert.x, vert.y, - z );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ bs = bevelSize;
|
|
|
|
|
|
- bs = bevelSize;
|
|
|
+ // Back facing vertices
|
|
|
|
|
|
- // Back facing vertices
|
|
|
+ for ( i = 0; i < vlen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < vlen; i ++ ) {
|
|
|
+ vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
|
|
|
|
|
- vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
|
|
+ if ( ! extrudeByPath ) {
|
|
|
|
|
|
- if ( ! extrudeByPath ) {
|
|
|
+ v( vert.x, vert.y, 0 );
|
|
|
|
|
|
- v( vert.x, vert.y, 0 );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
|
|
|
- binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
|
|
|
+ position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
|
|
|
|
|
|
- position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
|
|
|
+ v( position2.x, position2.y, position2.z );
|
|
|
|
|
|
- v( position2.x, position2.y, position2.z );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // Add stepped vertices...
|
|
|
+ // Including front facing vertices
|
|
|
|
|
|
- // Add stepped vertices...
|
|
|
- // Including front facing vertices
|
|
|
+ var s;
|
|
|
|
|
|
- var s;
|
|
|
+ for ( s = 1; s <= steps; s ++ ) {
|
|
|
|
|
|
- for ( s = 1; s <= steps; s ++ ) {
|
|
|
+ for ( i = 0; i < vlen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < vlen; i ++ ) {
|
|
|
+ vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
|
|
|
|
|
- vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
|
|
+ if ( ! extrudeByPath ) {
|
|
|
|
|
|
- if ( ! extrudeByPath ) {
|
|
|
+ v( vert.x, vert.y, amount / steps * s );
|
|
|
|
|
|
- v( vert.x, vert.y, amount / steps * s );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
|
|
|
|
|
|
- // 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 );
|
|
|
|
|
|
- normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
|
|
|
- binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
|
|
|
+ position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
|
|
|
|
|
|
- position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
|
|
|
+ v( position2.x, position2.y, position2.z );
|
|
|
|
|
|
- v( position2.x, position2.y, position2.z );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // Add bevel segments planes
|
|
|
|
|
|
- // Add bevel segments planes
|
|
|
+ //for ( b = 1; b <= bevelSegments; b ++ ) {
|
|
|
+ for ( b = bevelSegments - 1; b >= 0; b -- ) {
|
|
|
|
|
|
- //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 );
|
|
|
|
|
|
- t = b / bevelSegments;
|
|
|
- z = bevelThickness * Math.cos( t * Math.PI / 2 );
|
|
|
- bs = bevelSize * Math.sin( t * Math.PI / 2 );
|
|
|
+ // contract shape
|
|
|
|
|
|
- // contract shape
|
|
|
+ for ( i = 0, il = contour.length; i < il; i ++ ) {
|
|
|
|
|
|
- for ( i = 0, il = contour.length; i < il; i ++ ) {
|
|
|
+ vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
|
|
+ v( vert.x, vert.y, amount + z );
|
|
|
|
|
|
- vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
|
|
- v( vert.x, vert.y, amount + z );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // expand holes
|
|
|
|
|
|
- // expand holes
|
|
|
+ for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
|
|
|
- for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
+ ahole = holes[ h ];
|
|
|
+ oneHoleMovements = holesMovements[ h ];
|
|
|
|
|
|
- ahole = holes[ h ];
|
|
|
- oneHoleMovements = holesMovements[ h ];
|
|
|
+ for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
|
|
|
|
|
- for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
|
|
+ vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
|
|
|
|
|
- vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
|
|
+ if ( ! extrudeByPath ) {
|
|
|
|
|
|
- if ( ! extrudeByPath ) {
|
|
|
+ v( vert.x, vert.y, amount + z );
|
|
|
|
|
|
- v( vert.x, vert.y, amount + z );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
|
|
|
|
|
|
- v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -533,210 +509,206 @@ ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ /* Faces */
|
|
|
|
|
|
- /* Faces */
|
|
|
+ // Top and bottom faces
|
|
|
|
|
|
- // Top and bottom faces
|
|
|
+ buildLidFaces();
|
|
|
|
|
|
- buildLidFaces();
|
|
|
+ // Sides faces
|
|
|
|
|
|
- // Sides faces
|
|
|
+ buildSideFaces();
|
|
|
|
|
|
- buildSideFaces();
|
|
|
|
|
|
+ ///// Internal functions
|
|
|
|
|
|
- ///// Internal functions
|
|
|
+ function buildLidFaces() {
|
|
|
|
|
|
- function buildLidFaces() {
|
|
|
+ var start = verticesArray.length / 3;
|
|
|
|
|
|
- var start = verticesArray.length / 3;
|
|
|
+ if ( bevelEnabled ) {
|
|
|
|
|
|
- if ( bevelEnabled ) {
|
|
|
+ var layer = 0; // steps + 1
|
|
|
+ var offset = vlen * layer;
|
|
|
|
|
|
- var layer = 0; // steps + 1
|
|
|
- var offset = vlen * layer;
|
|
|
+ // Bottom faces
|
|
|
|
|
|
- // Bottom faces
|
|
|
+ for ( i = 0; i < flen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < flen; i ++ ) {
|
|
|
+ face = faces[ i ];
|
|
|
+ f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
|
|
|
|
|
|
- face = faces[ i ];
|
|
|
- f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ layer = steps + bevelSegments * 2;
|
|
|
+ offset = vlen * layer;
|
|
|
|
|
|
- layer = steps + bevelSegments * 2;
|
|
|
- offset = vlen * layer;
|
|
|
+ // Top faces
|
|
|
|
|
|
- // Top faces
|
|
|
+ for ( i = 0; i < flen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < flen; i ++ ) {
|
|
|
+ face = faces[ i ];
|
|
|
+ f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
|
|
|
|
|
|
- face = faces[ i ];
|
|
|
- f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ // Bottom faces
|
|
|
|
|
|
- // Bottom faces
|
|
|
+ for ( i = 0; i < flen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < flen; i ++ ) {
|
|
|
+ face = faces[ i ];
|
|
|
+ f3( face[ 2 ], face[ 1 ], face[ 0 ] );
|
|
|
|
|
|
- face = faces[ i ];
|
|
|
- f3( face[ 2 ], face[ 1 ], face[ 0 ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // Top faces
|
|
|
|
|
|
- // Top faces
|
|
|
+ for ( i = 0; i < flen; i ++ ) {
|
|
|
|
|
|
- for ( i = 0; i < flen; i ++ ) {
|
|
|
+ face = faces[ i ];
|
|
|
+ f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
|
|
|
|
|
|
- face = faces[ i ];
|
|
|
- f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
+ scope.addGroup( start, verticesArray.length / 3 - start, 0 );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- scope.addGroup( start, verticesArray.length / 3 - start, 0 );
|
|
|
+ // Create faces for the z-sides of the shape
|
|
|
|
|
|
- }
|
|
|
+ function buildSideFaces() {
|
|
|
|
|
|
- // Create faces for the z-sides of the shape
|
|
|
+ var start = verticesArray.length / 3;
|
|
|
+ var layeroffset = 0;
|
|
|
+ sidewalls( contour, layeroffset );
|
|
|
+ layeroffset += contour.length;
|
|
|
|
|
|
- function buildSideFaces() {
|
|
|
+ for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
|
|
|
- var start = verticesArray.length / 3;
|
|
|
- var layeroffset = 0;
|
|
|
- sidewalls( contour, layeroffset );
|
|
|
- layeroffset += contour.length;
|
|
|
+ ahole = holes[ h ];
|
|
|
+ sidewalls( ahole, layeroffset );
|
|
|
|
|
|
- for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
|
|
-
|
|
|
- ahole = holes[ h ];
|
|
|
- sidewalls( ahole, layeroffset );
|
|
|
+ //, true
|
|
|
+ layeroffset += ahole.length;
|
|
|
|
|
|
- //, true
|
|
|
- layeroffset += ahole.length;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ scope.addGroup( start, verticesArray.length / 3 - start, 1 );
|
|
|
|
|
|
- scope.addGroup( start, verticesArray.length / 3 - start, 1 );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ function sidewalls( contour, layeroffset ) {
|
|
|
|
|
|
- function sidewalls( contour, layeroffset ) {
|
|
|
+ var j, k;
|
|
|
+ i = contour.length;
|
|
|
|
|
|
- var j, k;
|
|
|
- i = contour.length;
|
|
|
+ while ( -- i >= 0 ) {
|
|
|
|
|
|
- while ( -- i >= 0 ) {
|
|
|
+ j = i;
|
|
|
+ k = i - 1;
|
|
|
+ if ( k < 0 ) k = contour.length - 1;
|
|
|
|
|
|
- j = i;
|
|
|
- k = i - 1;
|
|
|
- if ( k < 0 ) k = contour.length - 1;
|
|
|
+ //console.log('b', i,j, i-1, k,vertices.length);
|
|
|
|
|
|
- //console.log('b', i,j, i-1, k,vertices.length);
|
|
|
+ var s = 0,
|
|
|
+ sl = steps + bevelSegments * 2;
|
|
|
|
|
|
- var s = 0,
|
|
|
- sl = steps + bevelSegments * 2;
|
|
|
+ for ( s = 0; s < sl; s ++ ) {
|
|
|
|
|
|
- for ( s = 0; s < sl; s ++ ) {
|
|
|
+ var slen1 = vlen * s;
|
|
|
+ var slen2 = vlen * ( s + 1 );
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
- var a = layeroffset + j + slen1,
|
|
|
- b = layeroffset + k + slen1,
|
|
|
- c = layeroffset + k + slen2,
|
|
|
- d = layeroffset + j + slen2;
|
|
|
+ f4( a, b, c, d );
|
|
|
|
|
|
- f4( a, b, c, d );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ function v( x, y, z ) {
|
|
|
|
|
|
- function v( x, y, z ) {
|
|
|
+ placeholder.push( x );
|
|
|
+ placeholder.push( y );
|
|
|
+ placeholder.push( z );
|
|
|
|
|
|
- placeholder.push( x );
|
|
|
- placeholder.push( y );
|
|
|
- placeholder.push( z );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function f3( a, b, c ) {
|
|
|
|
|
|
- function f3( a, b, c ) {
|
|
|
+ addVertex( a );
|
|
|
+ addVertex( b );
|
|
|
+ addVertex( c );
|
|
|
|
|
|
- addVertex( a );
|
|
|
- addVertex( b );
|
|
|
- addVertex( c );
|
|
|
+ var nextIndex = verticesArray.length / 3;
|
|
|
+ var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
|
|
|
|
|
|
- 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 ] );
|
|
|
|
|
|
- addUV( uvs[ 0 ] );
|
|
|
- addUV( uvs[ 1 ] );
|
|
|
- addUV( uvs[ 2 ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ function f4( a, b, c, d ) {
|
|
|
|
|
|
- function f4( a, b, c, d ) {
|
|
|
+ addVertex( a );
|
|
|
+ addVertex( b );
|
|
|
+ addVertex( d );
|
|
|
|
|
|
- addVertex( a );
|
|
|
- addVertex( b );
|
|
|
- addVertex( d );
|
|
|
+ addVertex( b );
|
|
|
+ addVertex( c );
|
|
|
+ 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 );
|
|
|
|
|
|
- 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[ 0 ] );
|
|
|
- addUV( uvs[ 1 ] );
|
|
|
- addUV( uvs[ 3 ] );
|
|
|
+ addUV( uvs[ 1 ] );
|
|
|
+ addUV( uvs[ 2 ] );
|
|
|
+ addUV( uvs[ 3 ] );
|
|
|
|
|
|
- addUV( uvs[ 1 ] );
|
|
|
- addUV( uvs[ 2 ] );
|
|
|
- addUV( uvs[ 3 ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ function addVertex( index ) {
|
|
|
|
|
|
- function addVertex( index ) {
|
|
|
+ verticesArray.push( placeholder[ index * 3 + 0 ] );
|
|
|
+ verticesArray.push( placeholder[ index * 3 + 1 ] );
|
|
|
+ verticesArray.push( placeholder[ index * 3 + 2 ] );
|
|
|
|
|
|
- verticesArray.push( placeholder[ index * 3 + 0 ] );
|
|
|
- verticesArray.push( placeholder[ index * 3 + 1 ] );
|
|
|
- verticesArray.push( placeholder[ index * 3 + 2 ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function addUV( vector2 ) {
|
|
|
|
|
|
- function addUV( vector2 ) {
|
|
|
+ uvArray.push( vector2.x );
|
|
|
+ uvArray.push( vector2.y );
|
|
|
|
|
|
- uvArray.push( vector2.x );
|
|
|
- uvArray.push( vector2.y );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( ! options.arrays ) {
|
|
|
-
|
|
|
- this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
|
|
|
- this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
|
|
|
-
|
|
|
- }
|
|
|
+}
|
|
|
|
|
|
-};
|
|
|
+ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
|
|
+ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
|
|
|
|
|
|
-ExtrudeGeometry.WorldUVGenerator = {
|
|
|
+var WorldUVGenerator = {
|
|
|
|
|
|
generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
|
|
|
|