Three.js SVG Loader - can I simplify or fix geometry?

clock icon

asked 6 months ago Asked

message

1 Answers

eye

22 Views

I have imported an SVG shape of the letter 'M' into Three.js using SVG Loader. The geometry that is being created seems unecessarily complex and is causing issues.

Is there a way to achieve cleaner, more simple geomtery? I don't know if it's to do with SVG Loader, or the way I'm setting up the SVG file itself. Perhaps I need to create the shape in 3D and import it that way?

As you can see from the wireframe, the geometry isn't as neat and clean and simple as it could be. There seem to be extra polygons.

I am using SVG Renderer and the issue this causes is that the resulting SVG has these spurs where all the geometry points meet and overlap a little.

Any help would be greatly appreciated.

I have tried simplifying the svg file by removing any extrenous points.

Here is the SVG markup:

<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151.72 165.95">
  <path class="cls-1" d="M0,0h19.14l56.72,124.64L132.58,0h19.14v165.95h-19.37V44.35l-46.68,103.17h-19.61L19.37,44.35v121.61H0V0Z"/>
</svg>

Here is the SVG Renderer setup:

renderer = new SVGRenderer(); // Init a renderer
renderer.overdraw = 0.58; // Allow three.js to render overlapping lines
renderer.setSize( mainWidth, mainHeight );
mainElement.appendChild(renderer.domElement); // Add the renderer in the DOM
renderer.domElement.setAttribute('xmlns' ,'http://www.w3.org/2000/svg'); // Add the xmlns attribute

Here is the SVG Loader setup:

// Load SVG and create mesh
const loader = new SVGLoader();
loader.load('svg/m.svg', function (data) {
    const paths = data.paths;
    const shapes = [];
    paths.forEach((path) => {
        path.toShapes(true).forEach((shape) => {
            shapes.push(shape);
        });
    });

    mesh = createExtrudedMesh(shapes);
    scene.add(mesh);

    // Depth control
    const depthControl = document.getElementById('depth');
    depthControl.addEventListener('input', (event) => {
        const depth = event.target.value;
        extrudeSettings.depth = parseFloat(depth);
        
        // Remove the old mesh and add a new one
        scene.remove(mesh);
        mesh = createExtrudedMesh(shapes);
        scene.add(mesh);
    });

    animate();
});



// Render loop
function animate() {
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene, camera);
}

1 Answers

Hey there,

I understand the frustration with the complex geometry generated by the SVG Loader. Let's break down a few things to simplify your 'M' shape:

1. SVG Source Optimization:

  • Simplify the Path: Before loading the SVG, use a vector editing tool like Inkscape or Adobe Illustrator to reduce unnecessary points and curves in the 'M' path. The simpler the path, the less complex the resulting geometry.

2. SVG Loader Settings:

  • autoCurveThreshold: This setting controls how the loader converts curves into straight line segments. Experiment with lower values (e.g., 0.2 or 0.5) to simplify the geometry. However, be mindful that too low a value might compromise the shape's smoothness.

3. Post-Processing Geometry (with caution):

  • BufferGeometryUtils.mergeVertices: This can sometimes merge duplicate vertices, reducing the number of polygons. But use it judiciously, as it might impact shading and visual quality.

4. Alternative Approach: Extrude a Simple Shape:

  • If you don't need the exact precision of the SVG, create a simple 2D shape (e.g., a rectangle or polygon) and extrude it. This can be much faster and more efficient.

Code Example (Adjust autoCurveThreshold):

JavaScript
 

Write your answer here

Top Questions