3d-viewer/app/three/utils/build-meshes.ts
2025-02-26 14:01:38 +01:00

86 lines
2.5 KiB
TypeScript

import {
BufferAttribute,
BufferGeometry,
DoubleSide,
FrontSide,
Group,
Mesh,
MeshStandardMaterial,
} from "three";
import { uniforms } from "./uniforms";
import { shader } from "./shader";
import { fetchTriangleIndices } from "./fetch-triangle-indices";
import { fetchVertices } from "./fetch-vertices";
import { TRIANGLE_INDICES_URL, VERTICES_URL } from "../config";
interface MappedFeature {
featuregeom_id: number;
name: string;
geologicdescription: { "feature type": string; citation: string | null };
preview: { legend_color: string; legend_text: string };
}
async function buildMesh(layerData: MappedFeature) {
const color = `#${layerData.preview.legend_color}`;
const name = layerData.preview.legend_text;
const geomId = layerData.featuregeom_id.toString();
const geometry = new BufferGeometry();
const vertices = await fetchVertices(VERTICES_URL, geomId);
const positions = new BufferAttribute(vertices, 3);
geometry.setAttribute("position", positions);
const indexArray = await fetchTriangleIndices(TRIANGLE_INDICES_URL, geomId);
const indices = new BufferAttribute(indexArray, 1);
geometry.setIndex(indices);
geometry.scale(1, 1, 1);
geometry.computeBoundingSphere();
geometry.computeVertexNormals();
geometry.computeBoundingBox();
const material = new MeshStandardMaterial({
color: color,
metalness: 0.1,
roughness: 0.75,
flatShading: true,
side: FrontSide,
wireframe: false,
});
// material.onBeforeCompile = (materialShader) => {
// materialShader.uniforms.clippingLow = uniforms.clipping.clippingLow;
// materialShader.uniforms.clippingHigh = uniforms.clipping.clippingHigh;
// materialShader.uniforms.clippingScale = uniforms.clipping.clippingScale;
// materialShader.vertexShader = shader.vertexMeshStandard;
// materialShader.fragmentShader = shader.fragmentClippingMeshStandard;
// };
const mesh = new Mesh(geometry, material);
mesh.name = name;
mesh.userData.layerId = geomId;
mesh.castShadow = true;
mesh.receiveShadow = true;
// modelNode should be a THREE.Group object where all the model data gets added to
// in the original code modelNode is a direct reference to a THREE.Scene
// if (modelNode) {
// modelNode.add(mesh);
// }
return mesh;
}
export async function buildMeshes(mappedFeatures: MappedFeature[]) {
const meshes = [];
for (let i = 0; i < mappedFeatures.length; i++) {
const layerData = mappedFeatures[i];
const mesh = await buildMesh(layerData);
meshes.push(mesh);
}
return meshes;
}