PerfectVector
Par Irene Kim10 min de lecture

Three.js SVGLoader : transformer un dessin plat en maillage 3D

Charge des tracés SVG dans Three.js, préserve une vraie ouverture, corrige l’orientation verticale et dimensionne un maillage extrudé avec un exemple reproductible.

Sur cette page

Pour transformer un dessin SVG plat en maillage Three.js, charge le SVG, convertis ses tracés en formes, puis transmets ces formes à ExtrudeGeometry. Vérifie les trous, l’orientation verticale et les dimensions avant d’ajouter des effets. Une silhouette reconnaissable peut quand même avoir une contreforme remplie ou un coin à l’envers.

Ce guide utilise un badge original écrit à la main, avec une ouverture carrée et un coin supérieur droit coupé. L’asymétrie rend visible une erreur d’orientation. C’est un exemple de géométrie dans le navigateur, pas un résultat de conversion PerfectVector ni un test de fabrication.

Commencer par les formes auxquelles tu veux donner de la profondeur

Pour le premier essai, utilise un petit SVG avec des contours fermés et remplis. Enregistre ceci sous badge.svg :

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 180">
  <path fill="#e64b35" fill-rule="evenodd"
    d="M20 20H160L220 80V160H20Z M65 60H115V110H65Z"/>
</svg>

Deux sous-tracés fermés se trouvent dans un seul élément path : une limite extérieure et un carré intérieur. La règle evenodd fait de la région intérieure une ouverture. Un rectangle blanc distinct couvrirait seulement la face dans une image plate ; il ne décrirait pas la même zone vide.

Le dessin occupe 200 sur 140 unités de coordonnées dans un viewBox de 240 sur 180. Garde cette différence à l’esprit pour dimensionner le maillage. Les marges vides appartiennent à la zone d’affichage SVG, pas à la silhouette extrudée.

Si tu as déjà un original vectoriel éditable, utilise-le. Si un PNG ou JPG est ta seule source, la procédure image vers vecteur de PerfectVector peut t’aider à préparer un dessin en tracés SVG. Examine l’aperçu et les contours téléchargés, particulièrement les espaces négatifs, avant de charger le fichier dans Three.js. La vectorisation fournit le dessin 2D ; le code ci-dessous fournit profondeur, matériaux, éclairage et placement.

Charger le SVG et afficher le maillage

L’exemple a été testé avec Three.js 0.186.0. Garde la bibliothèque principale et le module complémentaire à la même version. Dans un projet navigateur avec imports de paquets, installe three@0.186.0, sers les fichiers en HTTP et crée un conteneur :

<div id="viewer"></div>
<script type="module" src="./main.js"></script>

Ton outil de compilation doit résoudre les imports three. Pour une page navigateur simple sans outil de compilation, place cette carte d’import avant le script module, avec les fichiers du même paquet installé :

<script type="importmap">
{
  "imports": {
    "three": "./node_modules/three/build/three.module.js",
    "three/addons/": "./node_modules/three/examples/jsm/"
  }
}
</script>

Place badge.svg à côté de la page HTML. L’URL relative de chargement ci-dessous est résolue par rapport à l’URL de cette page. Enregistre ensuite ceci sous main.js :

import * as THREE from 'three';
import { SVGLoader } from 'three/addons/loaders/SVGLoader.js';
 
const data = await new SVGLoader().loadAsync('./badge.svg');
const artwork = new THREE.Group();
for (const path of data.paths) {
  if (path.userData.style.fill === 'none') continue;
  for (const shape of path.toShapes()) {
    const geometry = new THREE.ExtrudeGeometry(shape, {
      depth: 20, bevelEnabled: false, steps: 1
    });
    const material = new THREE.MeshStandardMaterial({
      color: path.color, roughness: 0.65, metalness: 0
    });
    artwork.add(new THREE.Mesh(geometry, material));
  }
}
if (!artwork.children.length) throw new Error('No filled shapes found');
 
// SVG y grows down; this scene uses y up.
artwork.scale.y = -1;
const bounds = new THREE.Box3().setFromObject(artwork);
const size = bounds.getSize(new THREE.Vector3());
const center = bounds.getCenter(new THREE.Vector3());
const scale = 4 / size.x;
artwork.scale.multiplyScalar(scale);
artwork.position.copy(center).multiplyScalar(-scale);
 
const scene = new THREE.Scene();
scene.background = new THREE.Color('#f1f3f5');
scene.add(artwork);
scene.add(new THREE.HemisphereLight(0xffffff, 0x596477, 2));
const light = new THREE.DirectionalLight(0xffffff, 3);
light.position.set(-3, 5, 7);
scene.add(light);
const camera = new THREE.PerspectiveCamera(35, 800 / 600, 0.1, 100);
camera.position.set(4, 3, 9);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(800, 600);
document.querySelector('#viewer').append(renderer.domElement);
renderer.render(scene, camera);

SVGLoader est un module complémentaire importé séparément. loadAsync() lit le fichier ; parse(svgText) est l’autre solution lorsque tu possèdes déjà le balisage SVG sous forme de chaîne.

Dans r186, utilise path.toShapes(). Les anciens exemples appellent souvent SVGLoader.createShapes(path). Cet utilitaire a été déprécié dans r185 et délègue à toShapes() dans la version testée. Vérifie ta version installée avant de mélanger des extraits de tutoriels différents.

La boucle ignore volontairement fill="none". Elle gère les remplissages unis de cet exemple ; ce n’est pas un moteur SVG complet. Dégradés, masques, images intégrées, contours, opacité et couches de couleurs superposées demandent leurs propres décisions, plutôt que de supposer que l’apparence plate deviendra une géométrie 3D identique.

Capture réelle du navigateur comparant un badge SVG original avec ouverture carrée et coin supérieur droit coupé à son maillage extrudé Three.js
Rendu WebGL réel de l’exemple écrit à la main dans Three.js r186. L’ouverture reste vide, le coin coupé reste en haut à droite et l’échelle uniforme produit un maillage de 4 sur 2.8 sur 0.4.

Régler l’orientation avant de mesurer et centrer

Les coordonnées verticales du SVG augmentent vers le bas. Cette scène regarde le dessin avec y positif vers le haut ; artwork.scale.y = -1 restaure donc l’orientation attendue. Le coin coupé sert de vérification : il doit être en haut à droite.

Ce changement de signe appartient à cette configuration de coordonnées. N’ajoute pas une deuxième inversion parce que le maillage semble encore incorrect après la rotation d’une caméra ou d’un objet parent. Compare d’abord une caractéristique asymétrique connue de la source à la scène rendue.

Les lignes suivantes mesurent le groupe inversé, calculent une échelle uniforme et déplacent son centre mis à l’échelle à l’origine. Box3.setFromObject() mesure les limites en incluant les objets enfants et leurs transformations. Ici, le groupe n’a pas de parent transformé et le dessin n’est pas tourné au moment de la mesure.

L’extrusion originale mesure 200 sur 140 sur 20. Fixer la largeur à 4 donne une échelle de 4 / 200, soit 0.02. Comme cette échelle s’applique aux trois axes, les limites finales sont de 4 sur 2.8 sur 0.4. Une profondeur de 20 dans le constructeur ne reste pas à 20 après la mise à l’échelle du groupe.

Ce sont des unités de scène. L’exemple n’affirme pas qu’une unité est un millimètre. Si ton application nécessite une interprétation physique précise, définis-la explicitement et valide-la dans la procédure de destination.

Confirmer le trou avant de décorer la surface

Le test a produit un tracé chargé, une forme et un trou. Nous avons aussi lancé un rayon à travers l’ouverture carrée et un autre à travers la partie pleine : l’ouverture n’a renvoyé aucun impact sur le maillage, tandis que la partie pleine en a renvoyé un. Des rayons à travers le coin supérieur droit coupé et le coin inférieur droit plein ont confirmé l’orientation verticale indépendamment de la vue inclinée.

Tu peux commencer par une vérification visuelle plus simple dans ta scène : regarde la face de front, puis en biais sur un fond contrasté. L’ouverture doit laisser voir le fond et ses parois doivent apparaître lorsque la caméra bouge. Une face blanche couvrant la zone est un autre résultat.

Si une contreforme se remplit, isole cette forme. Examine si la source utilise des sous-tracés, des objets remplis séparés, un tracé de rognage ou un masque. N’essaie pas de masquer le problème avec une couleur de matériau. Le guide des trous SVG remplis explique les distinctions dans le fichier source ; le diagnostic d’extrusion traite de la réparation des contours lorsque le dessin sous-jacent est défectueux.

Ajouter les effets de profondeur après une extrusion simple réussie

L’exemple désactive les biseaux pour faciliter l’inspection des dimensions initiales. Les options d’ExtrudeGeometry contrôlent séparément profondeur, taille et épaisseur du biseau et échantillonnage des courbes. Revérifie les petites ouvertures et les limites lorsque tu actives le biseautage. Un bord décoratif change la géométrie que tu viens de mesurer.

Pour un dessin courbe, examine la silhouette du maillage à la taille et à la distance de caméra prévues dans ton application. Augmente l’échantillonnage des courbes seulement si les facettes le nécessitent ; réduire les nœuds inutiles de l’entrée est une tâche d’édition distincte. Aucun réglage ne restaure des détails absents de la source.

Un dessin uniquement en contours nécessite aussi une autre décision. Le chargeur expose pointsToStroke() pour la géométrie des contours, mais la boucle de formes remplies ci-dessus omet volontairement ces tracés. Si la ligne visible doit devenir un ruban extrudé, décide d’abord du contour fermé qui le définit. Si elle doit rester une ligne dans la scène, crée plutôt une représentation de ligne ou de contour.

Pour une application React, exécute côté client le chargement et le rendu réservés au navigateur et libère la géométrie, les matériaux et le moteur de rendu dont tu es propriétaire lorsque la vue est supprimée. L’exemple compact effectue un seul rendu à taille fixe ; une visionneuse de production nécessite aussi la gestion du redimensionnement et son propre cycle de vie des ressources.

Distinguer vérifications de source et de destination

Un maillage navigateur est utile pour un badge interactif, un aperçu de logo ou une décoration de scène. Il n’établit pas que le résultat est une pièce au maillage fermé et aux dimensions adaptées. Si la destination est la fabrication, utilise la procédure distincte image vers SVG pour impression 3D et examine le modèle importé à cet endroit.

Pour une utilisation à l’écran, garde trois fichiers ou étapes distincts : le SVG source éditable, le maillage dérivé et la présentation de scène. Tu identifieras plus facilement si un mauvais résultat vient de la géométrie des tracés, de la construction du maillage ou de la caméra et de l’éclairage. D’autres guides de procédures SVG traitent de la source lorsqu’elle doit être réparée avant chargement.

FAQ

Pourquoi mon SVG est-il à l’envers dans Three.js ? Les coordonnées verticales SVG augmentent vers le bas. Dans une scène utilisant y positif vers le haut et regardant l’avant du dessin, inverser l’échelle y du groupe peut restaurer l’orientation source. Vérifie une caractéristique asymétrique avant d’ajouter une autre inversion ou rotation.

Dois-je utiliser createShapes ou toShapes ? Cet exemple utilise path.toShapes() avec Three.js 0.186.0. SVGLoader.createShapes() a été déprécié dans r185. Utilise l’API documentée pour la version installée dans ton projet, avec le paquet principal et le module complémentaire à la même version.

SVGLoader transforme-t-il un PNG dans un SVG en maillage ? Une image matricielle intégrée ne fournit pas les contours remplis utilisés par cet exemple. Obtiens d’abord un dessin en tracés adapté, ou utilise l’image comme texture si préserver son apparence est le vrai objectif.

L’extrusion préserve-t-elle la largeur des contours SVG ? Cet exemple extrude des formes remplies et ignore les tracés dont fill vaut none. La géométrie de contour nécessite une procédure distincte ; une ligne peinte épaisse n’est pas automatiquement le contour fermé d’un ruban extrudé.

Sources

  1. Three.js — SVGLoader — Décrit l’import du module complémentaire, les méthodes d’analyse et de chargement, l’utilitaire de contour et la dépréciation de createShapes.
  2. Three.js — ShapePath — Décrit la conversion de collections de tracés en formes avec toShapes.
  3. Three.js — ExtrudeGeometry — Définit l’extrusion de formes et les options de profondeur, biseau et échantillonnage des courbes.
  4. Three.js — Box3 — Décrit la mesure des limites d’objets transformés et l’obtention de leur taille et centre.

Tu pars d’un emblème uniquement matriciel ? Prépare un SVG candidat, examine ses contours remplis et ses ouvertures, puis teste ce fichier dans cette petite scène avant de construire la visionneuse complète.

Plus depuis le blog

Repartez d’un SVG plus net
et plus facile à modifier