Dorian Fevrier's blog - Mot-clé - remplirJe m’appelle FEVRIER Dorian, je suis infographiste 3D passionné par mon métier, l’informatique en général, l’internet, la programmation et l’évolution de tout ce petit monde. Vous trouverez sur ce blog des tutoriaux, mes coups de cœurs, avis, etc.2024-01-02T23:48:05+01:00FEVRIER Dorianurn:md5:695d9c73474c33ce3dab043823509c4bDotclearRemplir un mesh de spheres dans Maya: La méthode d'un sénior!urn:md5:7e1c6717a192c8539f600af3b710ed132011-03-14T22:24:00+01:002023-03-13T22:24:09+01:00NarannScript et code3dastuceautodeskclosestPointOnMeshcodecollisionexplicationsfrparticulepythonremplirscriptsphere<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres_tn2.png" alt="remplir_un_mesh_de_spheres_tn2.png" style="float:left; margin: 0 1em 1em 0;" title="remplir_un_mesh_de_spheres_tn2.png, mar. 2011" />Aujourd'hui, je ne suis pas peu fier de vous présenter la méthode d'un gros sénior dans le domaine du FX: <a href="http://www.djelloul-bekri.fr/">Djelloul Bekri</a>, qui, en plus d'être un mec adorable m'a donné et autorisé à diffuser son "trick" pour remplir le volume d'un mesh de spheres. :laClasse:</p>
<p>Un grand merci à lui donc car je pense que beaucoup de FX guys vont apprendre un truc aujourd'hui. Voir plusieurs tant cette méthode peut s'adapter à beaucoup de choses. :sauteJoie:</p> <h3>Sommaire</h3>
<ul>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#ce_quon_cherche_a_faire">Ce qu'on cherche à faire</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#le_principe">Le principe</a>
<ul>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#remplir_un_mesh_de_particule">Remplir un mesh de particule</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#recuperer_les_positions_des_particules">Récupérer les positions des particules</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#calcul_du_rayon_maximal_de_chaque_particule">Calcul du rayon maximal de chaque particule</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#determiner_la_plus_grosse_sphere">Déterminer la plus grosse sphère</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#suppression_des_particules_inutiles">Suppression des particules "inutiles"</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#et">Et...</a></li>
</ul></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#das_code">Das Code!</a>
<ul>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#en_brut">En brut</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#les_details">Les détails</a></li>
</ul></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#bekri_djelloul">BEKRI Djelloul</a></li>
</ul>
<center>:longBar:</center>
<h3>Ce qu'on cherche à faire <a id="ce_quon_cherche_a_faire"></a></h3>
<p>Et bien... Ça:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres001.png" alt="remplir_un_mesh_de_spheres001.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres001.png, mar. 2011" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres007.png" alt="remplir_un_mesh_de_spheres007.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres007.png, mar. 2011" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres005.png" alt="remplir_un_mesh_de_spheres005.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres005.png, mar. 2011" /></p>
<p>Avant de commencer, il faut savoir que les algorithmes permettant de mettre des sphères dans de la géométrie (sphere packing algorythms) sont des sujets de recherche fréquents:</p>
<ul>
<li><a href="http://cg.in.tu-clausthal.de/research/ist/index.shtml" hreflang="en">Inner Sphere Trees for 6-DOF Haptic Rendering</a></li>
<li><a href="http://cg.in.tu-clausthal.de/research/protosphere/index.shtml" hreflang="en">A GPU-Assisted Prototype Guided Sphere Packing Algorithm for Arbitrary Objects</a></li>
<li><a href="http://www.google.com/search?q=Sphere+Packing+Algorithm">Et Google...</a></li>
</ul>
<p>Et hop! Une petite vidéo du principe:</p>
<center><iframe width="560" height="315" src="https://www.youtube.com/embed/GIoB7Pa0SjE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe></center>
<blockquote><p>Merci à Adrien Herubel pour ces quelques liens. :)</p></blockquote>
<p>Ces algorithmes peuvent servir à pleins de chose. Un exemple assez précis est de "sortir" les lignes de force/d’énergie d'un mesh pour lui appliquer un rigging automatique:</p>
<ul>
<li><a href="http://www.tonychai.com/ART.html" hreflang="en">ART - Auto-Rigging Tool</a></li>
</ul>
<center><iframe src="https://player.vimeo.com/video/4390629?h=6a1760b2d8" width="640" height="356" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></center>
<p>A vous de voir quoi en tirer. :sourit:</p>
<p>Je vais d'abords expliquer le principe. Ensuite je vous donnerai, en brut, le script de Djelloul que je commenterai, ligne à ligne. Si vous scritpez un peu, vous verrez qu'il y a énormément d'optimisations possibles mais ce n'était pas sa priorité lorsqu'il m'a montré ce script.</p>
<p>Cette méthode est donc un peu longue en temps machine. :seSentCon:</p>
<p>Mais si il vous en prend l'envie de vouloir optimiser ce code, n'hésitez pas à me l'envoyer. Je me ferai un plaisir de faire un lien et un commentaire ici même. :bravo:</p>
<center>:longBar:</center>
<h3>Le principe <a id="le_principe"></a></h3>
<p>Et bien oui, comme toute technique un chouilla compliqué, il y a de la théorie! :jdicajdirien:</p>
<p>Vous allez voir que le principe est assez simple et si vous pigez le truc, vous pourrez l'adapter à vos besoins.</p>
<h4>Remplir un mesh de particule <a id="remplir_un_mesh_de_particule"></a></h4>
<p>La première chose à faire est de remplir un mesh de particule.</p>
<p>Si vous suivez régulièrement mon blog, j'ai proposé <a href="https://www.fevrierdorian.com/blog/post/2010/09/22/Remplir-un-mesh-de-particule-dans-Maya-closestPointOnMesh-again">une solution</a> mais Djelloul, dans sa version (et surtout pour gagner du temps :laClasse: ) utilise <a href="http://download.autodesk.com/us/maya/2011help/CommandsPython/particleFill.html" hreflang="en">particleFill</a> qui remplit le mesh sélectionné de nParticle.</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres004.png" alt="remplir_un_mesh_de_spheres004.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres004.png, mar. 2011" /></p>
<h4>Récupérer les positions des particules <a id="recuperer_les_positions_des_particules"></a></h4>
<p>On récupère la position dans l'espace de chacune des particules crées.</p>
<h4>Calcul du rayon maximal de chaque particule <a id="calcul_du_rayon_maximal_de_chaque_particule"></a></h4>
<p>Une fois qu'on a toutes les positions des particules, pour chacune d'elle, on va récupérer la taille maximale (le rayon) que pourrait atteindre une sphère placée sur cette particule, sans sortir de la géométrie.</p>
<p>Pour calculer cette taille, on va récupérer le point de la géométrie le plus proche de la particule courante. Et pour cela on va utiliser un node que vous connaissez peut être déjà. Je vous le donne en mille, il s'agit du <a href="http://download.autodesk.com/us/maya/2011help/Nodes/closestPointOnMesh.html">closestPointOnMesh</a>. Je ne vais pas réexpliquer le principe, je me suis déjà <a href="https://www.fevrierdorian.com/blog/post/2010/08/19/Orienter-les-particules-sur-la-normale-d-un-mesh-ou-d-une-surface-closestPointOnMesh">étalé</a> <a href="https://www.fevrierdorian.com/blog/post/2010/09/22/Remplir-un-mesh-de-particule-dans-Maya-closestPointOnMesh-again">dessus</a>.</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/Schema_001.png" alt="Schema_001.png" style="display:table; margin:0 auto;" title="Schema_001.png, mar. 2011" /></p>
<p>Arrivé ici, nous avons deux choses:</p>
<ul>
<li>Une liste de points dans l'espace (les particules).</li>
<li>Une liste de rayon.</li>
</ul>
<p>Et bien entendu, ces deux listes font la même taille (un rayon par particule). Si vous n'avez pas compris ça, il peut être intéressant de relire des quelques points plus haut. :siffle:</p>
<p>On peut donc maintenant considérer qu'un ensemble "point+rayon" est une sphère.</p>
<h4>Déterminer la plus grosse sphère <a id="determiner_la_plus_grosse_sphere"></a></h4>
<p>Il faut bien un point de départ et dans le cas de cette algorithme, tout commence par la sphère la plus grosse.</p>
<p>Pour savoir ça, on parcourt tous les points et on regarde leur rayon. On ne garde que le point ayant le rayon le plus gros.</p>
<p>Une fois tous les points parcourus, le point ayant le rayon le plus gros est considéré comme la sphère la plus grosse (si vous ne comprenez pas ça... :septic: ).</p>
<p>Notez aussi que c'est à cet endroit dans le mesh que (pardonnez moi l'expression) "l'espace est le plus grand".</p>
<h4>Suppression des particules "inutiles" <a id="suppression_des_particules_inutiles"></a></h4>
<p>Une fois qu'on sait quelle est la sphère (l'ensemble point-rayon) la plus grosse dans le mesh, on peut supprimer toute les autres sphères qui sont en collision avec elle.</p>
<p>L'avantage d'utiliser des sphères pour des tests de collision c'est qu'il suffit de deux points et de deux rayons (un par sphère) pour savoir si elles se touchent, c'est tout! <sup></sup></p>
<p>Ça tombe bien, c'est exactement ce que l'on a!</p>
<p>Vérifier ça est assez simple:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/Schema_002.png" alt="Schema_002.png" style="display:table; margin:0 auto;" title="Schema_002.png, mar. 2011" /></p>
<p>Dans un premier temps, on récupère la distance entre les deux points (en jaune). Une <a href="http://www.google.com/search?q=distance+deux+points+3d">petite recherche sur google</a> et on trouve <a href="http://forums.futura-sciences.com/mathematiques-superieur/159674-distance-entre-points-un-repere-3d.html#postcount1225138">facilement</a> <a href="http://en.wikipedia.org/wiki/Euclidean_distance#Three_dimensions">la formule</a>:</p>
<blockquote><p>distance = sqrt( (pt1.x-pt2.x)² + (pt1.z-pt2.z)² + (pt1.z-pt2.z)² )</p></blockquote>
<p>sqrt(x) étant la racine carré de x.</p>
<p>Une fois qu'on a la distance, on additionne la taille des deux rayons et on compare!</p>
<p>Si la distance entre les deux centres des sphères est plus petite que la somme de leurs rayons, les sphères se touchent.</p>
<h4>Et... <a id="et"></a></h4>
<p>...Caetera! On recommence! :sourit:</p>
<p>En effet, tant qu'on a supprimé au moins un point, on recommence la boucle avec tousles points restants, et ce, jusqu'à ce qu'il ne reste aucun point à supprimer:</p>
<ul>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#determiner_la_plus_grosse_sphere">Déterminer la plus grosse sphère</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#suppression_des_particules_inutiles">Suppression des particules "inutiles"</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#et">Etc...</a></li>
</ul>
<p>Arrivé ici vous devriez avoir une vision globale de "comment que ça fonctionne ce truc". :joue:</p>
<p>Mais sans plus tarder: Le code!</p>
<center>:longBar:</center>
<h3>Das Code! <a id="das_code"></a></h3>
<h4>En brut <a id="en_brut"></a></h4>
<p>Voici le code de Djelloul, brut de pomme! Fait avec ses petits doigts, sans modifs de ma part.</p>
<pre>[python]
from pymel.all import *
import maya.mel as mel
import maya.cmds as cmds
import time
step = 100
######################################
def mag(p1,p2):
return ((p1[0]-p2[0])**2+(p1[1]-p2[1])**2+(p1[2]-p2[2])**2)**.5
if(len(ls(sl=1))):
obj=ls(sl=1)[0]
try:
particleFill(rs=step,maxX=1,maxY=1,maxZ=1,minX=0,minY=0,minZ=0,pd=1,cp=0)
except:
pass
part = ls(sl=1)[0]
partShape = listRelatives(part,shapes=1)[0]
closest=createNode("closestPointOnMesh")
connectAttr(obj+".outMesh",closest+".inMesh")
points=getAttr(part+".position")
delete(part)
rayons=[]
for point in points:
setAttr(closest+".inPosition",point)
rayons.append(mag(point,getAttr(closest+".position")))
delete(closest)
newPoints,newRayons = [],[]
while len(points)>0:
print "%s points encore a traiter..." % len(points)
action,p,max,maxId = 0,[],-1,-1
for i in range(len(points)):
if rayons[i]>max:
max,p,maxId=rayons[i],points[i],i
del(points[maxId])
del(rayons[maxId])
newPoints.append(p)
newRayons.append(max*1.2)
i=0
while i<len(points):
if mag(p,points[i])<rayons[i]+max:
del(points[i])
del(rayons[i])
else:
i=i+1
#Attention ! Le mode de creation des nParticles par default doit etre "Points" !
part = nParticle(p=newPoints)[1]
setAttr(part+".particleRenderType",4)
setAttr(part+".ignoreSolverGravity",1)
addAttr(part,ln="radiusPP",dt="doubleArray")
setAttr(part+".radiusPP",newRayons,type="doubleArray")
print "Fini."
else:
print("Il faut selectionner un mesh !")
</pre>
<h4>Les détails <a id="les_details"></a></h4>
<p>Bon, le premier truc est de passer les nParticules par défaut sur "Points":</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres008.png" alt="remplir_un_mesh_de_spheres008.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres008.png, mar. 2011" /></p>
<p>Vous pouvez l'essayer! Sélectionnez votre mesh et lancez le! (Si vous avez mis 100 en step, il vaut mieux être patient. Mettez 30 pour vos tests).</p>
<p>Pour la suite, je partirai de cette forme:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres001.png" alt="remplir_un_mesh_de_spheres001.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres001.png, mar. 2011" /></p>
<p>On commence par une petite déclaration d'une fonction qui renvoie la distance entre deux points.</p>
<pre>[python]
def mag(p1,p2):
return ((p1[0]-p2[0])**2+(p1[1]-p2[1])**2+(p1[2]-p2[2])**2)**.5
</pre>
<p>Si vous regardez bien, c'est la version Python de la formule que j'ai donné <a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#suppression_des_particules_inutiles">plus haut</a>.</p>
<pre>[python]
x**2
</pre>
<p>En Python, ça veut dire x² (au carré).</p>
<p>Et:</p>
<pre>[python]
x**0.5
</pre>
<p>Ça veut dire "racine carré".</p>
<p>En gros, chaque point (p1 et p2) est une liste de trois valeurs (x, y, z) et on s'en sert pour calculer la distance qui les sépares.</p>
<pre>[python]
if(len(ls(sl=1))):
obj=ls(sl=1)[0]
try:
particleFill(rs=step,maxX=1,maxY=1,maxZ=1,minX=0,minY=0,minZ=0,pd=1,cp=0)
except:
pass
</pre>
<p>Ici on s'assure que l'objet que l'on souhaite remplir est sélectionné et on lui applique un <a href="http://download.autodesk.com/us/maya/2011help/CommandsPython/particleFill.html" hreflang="en">particleFill</a> qui le remplit de nParticle (notez que c'est ici qu'est utilisé la variable <em>step</em>):</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres004.png" alt="remplir_un_mesh_de_spheres004.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres004.png, mar. 2011" /></p>
<pre>[python]
part = ls(sl=1)[0]
partShape = listRelatives(part,shapes=1)[0]
</pre>
<p>Quand on créé un système de particule, Maya le sélectionne automatiquement. Ici, il récupère la sélection ("part"). La variable "partShape" ne sera pas utilisée dans la suite du script.</p>
<pre>[python]
closest=createNode("closestPointOnMesh")
connectAttr(obj+".outMesh",closest+".inMesh")
</pre>
<p>On créé le node de closestPointOnMesh et on lui connecte la géométrie qu'on souhaite remplir.</p>
<pre>[python]
points=getAttr(part+".position")
delete(part)
</pre>
<p>On récupère la position de toute les particules du système dans une variable ("points"), puis on supprime le système de particule.</p>
<p>Vous comprenez donc que l'intérêt d'utiliser le particleFill est uniquement de récupérer, sans trop se casser le c** une liste de positions (x, y, z) qui soit "dans le mesh".</p>
<pre>[python]
rayons=[]
for point in points:
setAttr(closest+".inPosition",point)
rayons.append(mag(point,getAttr(closest+".position")))
delete(closest)
</pre>
<p>Cette boucle parcourt tous les points récupérés plus haut et demande au node de closestPointOnMesh quelle est la position (sur la surface du mesh) la plus proche de ce point. La distance (entre le point d'origine et le point le plus proche sur la surface) est ensuite calculée (via la procédure "mag") et est stockée dans la liste des rayons. (Il fait ça en une ligne donc n'hésitez pas à relire le code! :dentcasse: )</p>
<pre>[python]
newPoints,newRayons = [],[]
</pre>
<p>Il initialise deux listes (points et rayons) qui seront les listes des points et rayons restants (ceux qui vont vraiment servir).</p>
<p>Et maintenant, accrochez vous car on rentre dans le gros de l'algo! :gniarkgniark:</p>
<pre>[python]
while len(points)>0:
print "%s points encore a traiter..." % len(points)
p,max,maxId = [],-1,-1
</pre>
<p>Début de la boucle. On initialise trois variables:</p>
<ul>
<li>"p" qui sera le point le plus "gros" (ayant le rayon le plus gros).</li>
<li>"max", idem que pour point mais pour le rayon.</li>
<li>"maxId", l'index de l'ensemble point-rayon qui est le plus gros (rappelez vous, les deux listes font la même taille).</li>
</ul>
<pre>[python]
for i in range(len(points)):
if rayons[i]>max:
max,p,maxId=rayons[i],points[i],i
</pre>
<p>Cette boucle ne fait que rechercher (parmis tout les points) le point le plus gros et le stocke dans les variables initialisées plus haut.</p>
<p>A la fin de la boucle, max, p, et maxId appartiennent à la sphère (l'ensemble point-rayon toujours) la plus grosse. Celle qu'on va garder!</p>
<pre>[python]
del(points[maxId])
del(rayons[maxId])
newPoints.append(p)
newRayons.append(max*1.2)
</pre>
<p>Ici on "déplace" en quelque sorte le point le plus gros vers la nouvelle liste ("newPoints" et "newRayons"):</p>
<ul>
<li>On le supprime de la liste principale.</li>
<li>On l'ajoute à la nouvelle liste.</li>
</ul>
<p>Djelloul choisit de multiplier la taille du rayon par 1.2 pour compenser le fait que les sphères semblent ne pas se toucher.</p>
<pre>[python]
i=0
while i<len(points):
if mag(p,points[i])<rayons[i]+max:
del(points[i])
del(rayons[i])
else:
i=i+1
</pre>
<p>Là, on arrive à la fin de l'algo: On parcourt tous les points restants, on fait, sur chacun d'eux, <a href="https://www.fevrierdorian.com/blog/post/2011/03/14/Remplir-un-mesh-de-spheres-dans-Maya-La-methode-d-un-senior#suppression_des_particules_inutiles">un test de collision</a> avec la sphère la plus grosse (qu'on a récupéré juste au dessus).</p>
<p>Si il y a collision, on supprime le point. :grenadelauncher: (Et on "valide" la variable "action" pour que la boucle continue).</p>
<blockquote><p>Notez qu'on n'incrémente pas "i" si on supprime les sphères des listes car tous les index se décalent de un à cet endroit. L'index actuel doit donc être revérifié.</p></blockquote>
<pre>[python]
#Attention ! Le mode de creation des nParticles par default doit etre "Points" !
part = nParticle(p=newPoints)[1]
setAttr(part+".particleRenderType",4)
setAttr(part+".ignoreSolverGravity",1)
addAttr(part,ln="radiusPP",dt="doubleArray")
setAttr(part+".radiusPP",newRayons,type="doubleArray")
print "Fini."
</pre>
<p>C'est la dernière partie du script:</p>
<ul>
<li>On recréé un système de particule en lui donnant les points qu'on a conservé de l'ancien système (les nouveaux points en quelque sorte).</li>
<li>On met le display de particule en sphère, désactive la gravité.</li>
<li>On ajoute un attribut de "rayon per particle".</li>
<li>On donne à ce nouvel attribut les valeurs des rayons conservé de l'ancien système.</li>
</ul>
<pre>[python]
else:
print("Il faut selectionner un mesh !")
</pre>
<p>Ce dernier point ferme la boucle ouverte tout au début. :sourit:</p>
<p>Et voilà! :bravo:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2011_03_12_remplir_un_mesh_de_spheres/remplir_un_mesh_de_spheres005.png" alt="remplir_un_mesh_de_spheres005.png" style="display:table; margin:0 auto;" title="remplir_un_mesh_de_spheres005.png, mar. 2011" /></p>
<p>Rappelez vous que cette méthode n'est pas très optimisée. Soyez donc un peu patient. :siffle:</p>
<center>:longBar:</center>
<h3>BEKRI Djelloul <a id="bekri_djelloul"></a></h3>
<p>Et parce que je pouvais pas finir ce tuto sans un dernier remercient à celui qui en est le principal créateur.</p>
<p>Un grand merci à Djelloul donc. N'hésitez pas à parcourir ces différentes pages pour avoir une idée de ses compétences. :sourit:</p>
<ul>
<li><a href="http://www.djelloul-bekri.fr/">Son site</a></li>
<li><a href="http://www.linkedin.com/pub/djelloul-bekri/4/70/b1a">Son LinkedIn</a></li>
<li><a href="http://www.imdb.com/name/nm1806860/">Son IMDB</a></li>
</ul>
<p>J'espère que ce tuto était clair et que vous avez appris des choses aujourd'hui. N'hésitez pas à laisser un commentaire si je n'ai pas été assez précis ou que certains points vous semblent encore flou.</p>Remplir un mesh de particules dans Maya: closestPointOnMesh again!urn:md5:114949baea14101d160231df46e1ec622010-09-22T23:52:00+02:002013-07-26T18:13:13+02:00NarannInfographie 3D - Boulotexpressionfrmayameshparticuleremplirscript<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule_tn.png" alt="remplir_mesh_particule_tn.png" style="float:left; margin: 0 1em 1em 0;" title="remplir_mesh_particule_tn.png, sept. 2010" height="150" width="150" />Boujour à tous! :dentcasse:</p>
<p>Dans Maya, il peut arriver que l'on veuille remplir un mesh de particules de manière complètement aléatoire. Il existe plusieurs méthodes pour ça.</p>
<p>On peut, par exemple, émettre des particules vers l'intérieur du mesh et les faire rebondir sur les parois. Mais cette méthode ne donne pas un résultat si aléatoire que ça. Et dans certains cas, cela se voit. :reflechi:</p>
<p>Si on a des pépettes, on peut aussi utiliser Houdini qui fait ça à merveille et récupérer les particules dans Maya.</p>
<p>Ce que je vous propose est une méthode un peu "clef en main". Vous sélectionnez votre mesh, appliquez le script, réglez deux trois trucs appuyez sur play pour lancer la génération et c'est bon!</p> <p>Si on a des pépettes, on peut aussi utiliser Houdini qui fait ça à merveille et récupérer les particules dans Maya.</p>
<p>Ce que je vous propose est une méthode un peu "clef en main". Vous sélectionnez votre mesh, appliquez le script, réglez deux trois trucs appuyez sur play pour lancer la génération et c'est bon!</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule001.png" alt="remplir_mesh_particule001.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule001.png, sept. 2010" height="397" width="470" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule002.png" alt="remplir_mesh_particule002.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule002.png, sept. 2010" height="397" width="470" /></p>
<p>Mais avant ça, je vais vous expliquer un peu comment ça marche. :reflechi:</p>
<center>:longBar:</center>
<h5>Theorie</h5>
<p>:mayaProf:</p>
<p>Alors alors, comment ça se passe?</p>
<p>Pour faire simple, il faut lancer des particules dans un espace/volume, de manière aléatoire, puis déterminer si la particule créé est dans un mesh ou non...</p>
<p>Créer des particules de manière aléatoire dans un espace, ça on sait faire via un volume emitter</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule003.png" alt="remplir_mesh_particule003.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule003.png, sept. 2010" height="189" width="216" /></p>
<p>Avec cette méthode, chaque particule créé est placé quelque part dans le cube ou la sphere.</p>
<p>Bien, mais comment savoir si ses particules sont dans un mesh? Et bien on va se servir d'un node dont je vois ai déjà parlé (faire un lien): closestPointOnMesh.</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_13_oriente_particle_maya/oriente_particle_maya002.png" alt="oriente_particle_maya002.png" style="display:block; margin:0 auto;" title="oriente_particle_maya002.png, sept. 2010" height="424" width="556" /></p>
<p>Ce node permet de faire pas mal de choses. On lui donne en entrée un mesh ainsi qu'une position dans l'espace, et il nous donne, en sortie, d'autres informations.</p>
<p>Les informations qui nous intéressent sont:</p>
<ul>
<li>La position, sur le mesh, du point le plus proche du point donné en entré.</li>
<li>La normale de ce point.</li>
</ul>
<p>Et il n'en faut pas plus pour déterminer, avec ses informations, si le point est à l'intérieur ou à l'exterieur du mesh (si si je vous assure! :dentcasse: ).</p>
<p>Les plus perspicaces d'entre vous l'auront remarqué, votre mesh se doit d'être un minimum propre pour faire fonctionner correctement cette méthode.</p>
<p>En effet, si les normales du mesh sont "bizarre", il ne s'en sortira pas! :nannan:</p>
<p>Le principe est le suivant:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_001.png" alt="Schema_001.png" style="display:block; margin:0 auto;" title="Schema_001.png, sept. 2010" height="448" width="436" /></p>
<ul>
<li>Vous prenez un point, dans l'espace, notre particule.</li>
</ul>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_002.png" alt="Schema_002.png" style="display:block; margin:0 auto;" title="Schema_002.png, sept. 2010" height="448" width="436" /></p>
<ul>
<li>Vous cherchez le point le plus proche de votre particule sur le mesh à remplir.</li>
</ul>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_003.png" alt="Schema_003.png" style="display:block; margin:0 auto;" title="Schema_003.png, sept. 2010" height="448" width="436" /></p>
<ul>
<li>Vous récupérez la normale de ce point (sous forme de vecteur).</li>
</ul>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_004.png" alt="Schema_004.png" style="display:block; margin:0 auto;" title="Schema_004.png, sept. 2010" height="448" width="436" /></p>
<ul>
<li>Vous soustrayez la position du point sur le mesh à la position de la particule pour obtenir un vecteur du point du mesh vers votre particule.</li>
</ul>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_005.png" alt="Schema_005.png" style="display:block; margin:0 auto;" title="Schema_005.png, sept. 2010" height="448" width="436" /></p>
<center><i>V1-V2=V3 :sourit:</i></center>
<ul>
<li>Vous récupérez l'angle entre ses deux vecteurs (vecteurs normale et vecteurs "point du mesh vers particule").</li>
</ul>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/Schema_006.png" alt="Schema_006.png" style="display:block; margin:0 auto;" title="Schema_006.png, sept. 2010" height="448" width="436" /></p>
<ul>
<li>Si cet angle est supérieur à 90 degrée, le point est à l'intérieur du mesh!</li>
</ul>
<p>La magie des maths!</p>
<center>:longBar:</center>
<h5>Pratique :mechantCrash:</h5>
<p>Allez, on y va! Commencez par créer un emitter volumetric:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule004.png" alt="remplir_mesh_particule004.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule004.png, sept. 2010" height="109" width="213" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule005.png" alt="remplir_mesh_particule005.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule005.png, sept. 2010" height="147" width="303" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule006.png" alt="remplir_mesh_particule006.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule006.png, sept. 2010" height="68" width="323" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule003.png" alt="remplir_mesh_particule003.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule003.png, sept. 2010" height="189" width="216" /></p>
<p>Créez un mesh:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule007.png" alt="remplir_mesh_particule007.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule007.png, sept. 2010" height="379" width="477" /></p>
<p>Créer un closestPointOnMesh:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule008.png" alt="remplir_mesh_particule008.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule008.png, sept. 2010" height="53" width="236" /></p>
<p>Connectez lui le mesh:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule009.png" alt="remplir_mesh_particule009.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule009.png, sept. 2010" height="111" width="606" /></p>
<center><i>worldMesh pour le mesh et worldMatrix pour savoir ou est placé le mesh dans l'espace. :hehe:</i></center>
<p>Maintenant on passe à la seconde partie de la création, la plus dur. :grenadelauncher:</p>
<p>Créez un expression de création de particule:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule010.png" alt="remplir_mesh_particule010.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule010.png, sept. 2010" height="52" width="140" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule011.png" alt="remplir_mesh_particule011.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule011.png, sept. 2010" height="61" width="348" /></p>
<p>Et voici l'expression:</p>
<pre class="mel mel">vector $particlePos <span style="color: #339933;">=</span> myParticleSystem.<span style="color: #202020;">position</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionX</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">x</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionY</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">y</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionZ</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">z</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #993333;">float</span> $pointPos<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">position</span>`<span style="color: #339933;">;</span>
<span style="color: #993333;">float</span> $n<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">normal</span>`<span style="color: #339933;">;</span>
vector $difference <span style="color: #339933;">=</span> myParticleSystem.<span style="color: #202020;">position</span> <span style="color: #339933;">-</span> <span style="color: #339933;"><<</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span>
vector $normal <span style="color: #339933;">=</span> <span style="color: #339933;"><<</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span>
<span style="color: #993333;">float</span> $test <span style="color: #339933;">=</span> rad_to_deg<span style="color: #009900;">(</span>angle<span style="color: #009900;">(</span>$normal<span style="color: #339933;">,</span>unit<span style="color: #009900;">(</span>$difference<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span>$test <span style="color: #339933;">></span> <span style="color: #0000dd;">90</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1000000</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>(Ouïe que je suis méchant! :gne2: )</p>
<p>Voici les explications:</p>
<pre class="mel mel">vector $particlePos <span style="color: #339933;">=</span> myParticleSystem.<span style="color: #202020;">position</span><span style="color: #339933;">;</span></pre>
<p>Ici, on récupère la position de la particule courante, celle qu'on va créer.</p>
<pre class="mel mel">setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionX</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">x</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionY</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">y</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionZ</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">z</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
<p>On entre les valeurs de position de la particule courante via "setAttr" (afin de s'assurer que le node est évalué).</p>
<pre class="mel mel"><span style="color: #993333;">float</span> $pointPos<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">position</span>`<span style="color: #339933;">;</span></pre>
<p>Dans le même esprit que précédemment, ici on récupère la position du point le plus proche de notre particule.</p>
<pre class="mel mel"><span style="color: #993333;">float</span> $n<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">normal</span>`<span style="color: #339933;">;</span></pre>
<p>On récupère, dans un array de float, les valeurs XYZ de la normal du point (sur le mesh) le plus proche de notre particule.</p>
<pre class="mel mel">vector $difference <span style="color: #339933;">=</span> myParticleSystem.<span style="color: #202020;">position</span> <span style="color: #339933;">-</span> <span style="color: #339933;"><<</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span></pre>
<p>On récupère le vecteur du "point sur la surface" vers la position de la particule (rappelez vous! Le coups de la soustraction des vecteurs. C'est ici! :hehe: ).</p>
<pre class="mel mel">vector $normal <span style="color: #339933;">=</span> <span style="color: #339933;"><<</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span></pre>
<p>On "convertie" nos valeurs de normal (qui étaient dans un array), en vecteur.</p>
<pre class="mel mel"><span style="color: #993333;">float</span> $test <span style="color: #339933;">=</span> rad_to_deg<span style="color: #009900;">(</span>angle<span style="color: #009900;">(</span>$normal<span style="color: #339933;">,</span> unit<span style="color: #009900;">(</span>$difference<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
<p>On récupère l'angle (en radian) entre les deux vecteurs ($normal et $difference) que l'on convertie en dégrée. (unit() sert à normaliser un vecteur, angle() sert a récupérer l'angle en radian entre deux vecteur et rad_to_deg() convertie un angle radian en dégrée).</p>
<pre class="mel mel"><span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span>$test <span style="color: #339933;">></span> <span style="color: #0000dd;">90</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1000000</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>Et pour finir, on test la valeur de l'angle. Si il est supérieur à 90°, on considère que la particule à une durée de vie infini (enfin très grande... :pasClasse: ).</p>
<p>Sinon, on la fait directement "mourrir" :gniarkgniark: .</p>
<center>:longBar:</center>
<h5>Le script MEL</h5>
<p>Ouf, bon, maintenant que vous avez tout bien compris (n'est ce pas? :seSentCon: ), je vous donne un script qui vous créé ce petit système tout seul!</p>
<p>La seul chose que vous ayez à faire, c'est sélectionner un mesh, appliquer le script et bien placer le cube emitter pour qu'il englobe intelligemment la géométrie. Lancer la dynamique (play) et c'est bon!</p>
<pre class="mel mel"><span style="color: #009900;">{</span>
string $mySelectedMeshArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `ls <span style="color: #339933;">-</span>sl`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on récupère la sélection</span>
string $mySelectedMesh <span style="color: #339933;">=</span> $mySelectedMeshArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on ne prend que le premier élément de la selection</span>
string $mySelectedMeshShapeArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `listRelatives <span style="color: #339933;">-</span>shapes $mySelectedMesh`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on récupère le node de mesh depuis le node de transforme</span>
string $mySelectedMeshShape <span style="color: #339933;">=</span> $mySelectedMeshShapeArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on ne prend que le premier élément de la liste renvoyé</span>
string $myClosestPointOnMeshNode <span style="color: #339933;">=</span> `createNode closestPointOnMesh`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on cree le node de closestPointOnMesh</span>
connectAttr <span style="color: #339933;">-</span>f <span style="color: #009900;">(</span>$mySelectedMeshShape<span style="color: #339933;">+</span><span style="color: #ff0000;">".worldMesh[0]"</span><span style="color: #009900;">)</span> <span style="color: #009900;">(</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inMesh"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on lui connecte le mesh</span>
connectAttr <span style="color: #339933;">-</span>f <span style="color: #009900;">(</span>$mySelectedMeshShape<span style="color: #339933;">+</span><span style="color: #ff0000;">".worldMatrix[0]"</span><span style="color: #009900;">)</span> <span style="color: #009900;">(</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inputMatrix"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// et la matrice de transformation</span>
<span style="color: #666666; font-style: italic;">//create Emitter Volume</span>
string $myEmitterArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `emitter <span style="color: #339933;">-</span>pos <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>type volume <span style="color: #339933;">-</span>r <span style="color: #0000dd;">100</span> <span style="color: #339933;">-</span>sro <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>nuv <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>cye none <span style="color: #339933;">-</span>cyi <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>spd <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>srn <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>nsp <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>tsp <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>mxd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>mnd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>dx <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>dy <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>dz <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>sp <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>vsh cube <span style="color: #339933;">-</span>vof <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>vsw <span style="color: #0000dd;">360</span> <span style="color: #339933;">-</span>tsr <span style="color:#800080;">0.5</span> <span style="color: #339933;">-</span>afc <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>afx <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>arx <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>alx <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>rnd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>drs <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>ssz <span style="color: #0000dd;">0</span>`<span style="color: #339933;">;</span>
string $myEmitter <span style="color: #339933;">=</span> $myEmitterArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span>
string $myParticleSystemArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `particle`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// créé un système de particule</span>
string $myParticleSystem <span style="color: #339933;">=</span> $myParticleSystemArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span>
connectDynamic <span style="color: #339933;">-</span>em $myEmitter $myParticleSystem<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// connecte l'emitter au système de particule</span>
setAttr <span style="color: #009900;">(</span>$myEmitter<span style="color: #339933;">+</span><span style="color: #ff0000;">".awayFromCenter"</span><span style="color: #009900;">)</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// désactive la vitesse des particules</span>
setAttr <span style="color: #009900;">(</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanMode"</span><span style="color: #009900;">)</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on va mettre le lifespan nous même</span>
<span style="color: #666666; font-style: italic;">// créé l'expression</span>
string $expression <span style="color: #339933;">=</span> <span style="color: #ff0000;">"vector $particlePos = "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".position;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionX ($particlePos.x);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionY ($particlePos.y);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionZ ($particlePos.z);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $n[] = `getAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".normal`;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $pointPos[] = `getAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".position`;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $difference = "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".position - <<$pointPos[0],$pointPos[1],$pointPos[2]>>;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $normal = <<$n[0],$n[1],$n[2]>>;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $test = rad_to_deg(angle($normal,unit($difference)));<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"if ($test > 90)<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"{<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanPP = 1000000;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"}<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"else<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"{<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanPP = 0;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"}<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
dynExpression <span style="color: #339933;">-</span>s $expression <span style="color: #339933;">-</span>c $myParticleSystem<span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>Et voila!</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule001.png" alt="remplir_mesh_particule001.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule001.png, sept. 2010" height="397" width="470" /></p>
<p>Et comme toujours: <a href="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule001.rar">->la scène Maya<</a> (bouton droit de souris, save as...).</p>
<center>:longBar:</center>
<h5>Conclusion</h5>
<p>Bien entendu, il reste un bon nombre de méthodes pour optimiser ce script (utiliser des produits scalaires plutôt que des angles, le lifespanPP = 1000000 est pas forcément des plus pratique, etc...).</p>
<p>Mais le principe est là! :)</p>
<p>N'hésitez pas à laisser un commentaire si vous voyez un moyen d'améliorer ce script. Je mettrai ce billet à jour.</p>
<center>:longBar:</center>
<h5>Le lien qui m'a beaucoup aidé</h5>
<p><a href="http://blog.maxtorag.sk/?p=39" hreflang="en">http://blog.maxtorag.sk/?p=39</a></p>
<p>Un grand merci à son auteur! :sourit:</p>
<p>A bientôt!</p>
<p>Dorian</p>
<center>:longBar:</center>
<h5>MAJ 8 Mars 2010 <a name="maj_8_mars_2010"></a></h5>
<p>On peut facilement faire évoluer cette expression. :reflechi:</p>
<p>L'exemple ci dessous vous permet de faire un dégradé du nombre de particules générées sur les bords du mesh.</p>
<pre class="mel mel"><span style="color: #993333;">float</span> $fallOffDist <span style="color: #339933;">=</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// la distance le long de laquelle la génération des particules est diminué.</span>
vector $particlePos <span style="color: #339933;">=</span> myParticleSystem.<span style="color: #202020;">position</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionX</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">x</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionY</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">y</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
setAttr myClosestPointOnMeshNode.<span style="color: #202020;">inPositionZ</span> <span style="color: #009900;">(</span>$particlePos.<span style="color: #202020;">z</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #993333;">float</span> $n<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">normal</span>`<span style="color: #339933;">;</span>
<span style="color: #993333;">float</span> $pointPos<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `getAttr myClosestPointOnMeshNode.<span style="color: #202020;">position</span>`<span style="color: #339933;">;</span>
vector $pointPosVec <span style="color: #339933;">=</span> <span style="color: #339933;"><<</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$pointPos<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span>
vector $difference <span style="color: #339933;">=</span> particleShape1.<span style="color: #202020;">position</span> <span style="color: #339933;">-</span> $pointPosVec<span style="color: #339933;">;</span>
vector $normal <span style="color: #339933;">=</span> <span style="color: #339933;"><<</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">1</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span>$n<span style="color: #009900;">[</span><span style="color: #0000dd;">2</span><span style="color: #009900;">]</span><span style="color: #339933;">>>;</span>
<span style="color: #993333;">float</span> $test <span style="color: #339933;">=</span> rad_to_deg<span style="color: #009900;">(</span>angle<span style="color: #009900;">(</span>$normal<span style="color: #339933;">,</span>unit<span style="color: #009900;">(</span>$difference<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span>$test <span style="color: #339933;">></span> <span style="color: #0000dd;">90</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
<span style="color: #993333;">float</span> $dist <span style="color: #339933;">=</span> mag<span style="color: #009900;">(</span>$particlePos <span style="color: #339933;">-</span> $pointPosVec<span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on calcule la distance entre la particule et le point sur le mesh</span>
<span style="color: #993333;">float</span> $luck <span style="color: #339933;">=</span> $dist<span style="color: #339933;">/</span>$fallOffDist<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on fait un ratio.</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">(</span>$luck <span style="color: #339933;">></span> rand<span style="color: #009900;">(</span><span style="color: #0000dd;">1</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #666666; font-style: italic;">// si le ratio est plus grand qu'une valeur alléatoire entre 0 et 1, on genere la particule.</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1000000</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #009900;">}</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">{</span>
myParticleSystem.<span style="color: #202020;">lifespanPP</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>Il suffit de faire varier la variable $fallOffDist pour agrandir ou diminuer la taille du dégradé.</p>
<p>Bien entendu, cette méthode est beaucoup plus longue que la précédente (qui n'était déjà pas un exemple en terme de rapidité. :seSentCon: ).</p>
<p>Exemple:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule012.png" alt="remplir_mesh_particule012.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule012.png, mar. 2011" height="360" width="500" /></p>
<center><i>Avant. Les bords de la géométrie sont très facilement discernables.</i></center>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_09_22_remplir_mesh_particule/remplir_mesh_particule013.png" alt="remplir_mesh_particule013.png" style="display:block; margin:0 auto;" title="remplir_mesh_particule013.png, mar. 2011" height="360" width="500" /></p>
<center><i>Après. On voit bien que les bords ont moins de particules que l'intérieur.</i></center>
<p>Ducoup, le script MEL de génération de l'expression sur le mesh selectionné est le suivant:</p>
<pre class="mel mel"><span style="color: #009900;">{</span>
string $mySelectedMeshArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `ls <span style="color: #339933;">-</span>sl`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on récupère la sélection</span>
string $mySelectedMesh <span style="color: #339933;">=</span> $mySelectedMeshArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on ne prend que le premier élément de la selection</span>
string $mySelectedMeshShapeArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `listRelatives <span style="color: #339933;">-</span>shapes $mySelectedMesh`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on récupère le node de mesh depuis le node de transforme</span>
string $mySelectedMeshShape <span style="color: #339933;">=</span> $mySelectedMeshShapeArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on ne prend que le premier élément de la liste renvoyé</span>
string $myClosestPointOnMeshNode <span style="color: #339933;">=</span> `createNode closestPointOnMesh`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on cree le node de closestPointOnMesh</span>
connectAttr <span style="color: #339933;">-</span>f <span style="color: #009900;">(</span>$mySelectedMeshShape<span style="color: #339933;">+</span><span style="color: #ff0000;">".worldMesh[0]"</span><span style="color: #009900;">)</span> <span style="color: #009900;">(</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inMesh"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on lui connecte le mesh</span>
connectAttr <span style="color: #339933;">-</span>f <span style="color: #009900;">(</span>$mySelectedMeshShape<span style="color: #339933;">+</span><span style="color: #ff0000;">".worldMatrix[0]"</span><span style="color: #009900;">)</span> <span style="color: #009900;">(</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inputMatrix"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// et la matrice de transformation</span>
<span style="color: #666666; font-style: italic;">//create Emitter Volume</span>
string $myEmitterArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `emitter <span style="color: #339933;">-</span>pos <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>type volume <span style="color: #339933;">-</span>r <span style="color: #0000dd;">100</span> <span style="color: #339933;">-</span>sro <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>nuv <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>cye none <span style="color: #339933;">-</span>cyi <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>spd <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>srn <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>nsp <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>tsp <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>mxd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>mnd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>dx <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>dy <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>dz <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>sp <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>vsh cube <span style="color: #339933;">-</span>vof <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>vsw <span style="color: #0000dd;">360</span> <span style="color: #339933;">-</span>tsr <span style="color:#800080;">0.5</span> <span style="color: #339933;">-</span>afc <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>afx <span style="color: #0000dd;">1</span> <span style="color: #339933;">-</span>arx <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>alx <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>rnd <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>drs <span style="color: #0000dd;">0</span> <span style="color: #339933;">-</span>ssz <span style="color: #0000dd;">0</span>`<span style="color: #339933;">;</span>
string $myEmitter <span style="color: #339933;">=</span> $myEmitterArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span>
string $myParticleSystemArray<span style="color: #009900;">[</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> `particle`<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// créé un système de particule</span>
string $myParticleSystem <span style="color: #339933;">=</span> $myParticleSystemArray<span style="color: #009900;">[</span><span style="color: #0000dd;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">;</span>
connectDynamic <span style="color: #339933;">-</span>em $myEmitter $myParticleSystem<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// connecte l'emitter au système de particule</span>
setAttr <span style="color: #009900;">(</span>$myEmitter<span style="color: #339933;">+</span><span style="color: #ff0000;">".awayFromCenter"</span><span style="color: #009900;">)</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// désactive la vitesse des particules</span>
setAttr <span style="color: #009900;">(</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanMode"</span><span style="color: #009900;">)</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// on va mettre le lifespan nous même</span>
<span style="color: #666666; font-style: italic;">// créé l'expression</span>
string $expression <span style="color: #339933;">=</span> <span style="color: #ff0000;">"float $fallOffDist = 2;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $particlePos = "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".position;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionX ($particlePos.x);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionY ($particlePos.y);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"setAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".inPositionZ ($particlePos.z);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $n[] = `getAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".normal`;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $pointPos[] = `getAttr "</span><span style="color: #339933;">+</span>$myClosestPointOnMeshNode<span style="color: #339933;">+</span><span style="color: #ff0000;">".position`;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $pointPosVec = <<$pointPos[0],$pointPos[1],$pointPos[2]>>;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $difference = "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".position - $pointPosVec;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"vector $normal = <<$n[0],$n[1],$n[2]>>;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"float $test = rad_to_deg(angle($normal,unit($difference)));<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"if ($test > 90)<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"{<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" float $dist = mag($particlePos - $pointPosVec);<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" float $luck = $dist/$fallOffDist;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" if($luck > rand(1))<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" {<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanPP = 1000000;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" }<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" else<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" {<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanPP = 0;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" }<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"}<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"else<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"{<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">" "</span><span style="color: #339933;">+</span>$myParticleSystem<span style="color: #339933;">+</span><span style="color: #ff0000;">".lifespanPP = 0;<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
$expression <span style="color: #339933;">+=</span> <span style="color: #ff0000;">"}<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #339933;">;</span>
dynExpression <span style="color: #339933;">-</span>s $expression <span style="color: #339933;">-</span>c $myParticleSystem<span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>En espérant que ça vous aide! :sourit:</p>