Mesh within non-planar Boundary

Dear community,

I am nearing complete madness.

I need to create a mesh from a set of three-dimensional points.
An example of such a point-array is given below (string with x y z coordinates separated by a space).
The points are given in a specific order that form a linear ring and the first point in the array is the same as the last one so that the boundary is closed. The point coordinates come from a cityGML file and define various surfaces of buildings (roof, wall…).

To give you a feel on what the mesh should look like, I created a LineLoop like seen in the code below (using react-three-fiber, but that should be irrelevant).

But I can´t get my head around how to create a mesh within that boundary!
I would probably sooner or later find out how to draw a 2D-Shape from this and rotate it back up, BUT the mesh geometry is expected to be not perfectly planar!

Viewing the mesh in various modeling softwares it shows that triangulation will be necessary, but I am too stupid to apply the common libraries for triangulations to this three-dimensional geometry.

Please help me or I will lose my mind.

CODE TO CREATE THE LINE LOOP:

const vertices = new Float32Array(points.flat());
const geometry = new BufferGeometry();
geometry.setAttribute("position", new BufferAttribute(vertices, 3));

const material = new MeshBasicMaterial({ color: "red" });

return (
   <lineLoop geometry={geometry} material={material} />
);

STRING ARRAY OF THE POINTS:

“644046.36 5482714.13 305.265 644049.74 5482712.62 305.369 644049.64 5482712.401 305.03 644050.497 5482711.999 305.03 644050.6 5482712.23 305.387 644053.12 5482711.09 305.444 644053 5482710.822 305.03 644054.097 5482710.306 305.03 644054.23 5482710.6 305.485 644056.987 5482709.365 305.562 644059.244 5482714.344 313.266 644059.283 5482714.431 313.4 644028.212 5482729.037 313.4 644027.811 5482728.151 312.029 644028.04 5482728.04 312.024 644025.31 5482722.52 303.341 644030.43 5482720.17 303.414 644030.336 5482719.968 303.1 644033.618 5482718.425 303.1 644033.73 5482718.67 303.48 644039.12 5482716.13 303.473 644039.08 5482716.04 303.334 644045.77 5482712.88 303.316 644046.36 5482714.13 305.265”

LINE LOOP TO DEMONSTRATE THE INTENDED MESH GEOMETRY:

Have you tried the EarCut triangulation from Three.js?

Thank you for the recommendation!
I tried it and below is a picture of the result.
For some geometries, for example the one I posted before (one roof surface) it worked perfectly, but for some reason the smaller areas (side walls) don´t seem to work. Why could this be?

Every surface I have in the sample points array is correctly rendered with the line loop but not with earcut.

This is the code I used:

const EarcutGeometry = ({ points }) => {
    const mesh = useMemo(() => {

        const flattenedPoints = points.flat();
        const triangles = Earcut.triangulate(flattenedPoints, null, 3);

        const vertices = [];
        for (let i = 0; i < points.length; i++) {
            vertices.push(new Vector3(...points[i]));
        }

        const geometry = new BufferGeometry().setFromPoints(vertices);
        const indices = [];
        for (let i = 0; i < triangles.length; i += 3) {
            indices.push(triangles[i], triangles[i + 1], triangles[i + 2]);
        }
        geometry.setIndex(indices);
        geometry.computeVertexNormals(); // To smooth out the lighting

        const material = new MeshBasicMaterial({
            color: 0x00ff00,
            side: DoubleSide,
        });

        return <mesh geometry={geometry} material={material} />;
    }, [points]);

    return mesh;
};

Also it might be worth mentioning that when I leave the point coordinates untreated (with the really high numbers) the rendering gets messy. When I move everything closer to 0 the rendering gets fine.

and this is my points array:

const points= [
    "644063.47 5482714.13 293.67 644062.09 5482711.29 293.67 644063.02 5482710.31 293.67 644062.12 5482709.46 293.67 644061.21 5482710.39 293.67 644058.28 5482709.27 293.67 644058.23 5482707.98 293.67 644057.01 5482708 293.67 644057.02 5482709.35 293.67 644054.23 5482710.6 293.67 644053.67 5482709.36 293.67 644052.57 5482709.86 293.67 644053.12 5482711.09 293.67 644050.6 5482712.23 293.67 644050.05 5482711 293.67 644049.18 5482711.39 293.67 644049.74 5482712.62 293.67 644046.36 5482714.13 293.67 644045.77 5482712.88 293.67 644039.08 5482716.04 293.67 644039.12 5482716.13 293.67 644033.73 5482718.67 293.67 644032.62 5482716.25 293.67 644029.32 5482717.77 293.67 644030.43 5482720.17 293.67 644025.31 5482722.52 293.67 644028.04 5482728.04 293.67 644021.12 5482731.4 293.67 644024.64 5482738.67 293.67 644038.01 5482732.17 293.67 644037.95 5482732.04 293.67 644041.33 5482730.36 293.67 644049.21 5482726.61 293.67 644049.64 5482727.5 293.67 644051.33 5482730.99 293.67 644051.68 5482731.72 293.67 644056.21 5482729.57 293.67 644056.58 5482730.33 293.67 644057.37 5482729.95 293.67 644057 5482729.19 293.67 644061.56 5482727.03 293.67 644058.54 5482720.53 293.67 644061.58 5482719.31 293.67 644062.57 5482720.22 293.67 644063.4 5482719.33 293.67 644062.46 5482718.38 293.67 644063.49 5482715.42 293.67 644064.85 5482715.37 293.67 644064.81 5482714.14 293.67 644063.47 5482714.13 293.67",
    "644028.212 5482729.037 313.4 644027.811 5482728.151 314.864 644027.811 5482728.151 312.029 644028.212 5482729.037 313.4",
    "644062.46 5482718.38 293.67 644063.4 5482719.33 293.67 644063.4 5482719.33 303.291 644062.59 5482718.512 304 644062.59 5482718.512 305.03 644062.46 5482718.38 305.316 644062.46 5482718.38 293.67",
    "644063.02 5482710.31 293.67 644063.02 5482710.31 303.323 644062.12 5482709.46 303.321 644062.12 5482709.46 293.67 644063.02 5482710.31 293.67",
    "644046.36 5482714.13 293.67 644046.36 5482714.13 305.265 644045.77 5482712.88 303.316 644045.77 5482712.88 293.67 644046.36 5482714.13 293.67",
    "644062.09 5482711.29 293.67 644063.47 5482714.13 293.67 644063.47 5482714.13 305.18 644063.369 5482713.922 305.358 644062.209 5482711.535 305.504 644062.09 5482711.29 305.314 644062.09 5482711.29 293.67",
    "644038.01 5482732.17 293.67 644038.01 5482732.17 302.852 644037.95 5482732.04 303.067 644037.95 5482732.04 293.67 644038.01 5482732.17 293.67",
    "644050.05 5482711 293.67 644050.6 5482712.23 293.67 644050.6 5482712.23 305.387 644050.497 5482711.999 305.03 644050.497 5482711.999 304 644050.05 5482711 303.359 644050.05 5482711 293.67",
    "644030.336 5482719.968 303.1 644030.336 5482719.968 300.146 644033.564 5482718.45 300.134 644033.564 5482718.45 297.88 644033.618 5482718.425 297.88 644033.618 5482718.425 303.1 644030.336 5482719.968 303.1",
    "644059.244 5482714.344 313.266 644059.206 5482714.26 313.4 644062.533 5482718.171 305.469 644062.46 5482718.38 305.316 644062.59 5482718.512 305.03 644061.68 5482719.402 305.03 644061.58 5482719.31 305.24 644061.507 5482719.339 305.296 644059.244 5482714.344 313.266",
    "644063.369 5482713.922 305.358 644063.47 5482714.13 305.18 644063.548 5482714.131 305.03 644063.602 5482715.416 305.03 644063.49 5482715.42 305.246 644063.443 5482715.555 305.347 644059.206 5482714.26 313.4 644063.369 5482713.922 305.358",
    "644046.36 5482714.13 305.265 644049.74 5482712.62 305.369 644049.64 5482712.401 305.03 644050.497 5482711.999 305.03 644050.6 5482712.23 305.387 644053.12 5482711.09 305.444 644053 5482710.822 305.03 644054.097 5482710.306 305.03 644054.23 5482710.6 305.485 644056.987 5482709.365 305.562 644059.244 5482714.344 313.266 644059.283 5482714.431 313.4 644028.212 5482729.037 313.4 644027.811 5482728.151 312.029 644028.04 5482728.04 312.024 644025.31 5482722.52 303.341 644030.43 5482720.17 303.414 644030.336 5482719.968 303.1 644033.618 5482718.425 303.1 644033.73 5482718.67 303.48 644039.12 5482716.13 303.473 644039.08 5482716.04 303.334 644045.77 5482712.88 303.316 644046.36 5482714.13 305.265",
];

Yes, big numbers are an issue (not with Three.js, but with WebGL).

As for the side walls, my only guess is that the triangulation might fail for vertical shapes. Could you try with one specific failing wall:

  • rotate it horizontally by swapping coodinates: e.g. XYZ → YXZ or XZY – pick swapping that make the wall most horizontal
  • triangulate
  • rotate it back by swapping coordinates to their original order

Thanks again. Yes, I read up on Earcut and it really ignores the z-axis!
Rotating solves the problem!