// Contexte
Sur rayroud.com, la rubrique Impression 3D disposait déjà d’une sous-catégorie Modèles. L’idée : permettre de visualiser des fichiers 3D (.stl et .obj) directement depuis le navigateur, sans installer de logiciel. Mais afficher un modèle 3D, c’est une chose. Le gérer, l’uploader, et surtout en faire une vignette lisible, en est une autre.
Voici comment j’ai construit ce module, et les décisions techniques prises en route.
// 1. Stockage sur le VPS
Les fichiers sont déposés dans wp-content/uploads/models/ sur le serveur ( stack Docker webstack ). Rien ne part sur un CDN externe : tout reste sur le VPS, sauvegardé chaque nuit vers le NAS.
wp-content/uploads/models/ ├── modele1.stl ├── modele1.png <-- vignette générée automatiquement ├── modele2.obj └── modele2.png
// 2. Upload réservé aux administrateurs
Un formulaire d’upload est affiché uniquement si l’utilisateur est connecté avec le rôle admin (capacité upload_files). Les visiteurs voient la grille et peuvent ouvrir les modèles, mais ne peuvent rien déposer.
Côté sécurité : vérification du login WordPress, d’un nonce, et restriction stricte aux extensions .stl / .obj. Aucun fichier exécutable ne peut être déposé.
// 3. Le piège de three.js (r160)
Pour le visualiseur 3D, j’ai d’abord chargé three.js r160 via CDN. Problème : à partir de la r151, les versions « globales » (examples/js/) ont été supprimées du package. Résultat : OrbitControls, STLLoader et OBJLoader renvoyaient 404 → le JavaScript plantait → la grille restait vide.
Solution : revenir à la r140, dernière version disposant encore des loaders en mode global. Les scripts se chargent alors correctement.
// 4. Vignettes : le vrai défi
Première approche : afficher chaque modèle dans une mini-canvas three.js live (rotation automatique). Problème : 4 contextes WebGL simultanés sur mobile = fragile, et les vignettes restaient vides.
J’ai alors opté pour une vignette image : au moment de l’upload, le serveur rend le modèle 3D et enregistre une miniature PNG. Comme ça, la vignette est une simple image (<img>), fiable partout.
/// Rendu côté serveur, sans GPU
Le serveur web (conteneur PHP) n’a ni carte graphique ni Python installé. J’ai donc écrit un renderer maison en PHP + GD :
- Parse du STL (ASCII et binaire) et de l’OBJ
- Calcul du centre et de l’échelle du modèle
- Projection orthographique avec une rotation fixe (angle « sympa »)
- Tri des faces par profondeur (painter’s algorithm)
- Ombrage simple selon la normale de chaque face (effet volume)
- Sortie PNG sur fond sombre, dans le style « terminal néon » du site
Un détail technique : unpack('12f') plante en PHP moderne, il faut utiliser unpack('f*') puis ré-indexer. Corrigé.
// 5. Gestion des fichiers (menu contextuel)
Au lieu de boutons sempre visibles, la gestion admin se fait via un menu contextuel :
- Desktop : clic droit sur une vignette
- Mobile : appui long (~0,7 s) sur une vignette
Le menu propose : Ouvrir (le visualiseur 3D), Dupliquer, Renommer, Supprimer. Le menu se ferme au clic ailleurs.
// 6. Le visualiseur 3D (popup)
Un clic simple sur une vignette ouvre une popup (lightbox) avec le modèle 3D complet : rotation à la souris / doigt, zoom. Un seul contexte WebGL à la fois → fiable.
// Bilan technique
| Élément | Solution |
|---|---|
| Visualiseur 3D | three.js r140 (CDN) + OrbitControls/STLLoader/OBJLoader |
| Vignette | Renderer PHP+GD généré à l’upload (PNG) |
| Stockage | /wp-content/uploads/models/ sur le VPS |
| Upload | Réservé admin (login WP + nonce + extriction .stl/.obj) |
| Gestion | Menu contextuel (clic droit / appui long) |
| API | Endpoint autonome models-api.php (wp-load.php) |
Module opérationnel et testé sur le site. Les fichiers sont sauvegardés quotidiennement vers le NAS.

