Orienter les particules sur la normale d'un mesh ou d'une surface: closestPointOnMesh
Par Narann le lundi, 13 septembre 2010, 22:20 - Infographie 3D - Boulot - Lien permanent
Lors de mes recherches sur les particules, j'étais face à un problème qu'on rencontre assez fréquemment:
Orienter des instancers en fonction de la normale du mesh sur lequel elles se trouvent... :casseTeteMur:
Ça semble être un bête problème mais dans Maya, ce n'est pas si évident et il faut un peut bidouiller pour pouvoir le faire.
Je vous propose à travers ce tuto une petite solution qui, vous allez voir, n'est pas de moi mais que je ne pouvais m'empêcher de vous faire partager.
Une des méthodes rapides pour faire ça est de mettre une vitesse très très faible (0.001) aux particules et d'orienter la particule en fonction de sa vitesse. Franchement, ça dépanne mais ça peut poser quelques soucis plus tard....
Contexte
Je suis tombé sur un thread CGTalk d'une personne demandant justement, comment procéder.
La meilleur réponse fut sans conteste celle de YouDaftPunk qui parle d'un node qui permet de faire ça: "closestPointOnMesh" :sourit:
Il donne également une scène assez complète pour expliquer comment procéder: particle_normal_alignment.mb.zip
Un bon conseil: Mon tuto n'étant qu'une introduction, je vous invite, à garder le billet de YouDaftPunk de coté pour y revenir plus tard, télécharger sa scène et la décortiquer. :redface:
closestPointOnMesh
Le fonctionnement du node closestPointOnMesh est en fait assez simple:
En entrée:
- La position d'un point (x,y,z)
- Une surface mesh
En sortie:
- La position d'un autre point (x,y,z), celui qui est sur la surface
- Une orientation qui est en fait la normale de la face sur laquelle se trouve le point calculé
- Pleins d'autres choses que je n'utiliserai pas
Résultat:
Je vous donne ->la scène Maya<- (bouton droit de souris, save as...).
Vous pouvez bouger le "locator1", vous verrez que l'autre suit en restant sur la surface! :hehe:
Avec des particules
Maintenant me direz vous, comment l'utiliser avec des particules? Et bien si vous avez les bases, vous allez voir que la manœuvre est un peu hasardeuse (et "perf-killer" :baffed: ) mais qu'elle a le mérite d'exister et peut rendre de fiers services!
Créez un mesh ayant une forme un minimum intéressante (mais pas non plus tarabiscotée, closestPointOnMesh n'est en aucun cas le messie qui vous sortira de votre modé dégueulasse :siffle: )
Puis créez un node closestPointOnMesh auquel vous connectez le mesh:
Créez votre "Emitter from object":
Passez votre "Emitter Type" en "Surface":
Augmentez le "Rate":
Et enlevez la vitesse de vos particules:
Lancez votre dynamique, vous devriez obtenir quelque chose comme ça:
Créez un objet qui sera votre instancer:
Sélectionnez-le puis transformez-le en instancer:
Nous allons maintenant jouer avec les expressions pour orienter nos particules à la création.
Dans votre système de particule, créez deux attributs de type "vecteur par particule": aimUp, aimDir.
Dans l'onglet "Instancer" de votre "particle system", settez Aim Direction sur la variable aimUp puis Aim Axis sur la variable aimDir:
Créez une expression à la création:
Voici l'expression:
// on "regarde vers le haut" particleShape1.aimDir = <<0,1,0>>; // on donne les infos de position de la particule au node vector $p = particleShape1.position; float $x = $p.x; float $y = $p.y; float $z = $p.z; setAttr closestPointOnMesh1.inPosition $x $y $z; // on récupère la normal qu'on donne comme information a la particule vector $normal = `getAttr closestPointOnMesh1.normal`; // et on oriente la particule particleShape1.aimUp = $normal;
Note: Certains tiqueront et diront que l'utilisation des "setAttr" et "getAttr" est à proscrire lors de l'évaluation d'une expression car elles détruisent les perfs. Ils auront raison :hehe: . Mais le soucis vient de "l'évaluation des nodes Maya" (la "computation"). Celle ci ne se fait qu'une fois l'évaluation des particules terminé. Donc si on n'utilise pas de setAttr/getAttr, on ne force pas le node à recalculer ses valeurs, résultat, c'est comme si vous aviez évalué une particule et que toute les autres se récupères les même valeurs que la première, ça donne des choses assez drôle (qui peuvent être intéressantes dans certains cas).
Remettez-vous à la frame 1 pour virer vos particules puis calculez quelques images de dynamique:
Et voila le travail! :banaeyouhou:
Voici ->la scène Maya<- (bouton droit de souris, save as...).
A partir de là vous pouvez faire pas mal de choses.
Ici nous orientons les particules à la création, ce qui suppose qu'elles ne bougent pas.
Si c'est le cas, il faudra recréer une expression "Runtime before dynamics" qui réoriente les particules.
Je vous invite à regarder la scène de YouDaftPunk qui va encore plus loin que moi (pas difficile cela dis) en animant des particules le long de la surface, de manière aléatoire.
Si vous vous en êtes sortis avec ce tuto, vous devriez pouvoir vous débrouiller avec sa scène. :sourit:
Conclusion
J'espère que ce petit tuto vous aura appris quelque chose et/ou dépanné. Personnellement, c'est vraiment le genre de trucs qui se fait en trois cliques dans les autres softs 3D mais qui demande pas mal de technique dans Maya (comme d'hab, il faut bien justifier son salaire! :aupoil: ).
Si vous avez des questions, que je n'ai pas été assez clair ou qu'il manque une information, n'hésitez pas à laisser un commentaire.
A bientôt!
Dorian
Méthode alternative: Le Goal World Normal
EDIT: Suite au commentaire de Joss, je vous propose une méthode alternative qui est beaucoup plus rapide. :siffle:
Dans un premier temps, sélectionner votre géométrie:
Faite un "Emit from Object" mais en sélectionnez les options:
Passer "l'Emitter type" en Surface:
Et surtout cochez "Need parent UV (NURBS)":
Maintenant nous allons convertir la surface émettrice de particule en "Goal".
Sélectionnez le système de particule:
Puis votre surface:
Et passer tout ça en "Goal":
Maintenant allez dans votre particleShape:
Et créez deux attributs (goalU et goalV) de type Flaot Per Particule:
Une fois cela fait, nous allons créer une expression de création de particule:
Et copiez juste ça:
goalU = parentU; goalV = parentV;
Puis cliquez sur création:
Maintenant allez dans l'onglet "Goal Weights and Objects":
Et cliquez sur "Create Goal World Normal 0 PP"
Les particules ont donc maintenant leurs valeurs de Goal, qui sont en fait les valeurs d'UV de la surface. :sourit:
Pour rendre le tout plus visible nous allons créer notre instancer. :joue:
Sélectionnez la géométrie à instancier:
Puis sélectionnez votre "particle system":
Créez l'instancer:
Et pour finir, dans l'onglet "Instancer (Geometry Replacement)", mettez la "Aim Direction" sur "goalWorldNormal0PP":
Bougez votre timeline pour générer des particules:
Comme vous pouvez le constater, vous voyez que les instancers ne sont pas bien alignés. :mechantCrash:
C'est dû au fait que goalWorldMesh utilise l'axe X comme axe de référence. Mais il suffit de rajouter attribut (aimUp) et de l'orienter sur l'axe Y (qui est l'axe de ma flèche):
Entrez dans l'expression de création de la particule:
Ajoutez:
particleShape1.aimUp = <<0,1,0>>;
Validez puis mettez "Aim Axis" sur votre nouvel attribut: aimUp
Et voila le travail:
Vous remarquerez aussi que ça va beaucoup plus vite! :aupoil:
Voici ->la scène Maya<- (bouton droit de souris, save as...).
Un grand merci à Joss pour cette méthode!
A bientôt!
Dorian
Commentaires
encore plus Simple, vue que tu veux orienter des instances en fonction de la normale du mesh sur lequel elles se trouvent.
Cela supposes que tu utilise un goal.
En deux lignes d'expressions et qutres clics tu obtiens le meme resultat et sans avoir a calculer le point le plus proche de la surface (vue qu'avec un goal tu es deja sur la surface)
Bref vla le setup:
-emit from surface (avec need parent UV actif)
-metre la surface en goal
-ajouter aux partoches les attributs "goalU" et" goalV"
-metre en expression de creation
goalU = parentU;
goalV = parentV;
-dans l;oblet goalWeight tu clics "create goal world normal"
-dans l'instancer tu met le " aimDirection" en "goalWorldNormal"
and voila.
c'est simple et rapide a calculer ;)
cheers
Joss
Salut Joss et merci pour ton intervention.
En effet, ton approche est vraiment efficace! Je vais l'ajouter à l'article! :)
En fait, le node closestPointOnMesh permet de faire d'autres choses que je vais préciser dans un prochain billet.
A bientôt!
Dorian
Hi man,
Thanks a lot for the article! It helped me a lot!
But I had one problem with it: I use to put in "Aim Direction" the velocity code, for the particles alwars "look" forward. With your script I can't do this :(
You have any ideia of how I can do that?