In my addons hofk (Klaus Hoffmeister) · GitHub I defined the geometry myself. Old geometry, indexed and non-indexed.
The example of @prisoner849 and my one based on it ( Bend cylinder on specific path - #4 by prisoner849 ) change a CylinderGeometry.
There without caps.
For another project I also change the caps.
Therefore I looked into the three.js sourccode. There you find for the CircleGeometry the expected variant for an indexed geometry. The center is a vertex.
For the CylinderGeometry caps, however, an extra vertex is created for each triangle. This is actually the procedure for non-indexed geometry.
I have changed the function to only one vertex for the center. Works of course.
See code below. The changes are marked or commented.
Is there a reason (e.g. usage in another part of the framework) for the duplicated centers of the caps?
My problem is that I rely on continuity when using CylinderGeometry. If the definition is ever changed, my modification will no longer work.
The multiplied centers also make more effort.
The changed function:
function generateCap( top ) {
// save the index of the first center vertex
// const centerIndexStart = index; // is no longer required in case of change
const uv = new Vector2();
const vertex = new Vector3();
let groupCount = 0;
const radius = ( top ) ? radiusTop : radiusBottom; // const radius = ( top === true ) ? radiusTop : radiusBottom;
const sign = ( top ) ? 1 : - 1; // const sign = ( top === true ) ? 1 : - 1;
// first we generate the center vertex data of the cap.
// because the geometry needs one set of uvs per face, // ??? why
// we must generate a center vertex per face/segment // ???
// for ( let x = 1; x <= radialSegments; x ++ ) { // No loop here, only one vertex
// vertex
vertices.push( 0, halfHeight * sign, 0 );
// normal
normals.push( 0, sign, 0 );
// uv
uvs.push( 0.5, 0.5 );
// increase index
// index ++; // see below: index ++; // added for bottom
//} // No loop here, only one vertex
// save the index of the last center vertex
const centerIndex = index; //const centerIndexEnd = index; // only one index after change
// now we generate the surrounding vertices, normals and uvs
for ( let x = 0; x <= radialSegments; x ++ ) {
const u = x / radialSegments;
const theta = u * thetaLength + thetaStart;
const cosTheta = Math.cos( theta );
const 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 ++;
}
index ++; // after change added for bottom
// generate indices
for ( let x = 1; x <= radialSegments; x ++ ) { // for ( let x = 0; x < radialSegments; x ++ ) { // x = 0 to x = 1 , < to <=
const c = centerIndex; // const c = centerIndexStart + x; // only one index after change
const i = centerIndex + x; // const i = centerIndexEnd + x; // only one index after change
if ( top ) { // 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;
}
}
Addendum
I have now noticed that the description of the start angle in the docs does not fit.
thetaStart — Start angle for first segment, default = 0 (three o’clock position).
The mantle starts from +z.
However, the uv values of the upper cap are aligned to + x.
const mat1 = new THREE.MeshBasicMaterial( {
wireframe: false, side: THREE.DoubleSide, map: new THREE.TextureLoader( ).load( 'uvgrid01.png')
} );
const geometry = new THREE.CylinderGeometry( 1, 1, 2, 32, 5, false, Math.PI / 4, Math.PI );
const cylinder = new THREE.Mesh( geometry, mat1 );
scene.add( cylinder );