blockMesh = {
const blockWidth = 1;
const blockHeight = 0.03;
const terrainHeight = 0.036;
const rasterWidth = demData.length;
const xy = blockWidth / 2;
const z = blockHeight / 2;
const demRangeScale = d3.scaleLinear().domain(d3.extent(demData.flat())).range([0, terrainHeight]);
const dataVertices = demData
.map((row, i) => row.map((height, j) => ({
vertex: [
-xy + j * blockWidth / rasterWidth,
z + demRangeScale(height),
-xy + i * blockWidth / rasterWidth,
],
uv: [j / rasterWidth, i / rasterWidth]
})));
const vertices = [];
const faces = [];
const uvs = [];
let currentVertexCount = 0;
const vertexIndexes = [];
for (let rowIndex = 0; rowIndex < rasterWidth - 1; rowIndex++) {
for (let colIndex = 0; colIndex < rasterWidth - 1; colIndex++) {
const bottomRight = dataVertices[rowIndex + 1][colIndex + 1];
vertices.push(bottomRight.vertex);
uvs.push(bottomRight.uv);
const bottomRightIndex = currentVertexCount++;
vertexIndexes[`${rowIndex + 1}|${colIndex + 1}`] = bottomRightIndex;
let topLeftIndex = vertexIndexes[`${rowIndex}|${colIndex}`];
if (!topLeftIndex) {
const topLeft = dataVertices[rowIndex][colIndex];
vertices.push(topLeft.vertex);
uvs.push(topLeft.uv);
topLeftIndex = currentVertexCount++;
vertexIndexes[`${rowIndex}|${colIndex}`] = topLeftIndex;
}
let topRightIndex = vertexIndexes[`${rowIndex}|${colIndex + 1}`];
if (!topRightIndex) {
const topRight = dataVertices[rowIndex][colIndex + 1];
vertices.push(topRight.vertex);
uvs.push(topRight.uv);
topRightIndex = currentVertexCount++;
vertexIndexes[`${rowIndex}|${colIndex + 1}`] = topRightIndex;
}
let bottomLeftIndex = vertexIndexes[`${rowIndex + 1}|${colIndex}`];
if (!bottomLeftIndex) {
const bottomLeft = dataVertices[rowIndex + 1][colIndex];
vertices.push(bottomLeft.vertex);
uvs.push(bottomLeft.uv);
bottomLeftIndex = currentVertexCount++;
vertexIndexes[`${rowIndex + 1}|${colIndex}`] = bottomLeftIndex;
}
faces.push([topLeftIndex, topRightIndex, bottomLeftIndex]);
faces.push([bottomLeftIndex, topRightIndex, bottomRightIndex]);
}
}
// Create and add vertices, uvs, and faces for the bottom
[[-xy, -z, -xy], [+xy, -z, -xy], [+xy, -z, +xy], [-xy, -z, +xy]].forEach(v => {
vertices.push(v);
uvs.push([1, 0]);
});
faces.push(
[vertices.length - 1, vertices.length - 2, vertices.length - 3],
[vertices.length - 3, vertices.length - 1, vertices.length - 4]
);
// Create and add the vertices, uvs, and faces for the sides
// Head spinning repetitive code hell
for (let i = 0; i < rasterWidth - 1; i++) {
currentVertexCount = vertices.length;
const s4 = [[0, i], [0, i + 1]];
const h4 = s4.map(d => demData[d[0]][d[1]]);
const s3 = [[rasterWidth - i - 1, 0], [rasterWidth - i - 2, 0]];
const h3 = s3.map(d => demData[d[0]][d[1]]);
const s2 = [[rasterWidth - 1, rasterWidth - i - 1], [rasterWidth - 1, rasterWidth - i - 2]];
const h2 = s2.map(d => demData[d[0]][d[1]]);
const s1 = [[i, rasterWidth - 1], [i + 1, rasterWidth - 1]];
const h1 = s1.map(d => demData[d[0]][d[1]]);
vertices.push(
[-xy + s1[0][1] / rasterWidth * blockWidth, -z, -xy + s1[0][0] / rasterWidth * blockWidth],
[-xy + s1[1][1] / rasterWidth * blockWidth, -z, -xy + s1[1][0] / rasterWidth * blockWidth],
[-xy + s1[0][1] / rasterWidth * blockWidth, z + demRangeScale(h1[0]), -xy + s1[0][0] / rasterWidth * blockWidth],
[-xy + s1[1][1] / rasterWidth * blockWidth, z + demRangeScale(h1[1]), -xy + s1[1][0] / rasterWidth * blockWidth],
[-xy + s2[0][1] / rasterWidth * blockWidth, -z, -xy + s2[0][0] / rasterWidth * blockWidth],
[-xy + s2[1][1] / rasterWidth * blockWidth, -z, -xy + s2[1][0] / rasterWidth * blockWidth],
[-xy + s2[0][1] / rasterWidth * blockWidth, z + demRangeScale(h2[0]), -xy + s2[0][0] / rasterWidth * blockWidth],
[-xy + s2[1][1] / rasterWidth * blockWidth, z + demRangeScale(h2[1]), -xy + s2[1][0] / rasterWidth * blockWidth],
[-xy + s3[0][1] / rasterWidth * blockWidth, -z, -xy + s3[0][0] / rasterWidth * blockWidth],
[-xy + s3[1][1] / rasterWidth * blockWidth, -z, -xy + s3[1][0] / rasterWidth * blockWidth],
[-xy + s3[0][1] / rasterWidth * blockWidth, z + demRangeScale(h3[0]), -xy + s3[0][0] / rasterWidth * blockWidth],
[-xy + s3[1][1] / rasterWidth * blockWidth, z + demRangeScale(h3[1]), -xy + s3[1][0] / rasterWidth * blockWidth],
[-xy + s4[0][1] / rasterWidth * blockWidth, -z, -xy + s4[0][0] / rasterWidth * blockWidth],
[-xy + s4[1][1] / rasterWidth * blockWidth, -z, -xy + s4[1][0] / rasterWidth * blockWidth],
[-xy + s4[0][1] / rasterWidth * blockWidth, z + demRangeScale(h4[0]), -xy + s4[0][0] / rasterWidth * blockWidth],
[-xy + s4[1][1] / rasterWidth * blockWidth, z + demRangeScale(h4[1]), -xy + s4[1][0] / rasterWidth * blockWidth],
);
faces.push(
[currentVertexCount, currentVertexCount + 1, currentVertexCount + 2],
[currentVertexCount + 1, currentVertexCount + 2, currentVertexCount + 3],
[currentVertexCount + 4, currentVertexCount + 5, currentVertexCount + 6],
[currentVertexCount + 5, currentVertexCount + 6, currentVertexCount + 7],
[currentVertexCount + 8, currentVertexCount + 9, currentVertexCount + 10],
[currentVertexCount + 9, currentVertexCount + 10, currentVertexCount + 11],
[currentVertexCount + 12, currentVertexCount + 13, currentVertexCount + 14],
[currentVertexCount + 13, currentVertexCount + 14, currentVertexCount + 15],
);
for (let j = 0; j < 16; j++) uvs.push([1, 0]);
}
return { vertices, faces, uvs };
}