[Three.js] Normalisation de vecteur : Pourquoi forcer la longueur à 1 ? | chaen
[Three.js] Normalisation de vecteur : Pourquoi forcer la longueur à 1 ?
Une analyse de l'essence de la normalisation à travers la logique de mouvement dans les jeux et l'application de l'échelle dans Blender. Découvrez pourquoi séparer la direction de la magnitude est vital pour la physique et le rendu.
#Three.js
등록일 2026-01-032026-01-037
Commentaires
Le mot de passe saisi sert à ouvrir, modifier et supprimer les commentaires secrets.
En étudiant Three.js, on voit souvent .normalize() attaché aux vecteurs comme une sorte de rituel. Les tutoriels disent souvent que "c'est utile" sans plus d'explication, ce qui m'a rendu encore plus curieux.
Pourquoi transformer un vecteur parfaitement fonctionnel en une longueur de 1 ? Quand est-ce indispensable, et quand peut-on s'en passer ?
En y réfléchissant, ce n'était pas un concept totalement nouveau. J'utilise souvent Blender, et on m'a toujours dit d'appliquer l'échelle (Apply Scale) après avoir redimensionné un objet. La raison était "parce que ça risque de casser plus tard", mais je n'avais jamais vraiment compris pourquoi.
En creusant la normalisation dans Three.js, j'ai réalisé que cette habitude sur Blender résolvait le même problème d'une manière différente.
Ma compréhension de la normalisation
La normalisation est l'action de conserver la direction tout en fixant la longueur à exactement 1.
Ignorer "la distance parcourue"
Garder "la direction pointée"
C'est pourquoi un vecteur normalisé est utilisé pour :
La direction
La vue (ligne de mire)
La normale (orientation d'une surface)
Les vecteurs d'entrée de mouvement
Le point commun ? 👉 L'orientation est une information plus cruciale que la magnitude.
Pourquoi n'est-ce pas un problème dans les jeux sur grille ?
Dans un jeu comme les échecs ou les anciens Pokémon, le monde n'est pas un espace continu.
Une case à gauche
Une case à droite
Une case en diagonale
Mathématiquement, une diagonale vaut $√2 ≈ 1,41$, mais selon les règles du jeu, c'est juste "un déplacement".
📌 Ce qui compte, c'est la règle, pas la valeur exacte de la distance. Le problème du "déplacement diagonal plus rapide" n'existe donc pas.
Pourquoi cela pose problème dans Three.js / WebGL ?
L'espace dans Three.js est totalement différent :
Les coordonnées sont en $(x, y, z)$
Les valeurs sont des nombres flottants (décimales)
Le mouvement est un calcul de distance, pas de "cases".
Sans normalisation, les problèmes surgissent immédiatement.
⚠️ Déplacement diagonal sans normalisation
Entrée W + D → $(1, 1)$. La longueur est $√2 ≈ 1,41$.
Cela signifie que dans la même frame :
Déplacement droit → $1$
Déplacement diagonal → 1,41
Ce n'est pas qu'une impression de vitesse : la valeur réelle de la position se déplace plus loin.
Problèmes engendrés :
🧱 Bugs de collision : Traverser des murs fins ou des coins parce qu'on a parcouru trop de distance en une seule frame.
⏱ Déséquilibre d'arrivée : Un personnage en diagonale arrive toujours plus vite à destination (avantage de distance).
C'est pourquoi on utilise la normalisation
Dans les systèmes de mouvement libre, on suit ce flux :
Interpréter l'entrée comme une Intention de Direction (ex: $(1, 1)$ = "je veux aller en diagonale").
.normalize() → $(0,7, 0,7)$.
Multiplier par la Vitesse (speed).
Mouvement
Vecteur d'entrée
Longueur réelle
Après normalisation
Droite
(1, 0)
1,0
1,0
Haut
(0, 1)
1,0
1,0
Diagonale
(1, 1)
1,41
1,0
👀 Visuellement, on va en diagonale. 📐 Mathématiquement, on parcourt la même distance.
La vraie raison d'appliquer l'échelle dans Blender
C'est là que Blender intervient. Les Vecteurs Normaux servent au calcul de la lumière. Ces normales sont toujours supposées avoir une longueur de 1.
Si vous changez l'échelle sans faire Apply Scale :
Les vecteurs internes s'allongent aussi.
La normale n'est plus une simple "valeur de direction".
Pourquoi la lumière casse-t-elle ? (Produit scalaire)
Le calcul de l'éclairage utilise souvent le Produit Scalaire (Dot Product).
Cas normal :
Longueur normale = $1$
Longueur direction lumière = $1$
→ Résultat entre $0$ et $1$ (Luminosité attendue).
Cas corrompu :
Longueur normale = $100$
Longueur direction lumière = $50$
→ Résultat = 5000
Ce résultat provoque :
Des zones totalement blanches (brûlées).
Des artefacts de couleur bizarres.
Un ombrage qui semble cassé.
👉 Apply Scale, c'est dire : "Remets ces vecteurs à la norme de longueur 1."
Attention dans Three.js
.normalize()modifie le vecteur d'origine.
js
Si vous devez garder la position ou la force d'origine, clonez-le d'abord.
js
const direction =
Résumé
La normalisation n'est pas qu'une astuce mathématique. C'est :
Un standard de distance équitable pour le mouvement.
Un standard de luminosité pour l'éclairage.
Une séparation intentionnelle entre direction et magnitude.
Désormais, la raison d'utiliser .normalize() est limpide.
const v = new THREE.Vector3(3, 4, 0);v.normalize(); // v devient (0.6, 0.8, 0)