Issues with 3D text loader and Three.csg

Issues with 3D text loader

I’m encountering a puzzling issue while attempting to perform CSG operations on text geometries using the three-bvh-csg library. The library is designed for constructive solid geometry (CSG) in Three.js.

import * as THREE from 'three';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls';
import { Brush, Evaluator, ADDITION } from "three-bvh-csg";

const evaluator = new Evaluator();
const loader = new FontLoader();
let renderer, camera, scene, textMesh;

const modelViewerWidth = (window.innerWidth / 4) * 3;
const modelViewerHeight = window.innerHeight;

let height = 1;
let size = 5;

init();

async function init() {
    // create the scene and set a background color
    scene = new THREE.Scene();
    scene.background = new THREE.Color("#dadada");

    camera = new THREE.PerspectiveCamera(50, modelViewerWidth / modelViewerHeight, 1, 100);
    camera.position.set(0, 40, 20);

    // set up the renderer and the size of the model viewer
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(modelViewerWidth, modelViewerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;

    const controls = new OrbitControls(camera, renderer.domElement);

    // add the renderer to the modelViewer element
    document.getElementById("modelViewer").appendChild(renderer.domElement);

    // add the gridHelper to show orientation
    const gridHelper = new THREE.GridHelper(100, 100);
    scene.add(gridHelper);

    // Initialize with default text
    updateTextMesh(document.getElementById("inputText").value);

    render();
}

let brush1, brush2;

function updateTextMesh(newText) {
    if (textMesh) {
        scene.remove(textMesh);
    }

    loader.load('Roboto Black_Regular.json', function (font) {
        const geometry = new TextGeometry(newText, {
            font: font,
            size: size,
            height: height,
            curveSegments: 40,
        });

        textMesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: "#01509D" }));
        
        // Center the textMesh
        geometry.computeBoundingBox();
        const boundingBox = geometry.boundingBox;
        const centerOffset = new THREE.Vector3();
        centerOffset.subVectors(boundingBox.max, boundingBox.min);
        centerOffset.multiplyScalar(-0.5);
        textMesh.position.add(centerOffset);

        // Set the y position to place the textMesh on the plane
        textMesh.position.y = 0;

        textMesh.rotation.x = Math.PI * -0.5;
        
        const textMesh2 = textMesh.clone();
        textMesh2.material =  new THREE.MeshBasicMaterial({ color: "#ff0000" });
        textMesh2.scale.set(0.9, 0.9, 2);
        
        brush1 = new Brush(textMesh.geometry, new THREE.MeshBasicMaterial({ color: "#ff0000" }));
        brush2 = new Brush(textMesh2.geometry, new THREE.MeshBasicMaterial({ color: "#ff0000" }));

        const result = evaluator.evaluate(brush1, brush2, ADDITION);
        scene.add(result);
    });
}

function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}



// Update text on input change
document.getElementById("inputText").addEventListener("input", function (event) {
    updateTextMesh(document.getElementById("inputText").value);
});

// Update height on input change
document.getElementById("modelHeight").addEventListener("input", () => {
    height = document.getElementById("modelHeight").value;
    updateTextMesh(document.getElementById("inputText").value);
});

document.getElementById("textSize").addEventListener("input", () => {
    size = document.getElementById("textSize").value;
    updateTextMesh(document.getElementById("inputText").value);
})

This is how the letters look after addition
image
This is how the letters look after subtraction
image

Additional Notes:

  • No error messages are displayed in the console.
  • The issue is specific to text geometries; other geometries seem to behave as expected.

Thanks!

Duplicate?

No, that was about bufferGeometries and SVGLoaders, this is just 3D-text