function createOpenSurfaceShellMeshWithNormalsAndRoundEdges(triangleMesh, radius) {
	if (triangleMesh.normals.length == 0) {
		triangleMesh.computeSmoothNormals();
	}
	
	let newIndices = [];
	let newVertices = [];
	
	// Create two copies of the indices and vertices
	newIndices = triangleMesh.indices.concat(
		triangleMesh.indices.map(i => i + triangleMesh.vertices.length)
	);
	newVertices = triangleMesh.vertices.concat(triangleMesh.vertices);
	
	// Invert the winding order of the second copy indices
	for (let i = 0; i < triangleMesh.indices.length; i += 3) {
		let tmp = newIndices[i];
		newIndices[i] = newIndices[i+2];
		newIndices[i+2] = tmp;
	}
	
	// Push vertices in and out using the stored normal
	for (let i = 0; i < triangleMesh.vertices.length; i++) {
		let v = triangleMesh.vertices[i];
		let n = triangleMesh.normals[i];
		let positiveOffset = vec3mul(radius, n);
		let negativeOffset = vec3mul(-radius, n);
		newVertices[i] = vec3add(v, negativeOffset);
		newVertices[i + triangleMesh.vertices.length] = vec3add(v, positiveOffset);
	}
	
	// Create the rounded edges (approximated by tubes using half-circles).
	// TODO: Let the user specify the number of half-circle segments for rounded edges.
	let numSegments = 8;
    addTubesOnBorderEdges(triangleMesh, triangleMesh.vertices, triangleMesh.indices, newVertices, newIndices, numSegments, radius);
	
	let newTriangleMesh = new TriangleMesh();
	newTriangleMesh.indices = newIndices;
	newTriangleMesh.vertices = newVertices;
	return newTriangleMesh;
}
/**
 * Computes the shell of a (usually open) surface with a certain radius.
 * The edges are rounded (use @see createOpenSurfaceShellMeshWithNormals for hard edges).
 * The shell is extruded by offsetting all normals along their (averaged) normal.
 * This can cause some distortions for large radii. Thus, implementing a more correct algorithm
 * would be beneficial for these cases (eventual TODO).
 * @param {TriangleMesh} triangleMesh The triangle mesh to compute the shell of.
 * @param {number} radius The radius of the surface shell.
 */
Computes the shell of a (usually open) surface with a certain radius.
The edges are rounded (use @see createOpenSurfaceShellMeshWithNormals for hard edges).
The shell is extruded by offsetting all normals along their (averaged) normal.
This can cause some distortions for large radii. Thus, implementing a more correct algorithm
would be beneficial for these cases (eventual TODO).
@param {TriangleMesh} triangleMesh The triangle mesh to compute the shell of.
@param {number} radius The radius of the surface shell.
Computes the shell of a ( usually open ) surface with a certain radius . The edges are rounded ( use @see createOpenSurfaceShellMeshWithNormals for hard edges ) . The shell is extruded by offsetting all normals along their ( averaged ) normal . This can cause some distortions for large radii . Thus implementing a more correct algorithm would be beneficial for these cases ( eventual TODO ) . @param { TriangleMesh } triangleMesh The triangle mesh to compute the shell of . @param { number } radius The radius of the surface shell .
function createOpenSurfaceShellMeshWithNormalsAndRoundEdges(triangleMesh, radius) {
	if (triangleMesh.normals.length == 0) {
		triangleMesh.computeSmoothNormals();
	}
	let newIndices = [];
	let newVertices = [];
	newIndices = triangleMesh.indices.concat(
		triangleMesh.indices.map(i => i + triangleMesh.vertices.length)
	);
	newVertices = triangleMesh.vertices.concat(triangleMesh.vertices);
	for (let i = 0; i < triangleMesh.indices.length; i += 3) {
		let tmp = newIndices[i];
		newIndices[i] = newIndices[i+2];
		newIndices[i+2] = tmp;
	}
	for (let i = 0; i < triangleMesh.vertices.length; i++) {
		let v = triangleMesh.vertices[i];
		let n = triangleMesh.normals[i];
		let positiveOffset = vec3mul(radius, n);
		let negativeOffset = vec3mul(-radius, n);
		newVertices[i] = vec3add(v, negativeOffset);
		newVertices[i + triangleMesh.vertices.length] = vec3add(v, positiveOffset);
	}
	let numSegments = 8;
    addTubesOnBorderEdges(triangleMesh, triangleMesh.vertices, triangleMesh.indices, newVertices, newIndices, numSegments, radius);
	let newTriangleMesh = new TriangleMesh();
	newTriangleMesh.indices = newIndices;
	newTriangleMesh.vertices = newVertices;
	return newTriangleMesh;
}
function createOpenSurfaceShellMeshWithNormalsAndRoundEdges ( triangleMesh , radius ) { if ( triangleMesh . normals . length == 0 ) { triangleMesh . computeSmoothNormals ( ) ; } let newIndices = [ ] ; let newVertices = [ ] ; newIndices = triangleMesh . indices . concat ( triangleMesh . indices . map ( i => i + triangleMesh . vertices . length ) ) ; newVertices = triangleMesh . vertices . concat ( triangleMesh . vertices ) ; for ( let i = 0 ; i < triangleMesh . indices . length ; i += 3 ) { let tmp = newIndices [ i ] ; newIndices [ i ] = newIndices [ i + 2 ] ; newIndices [ i + 2 ] = tmp ; } for ( let i = 0 ; i < triangleMesh . vertices . length ; i ++ ) { let v = triangleMesh . vertices [ i ] ; let n = triangleMesh . normals [ i ] ; let positiveOffset = vec3mul ( radius , n ) ; let negativeOffset = vec3mul ( - radius , n ) ; newVertices [ i ] = vec3add ( v , negativeOffset ) ; newVertices [ i + triangleMesh . vertices . length ] = vec3add ( v , positiveOffset ) ; } let numSegments = 8 ; addTubesOnBorderEdges ( triangleMesh , triangleMesh . vertices , triangleMesh . indices , newVertices , newIndices , numSegments , radius ) ; let newTriangleMesh = new TriangleMesh ( ) ; newTriangleMesh . indices = newIndices ; newTriangleMesh . vertices = newVertices ; return newTriangleMesh ; }
Computes the shell of a (usually open) surface with a certain radius.
Computes the shell of a ( usually open ) surface with a certain radius .
// Create two copies of the indices and vertices // Invert the winding order of the second copy indices // Push vertices in and out using the stored normal // Create the rounded edges (approximated by tubes using half-circles). // TODO: Let the user specify the number of half-circle segments for rounded edges.