This question was asked many times on SO, but there hasn’t been any appropriate and simple solution so far. I can’t say though that mine is just what we need, but anyway, here it is. Based on the method .toGrid() from this showcase Grids of Waves (shaders).

https://jsfiddle.net/prisoner849/8hqy99jj/
GridBoxGeometry. Takes two parameters.
The first one geometry is of the type THREE.BoxBufferGeometry.
The second one independent is optional boolean. Default value is false. If set to true, the resulting geometry will have a cloned copy of the buffer attribute position from the first parameter, otherwise, it shares this attribute.
Criticism is very welcomed.
function GridBoxGeometry(geometry, independent) {
if (!(geometry instanceof THREE.BoxBufferGeometry)) {
console.log("GridBoxGeometry: the parameter 'geometry' has to be of the type THREE.BoxBufferGeometry");
return geometry;
}
independent = independent !== undefined ? independent : false;
let newGeometry = new THREE.BoxBufferGeometry();
let position = geometry.attributes.position;
newGeometry.attributes.position = independent === false ? position : position.clone();
let segmentsX = geometry.parameters.widthSegments || 1;
let segmentsY = geometry.parameters.heightSegments || 1;
let segmentsZ = geometry.parameters.depthSegments || 1;
let startIndex = 0;
let indexSide1 = indexSide(segmentsZ, segmentsY, startIndex);
startIndex += (segmentsZ + 1) * (segmentsY + 1);
let indexSide2 = indexSide(segmentsZ, segmentsY, startIndex);
startIndex += (segmentsZ + 1) * (segmentsY + 1);
let indexSide3 = indexSide(segmentsX, segmentsZ, startIndex);
startIndex += (segmentsX + 1) * (segmentsZ + 1);
let indexSide4 = indexSide(segmentsX, segmentsZ, startIndex);
startIndex += (segmentsX + 1) * (segmentsZ + 1);
let indexSide5 = indexSide(segmentsX, segmentsY, startIndex);
startIndex += (segmentsX + 1) * (segmentsY + 1);
let indexSide6 = indexSide(segmentsX, segmentsY, startIndex);
let fullIndices = [];
fullIndices = fullIndices.concat(indexSide1);
fullIndices = fullIndices.concat(indexSide2);
fullIndices = fullIndices.concat(indexSide3);
fullIndices = fullIndices.concat(indexSide4);
fullIndices = fullIndices.concat(indexSide5);
fullIndices = fullIndices.concat(indexSide6);
newGeometry.setIndex(fullIndices);
function indexSide(x, y, shift) {
let indices = [];
for (let i = 0; i < y + 1; i++) {
let index11 = 0;
let index12 = 0;
for (let j = 0; j < x; j++) {
index11 = (x + 1) * i + j;
index12 = index11 + 1;
let index21 = index11;
let index22 = index11 + (x + 1);
indices.push(shift + index11, shift + index12);
if (index22 < ((x + 1) * (y + 1) - 1)) {
indices.push(shift + index21, shift + index22);
}
}
if ((index12 + x + 1) <= ((x + 1) * (y + 1) - 1)) {
indices.push(shift + index12, shift + index12 + x + 1);
}
}
return indices;
}
return newGeometry;
};

