# articles

feed_id: urn:md5:83166070f4695a715ca359133a4fb7a0
uri: Resolve-network-slowdowns-due-to-Nuke-After-Effects-and-other-softwar
title:
Resolve network slowdowns due to Nuke, After Effects and others software like them (English Translation)

url:
http://www.fevrierdorian.com/blog/post/2012/10/19/Resolve-network-slowdowns-due-to-Nuke-After-Effects-and-other-softwares-like-them

content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2012_10_14_nuke_reseau_lenteurs/nuke_reseau_tn.png" alt="nuke_reseau_tn.png" style="float:left; margin: 0 1em 1em 0;" title="nuke_reseau_tn.png, oct. 2012"  height="150" width="150" />This is an english translation of a <a href="http://www.fevrierdorian.com/blog/post/2012/10/14/Resoudre-les-ralentissements-reseaux-dus-a-Nuke-After-Effect-et-autres-logiciels-du-genre">ticket I wrote</a> (in french <img src="/blog/themes/blueSilenceCustom/smilies/france.gif" alt=":franceHappy:" class="smiley" /> ) few days ago.</p>


<p>Nuke, After Effects and probably others, can be very "greedy" in terms of disk accesses. So much so they can break network performances drastically if several stations are renderings.</p>


<p>In this ticket I purpose a quick explanation of the why and how and a small Python class that can be used as a prototype to solve the problem.</p>    <h3>What's the problem?</h3>

<p>Nothing better than a concrete case to state the thing:</p>


<p>At the end of <a href="http://www.imdb.com/title/tt1482459/" hreflang="en">Lorax</a>, there was a big number of "compers" (compositors) who was rendering their images all at the same time and time estimations given by Nuke was sometime surprising (3h-4h left for a simple nuke script). Monitoring a file being written, I realized it weight was increasing very slowly. It was 100ko, then 300ko, then after 10 minutes it became 400ko etc... I concluded the network was overloaded... <img src="/blog/themes/blueSilenceCustom/smilies/reflexionIntense.gif" alt=":reflexionIntense:" class="smiley" /></p>


<p>I remembered that we had the same worries on <a href="http://www.allocine.fr/film/fichefilm_gen_cfilm=183772.html" hreflang="fr">Tales Of The Night</a>. Our infrastructure was certainly much smaller but 3 After Effect render was "pumping" the entire network. The found solution at that time was to render the file in local and copy it once finished. The effects were immediate: No more slowdown with the network. <img src="/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>So I tried to render the nuke script of a CG artist locally to see if it reduce the problem. The largest files to read were source files (because they are many), and the final image weight was actually very light so I was under no illusions. But once again, the conclusion was clear: The rendering was finished in 10-15 minutes (I'm not kidding) instead of 3-4hrs... <img src="/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>I've thought it was maybe the writing process which was a problem. However, when I copied the newly calculated image sequence to the server disks, the copy was very fast. So I've done this with every artist, one by one, and in a big afternoon, the network has no bottleneck anymore and all render ended up.</p>


<p>But that was not a solution. We had to understand why Nuke couldn't write it images quickly through the network. After <a href="http://forums.thefoundry.co.uk/phpBB2/viewtopic.php?p=29117" hreflang="en">have asked</a> on the nuke-users mailing list (where I could see I was not alone but The Foundry doesn't seemed able to change this), I've started to "profile" Nuke to know how it does the job (<a href="http://en.wikipedia.org/wiki/Strace" hreflang="en">strace</a> and <a href="http://linux.die.net/man/1/inotifywatch" hreflang="en">inotifywatch</a> are you friends <img src="/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> ).</p>


<p>Conclusions seems obvious but it's always good to check in practice what you suspect:</p>


<p>With Nuke, if you write a <em>zip 1 line</em> compressed EXR, in 1920x1080, Nuke will do a little less than 900 (approximately) write accesses on the file. If you are in <em>zip 16 lines</em>, it will do about 70 accesses (1080/16). And in uncompressed, that's really 1080 accesses. <img src="/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></p>


<p>In facts, compress in <em>zip 16 line</em> is not efficient if images should be read by Nuke. And depending of your network infrastructure, write line by line can put it completely down. It's difficult to explain how finally few Nuke rendering can fill a network, even if this one is strong. I feel this is related to multithreading: Nuke reads images (often, many at the same time) on the network while it is writing through it.</p>


<p>The most obvious solution is therefore to write the rendered image(s) on the local disk and to copy it in one time (one access) on the network disk. If you don't have technical resources (or just time), it's the simplest approach, but on larger projects it can quickly become daunting and (lest we forget) source of errors.</p>


<p>There are several solutions and I was leaning on a prototype that I found interesting because it's easy to implement.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2012_10_14_nuke_reseau_lenteurs/problems.jpg" alt="problems.jpg" style="display:block; margin:0 auto;" title="problems.jpg, oct. 2012"  height="440" width="720" /></p>


<h3>The principle</h3>

<ul>
<li>You launch a Python thread that will watch a folder.</li>
<li>Every three seconds, the thread will list present files in a folder and check if their name will match to a given regular expression (the "pattern" of your file name).</li>
<li>If the file seems to be a file you want to move once finished, it search the same file with ".finished" (example: "toto.001.exr.finished").</li>
<li>If this file exists, it move the origin file and remove the ".finished" one and start the main loop again.</li>
<li>Once the render is done (so every images are finished), you ask the thread to stop itself.</li>
</ul>

<p>As you can see, this method requires that you create a ".finished" file each time an images is finished. This is because it's impossible for the thread to know when an image is actually completed. The creation of this ".finished" file can be handled in a thousand different ways (For Maya, a simple "Post render frame" should do the job) so I will not go into details. <img src="/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<h3>The code</h3>


<p>Here it is:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">threading</span>, <span style="color: #dc143c;">re</span>, <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MoverThread<span style="color: black;">&#40;</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span> <span style="color: black;">&#41;</span> :
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>, dirTocheck, dirToMoveIn, patternToCheck, force=<span style="color: #008000;">False</span> <span style="color: black;">&#41;</span> :
		<span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #008000;">self</span>._terminate = <span style="color: #008000;">False</span>
		<span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> = dirTocheck
		<span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> = dirToMoveIn
		<span style="color: #008000;">self</span>.<span style="color: black;">force</span> = force
&nbsp;
		<span style="color: #808080; font-style: italic;"># regex pattern</span>
		<span style="color: #008000;">self</span>.<span style="color: black;">patternToCheck</span> = patternToCheck
		<span style="color: #008000;">self</span>.<span style="color: black;">rePattern</span> = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span> patternToCheck <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># sanity check</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span><span style="color: black;">&#41;</span> :
			<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;The given directory (dirTocheck) is not a valid directory -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span>  <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span><span style="color: black;">&#41;</span> :
			<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;The given directory (dirToMoveIn) is not a valid directory -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span>  <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span> :
&nbsp;
		filesNotMoved = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>._terminate :
&nbsp;
			<span style="color: #808080; font-style: italic;"># we wait 3 seconds before do anything</span>
			<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span> <span style="color: #ff4500;">3</span> <span style="color: black;">&#41;</span>
&nbsp;
			<span style="color: #808080; font-style: italic;"># for every &quot;entry&quot; (file or folder) in the folder we check it have the good pattern. If it has, we check for a &quot;.finished&quot; file</span>
			<span style="color: #ff7700;font-weight:bold;">for</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> <span style="color: black;">&#41;</span> :
&nbsp;
				<span style="color: #808080; font-style: italic;"># check the current entry is &quot;compliant&quot; with the given regex</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">rePattern</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span> entry <span style="color: black;">&#41;</span> :
					<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
				srcFilePath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span>, entry <span style="color: black;">&#41;</span>
				dstFilePath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span>, entry <span style="color: black;">&#41;</span>
&nbsp;
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span> srcFilePath+<span style="color: #483d8b;">&quot;.finished&quot;</span> <span style="color: black;">&#41;</span> :
&nbsp;
					<span style="color: #808080; font-style: italic;"># destination file aready exist?</span>
					<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span> dstFilePath <span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">force</span>:
&nbsp;
						<span style="color: #808080; font-style: italic;"># don't add the entry if it is already in the list</span>
						<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> filesNotMoved :
							filesNotMoved.<span style="color: black;">append</span><span style="color: black;">&#40;</span> entry <span style="color: black;">&#41;</span>
&nbsp;
						<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
					<span style="color: #808080; font-style: italic;"># move the file to it new location</span>
					<span style="color: #dc143c;">os</span>.<span style="color: black;">rename</span><span style="color: black;">&#40;</span> srcFilePath, dstFilePath <span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">os</span>.<span style="color: black;">remove</span><span style="color: black;">&#40;</span> srcFilePath+<span style="color: #483d8b;">&quot;.finished&quot;</span> <span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;File %s moved to %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span> entry, <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">break</span>	<span style="color: #808080; font-style: italic;"># restart the while loop to avoid to continue the list of file we maybe have removed: &quot;.finished&quot;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Terminated!&quot;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">for</span> fileNotMoved <span style="color: #ff7700;font-weight:bold;">in</span> filesNotMoved :
			<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Already exists: Can't move %s to %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span> fileNotMoved, <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> join<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span> :
&nbsp;
		<span style="color: #008000;">self</span>._terminate = <span style="color: #008000;">True</span>
&nbsp;
		<span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span></pre>

<p>As you can see (or not), everything happen in a thread.</p>


<p>It's used like this:</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> waitFinishAndCopy
myMoverThread = waitFinishAndCopy.<span style="color: black;">MoverThread</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/a/local/path/&quot;</span>, <span style="color: #483d8b;">&quot;/a/network/path/&quot;</span>, <span style="color: #483d8b;">&quot;^toto<span style="color: #000099; font-weight: bold;">\.</span>[0-9]{4}<span style="color: #000099; font-weight: bold;">\.</span>exr$&quot;</span><span style="color: black;">&#41;</span>
myMoverThread.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># start rendering, do rendering, end rendering.</span>
myMoverThread.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>


<p>And voila!</p>


<h3>Conclusion</h3>


<p>I hope this modest prototype will inspire you if you are experiencing delays on your network. <img src="/blog/themes/blueSilenceCustom/smilies/mechantCrash.gif" alt=":mechantCrash:" class="smiley" /></p>


<p>I also suggest to do some profiling on your core network applications, especially if they are used by many people. Their behavior is always interesting (and sometimes surprising).</p>


<p>Have a nice day!</p>


<p>Dorian</p>

<center><img src="/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:df614baf78d8e7e03917d6ade3fef585
title: Résoudre les ralentissements réseaux dûs a Nuke, After Effect et autres logiciels du genre
uri: Résoudre-les-ralentissements-réseaux-dûs-a-Nuke-After-Effect-et-au
url:
http://www.fevrierdorian.com/blog/post/2012/10/14/Resoudre-les-ralentissements-reseaux-dus-a-Nuke-After-Effect-et-autres-logiciels-du-genre

content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2012_10_14_nuke_reseau_lenteurs/nuke_reseau_tn.png" alt="nuke_reseau_tn.png" style="float:left; margin: 0 1em 1em 0;" title="nuke_reseau_tn.png, oct. 2012"  height="150" width="150" />Nuke, After Effect et surement d'autres, peuvent se révéler très "gourmand" en terme d’accès disque. A tel point qu'ils peuvent rapidement mettre des disques réseaux à genoux si plusieurs stations font des rendus.</p>


<p>Dans ce billet je vous propose une explication rapide du comment du pourquoi ainsi qu'une petite classe Python qui fait office de prototype pour solutionner le probleme.</p>    <h3>C'est quoi le problème?</h3>

<p>Rien de mieux qu'un cas concret pour énoncer la chose:</p>


<p>Sur la fin de <a href="http://www.allocine.fr/film/fichefilm_gen_cfilm=170530.html" hreflang="fr">Lorax</a>, il y avait un grand nombre de "compeurs" (compositeurs) qui rendaient leurs images en même temps et les estimations affichées par Nuke étaient parfois surprenantes (3h-4h restantes pour des compos simples). En surveillant un fichier en train de s’écrire, je me suis rendu compte qu'il montait très lentement. Il était à 100ko, puis passait à 300ko, puis au bout de dix secondes passait à 400ko etc... J'en ai conclu que le réseau était surchargé... <img src="/blog/themes/blueSilenceCustom/smilies/reflexionIntense.gif" alt=":reflexionIntense:" class="smiley" /></p>


<p>Je me suis rappelé que nous avions eu le même soucis sur <a href="http://www.allocine.fr/film/fichefilm_gen_cfilm=183772.html" hreflang="fr">Les Contes De La Nuit</a>. Notre infrastructure était, certes, beaucoup plus modeste mais 3 After Effect en rendu plombaient l’intégralité du réseau. La solution trouvé à ce moment la fut de rendre en local puis de copier les fichier une fois finis. Les effets furent immédiats: Le réseau ne ramait plus. <img src="/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>J'ai donc tenté de rendre le compo d'un graphiste en local pour voir si cela diminuait le problème. Les plus gros fichiers à lires étant les fichiers sources, car plus nombreux, et l'image rendu étant relativement légère, je ne me faisais pas trop d'illusions. Et pourtant, une fois de plus, le constat est sans appel: Le rendu se finissait en 10-15 minutes (je ne rigole pas) au lieu de 3-4h... <img src="/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>Je me suis dis que c’était l’écriture qui devait poser problème. Pourtant, quand je copiais la séquence d'image fraichement calculée, la copie était très rapide. Je suis donc passé voir les graphistes les uns après les autres et en un gros après midi, le réseau était complètement désengorgé et les rendus passèrent tous.</p>


<p>Mais ce n’était pas une solution. Il fallait comprendre pourquoi Nuke n'arrivait pas à écrire ces images rapidement sur le réseau. Après avoir <a href="http://forums.thefoundry.co.uk/phpBB2/viewtopic.php?p=29117" hreflang="en">posé la question</a> sur la mailing list nuke-users (ou j'ai pu constater que je n’étais pas seul mais que The Foundry semblait ne rien pouvoir faire), j'ai commencé à "profiler" Nuke pour savoir comment ils s'y prenait (<a href="http://fr.wikipedia.org/wiki/Strace" hreflang="fr">strace</a> et <a href="http://linux.die.net/man/1/inotifywatch" hreflang="en">inotifywatch</a> sont tes amis <img src="/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> ).</p>


<p>Les conclusions semblent évidentes mais il est toujours bon de vérifier par la pratique ce qu'on soupçonne:</p>


<p>Sous Nuke, si vous écrivez un EXR compressé <em>zip 1 line</em>, en 1920x1080, Nuke fera  un peu moins de 900 (et des brouettes) accès en écriture sur le fichier. Si vous êtes en <em>zip 16 lines</em>, il fera environs 70 accès (1080/16). Et en non compressé c'est réellement 1080 accès. <img src="/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></p>


<p>Dans les fait, compresser en <em>zip 16 line</em> n'est pas super efficace si les images doivent être lus par Nuke. Et suivant l'infrastructure de votre réseau, écrire ligne à ligne peut le mettre complètement à plat. Il est difficile d'expliquer comment finalement peu de rendus Nuke sont nécessaires pour plomber un réseau, même si ce dernier est costaud. J'ai la sensation que c'est lié au multithreading: Nuke lit des images (souvent beaucoup en même temps) sur le réseau pendant qu'il y écrit.</p>


<p>La solution la plus évidente reste donc d’écrire l'image (les images) rendu sur le disque local et de la copier en une fois (un seul accès) sur le disque réseau. Si vous ne disposez pas des ressources techniques nécessaires ou bien tout simplement de temps, c'est l'approche la plus simple mais sur des projets plus conséquents ça peut rapidement devenir rébarbatif et (ne l'oublions pas) source d'erreurs.</p>


<p>Il y a plusieurs solutions et je m’étais penché sur un prototype que je trouvais intéressant car facile à mettre en place.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2012_10_14_nuke_reseau_lenteurs/problems.jpg" alt="problems.jpg" style="display:block; margin:0 auto;" title="problems.jpg, oct. 2012"  height="440" width="720" /></p>


<h3>Le principe</h3>

<ul>
<li>Vous lancez un thread python qui va surveiller un dossier.</li>
<li>Toute les trois secondes le thread va lister les fichiers présents dans le dossier et voir si leur nom correspond à une expression régulière (le "modèle" de votre nom de fichier).</li>
<li>Si le fichier semble être un fichier que vous souhaitez déplacer une fois fini, il cherche ce même fichier avec ".finished" (exemple: "toto.001.exr.finished").</li>
<li>Si ce fichier existe, il déplace le fichier d'origine et supprime son équivalent en ".finished" puis relance la boucle principale.</li>
<li>Une fois le rendu fini, vous donner l'ordre au thread de s’arrêter.</li>
</ul>

<p>Comme vous pouvez le voir, ce système nécessite que vous créiez un fichier ".finished" à chaque fois qu'une image est fini. C'est dû au fait qu'il est impossible pour le thread de savoir à quel moment une image est fini de calculer et complète (et ducoup, quand il peut le lancer la copie). La création de ce ".finished" peut être géré de mille façons différentes (Pour Maya, un "Post render frame" fait l'affaire) donc je ne rentre pas dans les détails. <img src="/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<h3>Le code</h3>


<p>Voici le code brut de décoffrage:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">threading</span>, <span style="color: #dc143c;">re</span>, <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MoverThread<span style="color: black;">&#40;</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span> <span style="color: black;">&#41;</span> :
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>, dirTocheck, dirToMoveIn, patternToCheck, force=<span style="color: #008000;">False</span> <span style="color: black;">&#41;</span> :
		<span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #008000;">self</span>._terminate = <span style="color: #008000;">False</span>
		<span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> = dirTocheck
		<span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> = dirToMoveIn
		<span style="color: #008000;">self</span>.<span style="color: black;">force</span> = force
&nbsp;
		<span style="color: #808080; font-style: italic;"># regex pattern</span>
		<span style="color: #008000;">self</span>.<span style="color: black;">patternToCheck</span> = patternToCheck
		<span style="color: #008000;">self</span>.<span style="color: black;">rePattern</span> = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span> patternToCheck <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># sanity check</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span><span style="color: black;">&#41;</span> :
			<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;The given directory (dirTocheck) is not a valid directory -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span>  <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span><span style="color: black;">&#41;</span> :
			<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;The given directory (dirToMoveIn) is not a valid directory -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span>  <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span> :
&nbsp;
		filesNotMoved = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>._terminate :
&nbsp;
			<span style="color: #808080; font-style: italic;"># we wait 3 seconds before do anything</span>
			<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span> <span style="color: #ff4500;">3</span> <span style="color: black;">&#41;</span>
&nbsp;
			<span style="color: #808080; font-style: italic;"># for every &quot;entry&quot; (file or folder) in the folder we check it have the good pattern. If it has, we check for a &quot;.finished&quot; file</span>
			<span style="color: #ff7700;font-weight:bold;">for</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span> <span style="color: black;">&#41;</span> :
&nbsp;
				<span style="color: #808080; font-style: italic;"># check the current entry is &quot;compliant&quot; with the given regex</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">rePattern</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span> entry <span style="color: black;">&#41;</span> :
					<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
				srcFilePath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirTocheck</span>, entry <span style="color: black;">&#41;</span>
				dstFilePath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span>, entry <span style="color: black;">&#41;</span>
&nbsp;
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span> srcFilePath+<span style="color: #483d8b;">&quot;.finished&quot;</span> <span style="color: black;">&#41;</span> :
&nbsp;
					<span style="color: #808080; font-style: italic;"># destination file aready exist?</span>
					<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span> dstFilePath <span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">force</span>:
&nbsp;
						<span style="color: #808080; font-style: italic;"># don't add the entry if it is already in the list</span>
						<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> filesNotMoved :
							filesNotMoved.<span style="color: black;">append</span><span style="color: black;">&#40;</span> entry <span style="color: black;">&#41;</span>
&nbsp;
						<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
					<span style="color: #808080; font-style: italic;"># move the file to it new location</span>
					<span style="color: #dc143c;">os</span>.<span style="color: black;">rename</span><span style="color: black;">&#40;</span> srcFilePath, dstFilePath <span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">os</span>.<span style="color: black;">remove</span><span style="color: black;">&#40;</span> srcFilePath+<span style="color: #483d8b;">&quot;.finished&quot;</span> <span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;File %s moved to %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span> entry, <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">break</span>	<span style="color: #808080; font-style: italic;"># restart the while loop to avoid to continue the list of file we maybe have removed: &quot;.finished&quot;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Terminated!&quot;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">for</span> fileNotMoved <span style="color: #ff7700;font-weight:bold;">in</span> filesNotMoved :
			<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Already exists: Can't move %s to %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span> fileNotMoved, <span style="color: #008000;">self</span>.<span style="color: black;">dirToMoveIn</span> <span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> join<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span> :
&nbsp;
		<span style="color: #008000;">self</span>._terminate = <span style="color: #008000;">True</span>
&nbsp;
		<span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span></pre>

<p>Comme vous pouvez le voir (ou pas), tout ce passe dans une thread.</p>


<p>Ca s'utilise comme ça:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> waitFinishAndCopy
myMoverThread = waitFinishAndCopy.<span style="color: black;">MoverThread</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/a/local/path/&quot;</span>, <span style="color: #483d8b;">&quot;/a/network/path/&quot;</span>, <span style="color: #483d8b;">&quot;^toto<span style="color: #000099; font-weight: bold;">\.</span>[0-9]{4}<span style="color: #000099; font-weight: bold;">\.</span>exr$&quot;</span><span style="color: black;">&#41;</span>
myMoverThread.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># start rendering, do rendering, end rendering.</span>
myMoverThread.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>


<p>Et voila!</p>


<h3>Conclusion</h3>


<p>J’espère que ce modeste prototype vous inspirera si vous rencontrez des lenteurs sur votre réseau. <img src="/blog/themes/blueSilenceCustom/smilies/mechantCrash.gif" alt=":mechantCrash:" class="smiley" /></p>


<p>Je vous conseille de faire un peu de profilage réseau sur vos principales applications, surtout si elles sont utilisées par beaucoup de monde. Leurs comportements est toujours intéressant (et parfois surprenant).</p>


<p>Passez une bonne journée!</p>


<p>Dorian</p>

<center><img src="/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:9ae2161d6ae68c514e18540d668a0aed
title: Tales of the Night, summary of a technical supervision
uri: Tales-of-the-Night-summary-of-a-technical-supervision
url:
http://www.fevrierdorian.com/blog/post/2011/07/21/Tales-of-the-Night-summary-of-a-technical-supervision

content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/lcdln_resume_superviseur_tn.png" alt="lcdln_resume_superviseur_tn.png" style="float:left; margin: 0 1em 1em 0;" title="lcdln_resume_superviseur_tn.png, juil. 2011"  height="150" width="150" />This is an english traduction of <a href="http://www.fevrierdorian.com/blog/post/2011/07/20/Les-Contes-de-la-Nuit-resume-d-une-supervision-technique">a post</a> I've made some time ago.</p>


<p>As you maybe know, the feature film <a href="http://www.imdb.com/title/tt1828229/" hreflang="en">Tales of the Night</a> (<em>Les Contes de la Nuit</em> in french) from <a href="http://www.imdb.com/name/nm0643664/" hreflang="en">Michel Ocelot</a> (<a href="http://www.imdb.com/title/tt0181627/" hreflang="en">Kirikou</a>, <a href="http://www.imdb.com/title/tt0439123/" hreflang="en">Azur et Asmar</a> and others) has been released in August.</p>


<p>I was fortunate to supervise the technical aspects of production. Beyond that I think this film is a real artistic success, it was definitely one of my most beautiful experience. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>In this post I purpose to go around the means in place to achieve that beautiful, what do I say? Wonderfull project!</p>


<p>(And do little advertising too <img src="/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> )</p>    <h3>Note</h3>

<blockquote><p>Although the content of this blog is licensed under a Creative Common, all images on this post are the property of their respective authors. Violators may be subject to prosecution and could be kidnapped in their sleep, stoned in the public place and deprived of candies. <img src="/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p></blockquote>


<h3>How I arrived on the project</h3>

<p>First, replacing the context seems to me interesting.</p>


<p>All start in the end of 2009, I'm working in <a href="http://www.def2shoot.com/" hreflang="en">Def2Shoot</a> the animated feature <a href="http://www.imdb.com/title/tt1039651/" hreflang="en">Yona Yona</a> (old project name). Following several french-Japanese production meetings, the choice to do animation of the main characters in Maya and sets in XSI is made. I find myself being the only TD in Maya (D2S is on XSI).</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/yona.jpg" title="yona.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.yona_m.jpg" alt="yona.jpg" style="display:block; margin:0 auto;" title="yona.jpg, juil. 2011"  height="560" width="411" /></a></p>


<p>Franck Malmin (<a href="http://www.excessif.com/cinema/actu-cinema/dossiers/la-naissance-de-yona-par-franck-malmin-producteur-executif-5668560-760.html">read his post-mortem</a>, really honnest, about the film, in fr), D2S CEO , purpose to the Yona Yona Surfacing TD's to help "a production" to start. This one begins to spend few afternoons in <a href="http://www.nord-ouest.fr/" hreflang="fr">Nord Ouest Film</a>, where a part of "Michel's team" is already in place.</p>


<p>At that point I knew no more. But difficulties that would encounter  Yona Yona began to be felt and production ask for the full-time return of his surfacing TD on the project.</p>


<p>In Def2Shoot, the Maya part is less of a problem (thanks to the arrival of a second TD) and Frank asked me to continue the work begun at Nord Ouest.</p>


<p>It was at this time I meet peoples I knew as the "Michael's team", all great persons. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>At first, my job was not to last long and was very basic. I had to understand the project needs and refer them to quick solutions (help to convert mental ray's .map because some matte painting was monstrously large, define a folder hierarchy and explain the "why" and the "how" of each file, etc. ...).</p>


<p>Despite the rather limited technical needs that require this project (Tales of the Night, it's not Transformers with raytracing everywhere), the team, actually rather small and composed of <del>few</del> no technicians, could, in long-term, end up spending more time dealing with technical problems rather than really work peacefully. <img src="/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>There was still, at that time, 10 episodes of 13 minutes each release in full HD.</p>


<p>This concern was shared with the rest of the team and after few conversations between Frank and production, it was decided that I will continue the project until the end (the project lasted one year and a half and it should be noticed that deadlines were met).</p>


<p>I was now officially part of the team!</p>
<center><img src="/blog/themes/blueSilenceCustom/smilies/youplaBoum.gif" alt=":youplaBoum:" class="smiley" /></center>



<h3>Drastic measures</h3>


<p>This decision will quite change my involvement on the project and I could see "farther", do things more advanced, manage more complex cases etc...</p>


<p>Michel Ocelot's Director sssistant came from 2D and was used to do a <del>heavy</del> amazing preprod work. Thus, storyboard and directing was already made and technical stripping was already in Excel files of the director of production (sorry, I don't really know english terms for this) even before an episode would only go in Layout.</p>


<p>This kind of thing quite assured me because have to think about changing everything at the last moment (<del>very</del> too present attitude in advertisement and the cinema aka "à l'américaine") would not led me to take some risks improving the production and it conditions. Naturally when you have some assurance that what you want to do is what we gonna do, you provide less time for "bad crafting".</p>


<p>That's when I could begin defining the outline of the workflow.</p>


<h3>Use scripts</h3>


<p>Let's don't turn around the bush: Scripting was everywhere no one dared venture. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>The importance of a technically coherent folder hierarchy was thus essential in order to automate tasks, while keeping in mind that it would be handled by "human" and, therefore, should also remain comprehensible.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/noShowPlans_001.png" alt="noShowPlans_001.png" style="display:block; margin:0 auto;" title="noShowPlans_001.png, juil. 2011"  height="246" width="338" /></p>


<p>The preferred language was MEL ​​in all Maya aspects (I was not yet comfortable with "Python in Maya") and Python for everything related to file manipulation (<em>os</em> and <em>re</em> are your friends).</p>


<p>Scripting usage was mainly made ​​for "crossing points" of information/files. I will often refer about it during the rest of this post because I almost passed this production my fingers on the keyboard. <img src="/blog/themes/blueSilenceCustom/smilies/pafOrdi.gif" alt=":pafOrdi:" class="smiley" /></p>



<h3>Pipeline summary</h3>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/Schema_pipeline.png" title="Schema_pipeline.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.Schema_pipeline_m.jpg" alt="Schema_pipeline.png" style="display:block; margin:0 auto;" title="Schema_pipeline.png, juil. 2011"  height="215" width="560" /></a></p>
<center><i>A plan that basically sums up the different steps of the pipeline</i></center>



<h4>Decorators</h4>


<p>"Decorators" (mappers) made their sets in Photoshop (in very huge and very heavy files ^^ ), they exported their work in different layers in tiff in a dedicated folder following ad naming convention specified in advance.</p>


<p>At first, they converted their .tiff in .map (and .dds) themselves but this highly repeteative task took time. So I quickly made script that was going through all textures of the current project and checked that each .map (or .dds) was older than her .tiff. Otherwise, it made a conversion. <img src="/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>



<h4>Characters</h4>


<p>I wasn't directly involved in the characters creation.</p>


<p>A 2D artist did the Photoshop version of the characters, burst them on a plan, a character TD, temporarily joint bye an animateur had set up an automated rig system to generate animable characters.</p>


<p>Character maps was converted the same way than decors.</p>


<p>My part, in the pipeline started at Layout stage with a tool to list characters and import them in the Maya scenes depending on the episode we was working on.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/layoutGen_001.png" alt="layoutGen_001.png" style="display:block; margin:0 auto;" title="layoutGen_001.png, juil. 2011"  height="341" width="412" /></p>


<p>So it was a big communication work to know who list and in which case do not list a particular character.</p>



<h5>Notice about .dds format</h5>


<p>Michel Ocelot validate animation on playblasts. So it need that playblast look "much as possible" near the final render.</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/playblast001.png" title="playblast001.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.playblast001_m.jpg" alt="playblast001.png" style="display:block; margin:0 auto;" title="playblast001.png, juil. 2011"  height="315" width="560" /></a></p>
<center><i>This is a playblast. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></i></center>



<p>For this, textures used in the scene had to be thoses used in render, dealing with a resizing.</p>


<p>So I've coded a CgFX shader which I gave the .dds texture versions to reduce their load in GPU memory.</p>


<p>This technique worked very well on sets but a bug I was unable to resolve made some textures disappear during controller movements of the characters.</p>


<p>I had to hack a kind of surface shader for the viewport but we loose the advangate of .dds textures because it seems that Maya uncompress and place the entire texture in GPU memory. <img src="/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /></p>


<p>It's a shame because it was character textures size that take more memory actually. So I had to make some "low" version of .dds texture (which already was in low def) and a tool to switch between versions (some shot had a lot of characters)...</p>


<h4>Layout</h4>


<p>So I've made the character importer but also a "set generator". Each shot in the film is actually a layering of maps:</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/orgaDesPlans001.png" title="orgaDesPlans001.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.orgaDesPlans001_m.jpg" alt="orgaDesPlans001.png" style="display:block; margin:0 auto;" title="orgaDesPlans001.png, juil. 2011"  height="339" width="560" /></a></p>


<p>As file naming convention was clear, it was very simple, using a script, to know where were the different layers of the current shot.</p>


<p>It was enough then to specify the episode number and the shot number we want to generate, and click ok.</p>


<p>A set rig was imported and adapted to the shot. Layers of set maps was load on their own plane and the camera's image plane displayed the animatic exported from the montage.</p>


<p>All that remained was "only to" put the characters.</p>


<p>I've also write a "transfer to shot" script to make layouters don't have to reposition every character whereas their was in the same position two shot later...</p>


<h4>Animation</h4>


<p>There was nothing "pipelined" concerning the layout's scene publication. Animators just copy the layout scene and start to animate they shot from this.</p>


<p>I've coded a character panel which was mainly used for hands. Hands simply textures on faces displayed/hidden during the animation.</p>


<p>Hand textures and numeric attributes for "display/hide" followed naming convention. So, each time a new hand was created by mappers, I just had to add a line in my panel's code to make everything appear in the panel.</p>


<p>However, responding to the render automation constraint required that scenes was published in specific folders where the script could find them.</p>


<p>So I've made a publication tool which save the current Maya scene and a little empty file (who played the role of "marker" to specify this scene had just been republished).</p>


<h4>Rendering</h4>


<p>There was no human need for this part. All had been scripted by me.</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/script001.png" title="script001.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.script001_m.jpg" alt="script001.png" style="display:block; margin:0 auto;" title="script001.png, juil. 2011"  height="509" width="560" /></a></p>
<center><i>jEdit was my friend! <img src="/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></i></center>



<p>I had to launch a script getting the whole scene from animation who had a "marker", open them and apply another script which do many things (some examples):</p>
<ul>
<li>Change texture path (replacing ".dds" by ".map" for examples).</li>
<li>Change texture options (to use <a href="http://download.autodesk.com/us/maya/2011help/mr/manual/node24.html" hreflang="en">elliptical filtering</a>).</li>
<li>Set optimal render parameters.</li>
<li>Go lookup, in a text file, if the actual shot had motion blur and activate it.</li>
<li>Apply some modifications (animation offset of hands of 0.5 frame if render with motion blur to avoid "poping effect" during image rotation, hide some visible controlers, etc...).</li>
<li>Do some hack depending of the episode/shot (apply a different blur to the "Garçon Tamtam" hands for example).</li>
<li>Generate job file containing command lines to launch (we used <a href="http://www.uberware.net/smedge/" hreflang="en">Smedge</a>) and a .bat for special case we need to render locally.</li>
<li>Remove the "marker" file.</li>
<li>Save the "ready to render" scene in the good folder.</li>
</ul>

<p><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/batchSmedge001.png" alt="batchSmedge001.png" style="display:block; margin:0 auto;" title="batchSmedge001.png, juil. 2011"  height="224" width="238" /></p>
<center><i>Job file generated by the script</i></center>



<p>When lunch time came, artists launched a Smedge client on they worksation to let renders be computed.</p>


<p>Mental ray was the main render engine and it did it well (it was my favorite render engine...). Once the .map created and the elliptical filter set, everthing was fine!</p>


<h4>Compositing</h4>


<p>Compositing était fait sous After Effect et se divisait en deux parties.
Compositing was made with After Effect and was divided in two parts.</p>
<ul>
<li>A first one containing every "a little special things" (smoke effects, morphings, some particular animations, etc...) was done by a 2D animator.</li>
<li>A second one representing the most of the shots (80%) was mainly quick improvements, global effects (depth of field), etc...</li>
</ul>

<p>I've made a After Effect script (my first one) who created a compo for the shot, import every layers, stacked them in the good order and created an export set.</p>


<p>It was also using this script we could quickly had "raw" renders: We launched this script for a list of shot to render, click the "Render" button and the computing of everything just start. It only remained to check the editing project (Final Cut) which was automatically updated.</p>


<p>A second script (used by the first one actually) generate export sets from selected compos in After Effect. This simplify compositor life which never loose time to correctly export they work.</p>


<h4>All the rest</h4>


<p>Of course, there was many little task to do during the project:</p>
<ul>
<li>Episode backup.</li>
<li>Disque space management on servers.</li>
<li>Technical storyboard reading.</li>
<li>etc...</li>
</ul>

<h3>Passage du stade de série au stade de long métrage en relief
From a serie to a relief full feature film</h3>


<p>Yeap! Because this is what make this project interesting. The original idea was to do a full HD serie for a french TV channel (Canal+) and it terminate with a full feature film in relief. This is not something you work on everyday. <img src="/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>I remember that it's following a projection for Canal+ that the idea of a full feature film has begun, without be really official (there was no talk about relief at this time). In practice, this change really few things for us.</p>


<p>But when we started to talk about relief, things have changed a little. <a href="http://www.macguff.fr/fr#/jobs/456-les-contes-de-la-nuit" hreflang="fr">Mac Guff</a> was on it. We gave them some shots sufficiently representative of the movie and they've done "real" (<em>not-like-clash-of-the-titans</em>) relief.</p>


<p>I insist on the word "real" relief because Mac Guff had all layers (and our After Effect files) and was able to work the relief without having to artificially recreate the depth.</p>


<p>During the first projection we were 5-6 et I must say I was really impressed by the result. The depth and the black gave a real theatrical effect. The relief team had done an excellent job and I think everyone was won over. (Avatar could go get dressed, he'd just take a low kick reverse rotation there! <img src="/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> )</p>


<p>Once the relief has been officially validated, the number of layer had exploded. It happened that After Effect projects beating down our little network. Finally, compute images locally was a simple and cheap solution that solves in part the problem.</p>


<p>The production is very well done, without pain and it's rare enough to be notified.</p>


<h3>What I would have liked to do better</h3>


<p>Of course, with retrospective, I think that some points would have deserved a little more attention.</p>

<ul>
<li>I wish I solve the texture problems (cgfx + .dds) that "pop" in the viewport when animators were moving their controllers. The solution found was not optimal and would increase the Maya load when there was a lot of characters. <em>seg faults</em> were too recurrent...</li>
<li>I've choose to use .png at every step of the project (excepted Photoshop because .tiff file format was the only one that keep alphas during .map conversions) because this format was very "simple" (RGBA and that's all!) and I wanted to avoid the .tiff which was much more "opaque" (many kind of possible compression, number of channel, can't be opened everywhere, etc...). This is something I see as a "rookie" mistake now because the .png file format is extremely slow to open. The. tiff, if it is well managed in all steps of the pipeline, offers a much better speed.</li>
<li>Probably other things...</li>
</ul>

<h3>Conclusion</h3>

<p>As you maybe understood, this was a great both professional and personal experience. Work with Michel Ocelot is very pleasant.</p>


<p>It was also a first technical supervision for me on a feature film.</p>


<p>The movie will be <a href="http://www.allocine.fr/film/fichefilm-183772/palmares/" hreflang="fr">8 times nominated</a> to the International Festival of Berlin which is still a great achievement when I remember the actually low number of peoples who worked on this project (compared to other productions of film animation).</p>


<p>Press reviews are very good and I hope this post, a little technique, will make you want to see this film made ​​with love. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>

<div class="external-media" style="margin: 1em auto; text-align: center;">
<iframe width="640" height="390" src="http://www.youtube.com/embed/ZoZGOtCzGLc" frameborder="0" allowfullscreen></iframe>
</div>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/lescontes.jpg" title="lescontes.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2011_04_06_lcdln_resume_superviseur/.lescontes_m.jpg" alt="lescontes.jpg" style="display:block; margin:0 auto;" title="lescontes.jpg, juil. 2011"  height="560" width="411" /></a></p>


<p>My favorite tales? <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>
<ul>
<li>The Werewolf: Because the work done on the leaves makes great stereo.</li>
<li>The Chosen One of the Golden City: Because in the movie theater, with the music, your adult heart will necessary let fall some tears of happiness.</li>
</ul>

<p>See you!</p>


<p>Dorian</p>


<h3>Liens</h3>
<ul>
<li><a href="http://www.imdb.com/title/tt1828229/fullcredits" hreflang="en">IMDb Les Contes de la nuit</a></li>
<li><a href="http://www.imdb.com/title/tt1723666/fullcredits" hreflang="en">IMDb Dragons et Princesses</a></li>
<li><a href="http://en.wikipedia.org/wiki/Dragons_et_princesses" hreflang="en">Wikipedia Dragons et Princesses</a></li>
</ul>


feed_id: urn:md5:f4f530250f4937eec114f9e8190639e1
title: Powerslide sur GOG en full HD avec AA et tout et tout!
uri: Powerslide-sur-GOG-en-full-HD-avec-AA-et-tout-et-tout
url:
http://www.fevrierdorian.com/blog/post/2013/01/16/Powerslide-sur-GOG-en-full-HD-avec-AA-et-tout-et-tout

content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_tn.png" alt="Powerslide_GOG_tn.png" style="float:left; margin: 0 1em 1em 0;" title="Powerslide_GOG_tn.png, janv. 2013"  height="150" width="150" />J'ai acheté <a href="http://www.gog.com/gamecard/powerslide" hreflang="en">Powerslide sur GOG</a> il y a quelques temps. <img src="/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p>


<p>Pour info, <a href="http://fr.wikipedia.org/wiki/GOG.com" hreflang="fr">GOG</a> était l’abréviation de <em>Good Old Games</em> et proposait (et propose toujours) des jeux sans DRM, à des prix attractifs et surtout une compatibilité avec les nouveaux systèmes.</p>


<p>C'est précisément ça qui m'a amené à dépenser la moitié moins du prix d'une peinte parisienne (c'est le premier argument qui m'est passé par la tête au moment de payer, allez savoir pourquoi...) pour ce jeu dont j'ai dû passer plus de temps sur la démo que sur la plupart des autres jeux que j'avais pu acheter à l’époque. <img src="/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>    <h3>Envie de rejouer aux jeux de ton enfance? Ça y est, t'est vieux!</h3>


<p>Tout commence par un screenshot du jeu sur lequel je tombe totalement par hasard sur un forum (sur un thread inspiré du genre "Un screenshot, devinez le jeu"). Je me dis "tiens il était cool ce jeu, ça serait bien d'y rejouer, juste pour voir" <img src="/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> .</p>


<p>Après pas mal de recherches, je trouve quelques isos du CD original et lance une installation.</p>


<p>Et paf! C'est la que tu te prend dix ans d’évolution des OS dans la tronche... Faire fonctionner correctement ce jeu en version original relève de l'exploit (au sens français comme au <a href="http://fr.wikipedia.org/wiki/Exploit_%28informatique%29" hreflang="fr">sens informatique</a>). Certains semblent y être arrivé. Ne m'étant jamais vraiment tourné vers du "revival" de jeux fonctionnant via 3dfx j'ai du me contenter d’échecs à répétition... <img src="/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /></p>


<p>Après plusieurs soirées (parce que oui, quand quelque chose comme ça me résiste, je suis du genre assez bête pour insister) à tenter par tout les moyens de faire fonctionner ce jeu, j'ai du me résilier à abandonner. <em>Powerslide</em> allait rejoindre la longue liste des jeux qu'il n'est plus possible de faire fonctionner sans prise de tête (<a href="http://www.google.fr/search?q=shadow+of+the+empire+win+7" hreflang="fr">Shadow Of The Empire</a>... Snif...).</p>


<p>Puis je réalise que GOG (que je connaissais déjà) propose une version. Il faut savoir que GOG fait un gros travaille pour rendre les anciens jeu jouable sur les nouveaux systèmes sans que l'utilisateur ait justement à bricoler. T'installe, tu lance, tu enjoy! <img src="/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>


<p>4.74 euros plus tard (tant pis, je boirai un verre d'eau à ma prochaine sortie... <img src="/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> ) + le temps régler le wrapper <a href="http://www.zeus-software.com/downloads/nglide" hreflang="en">nGlide</a> intégré, je branche mon pad, lance le même circuit + la même voiture que la démo et m'affale dans mon siège, détendu, pour profiter des quelques minutes de nostalgie qui s'offre à moi.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_nGlide_001.png" alt="Powerslide_GOG_nGlide_001.png" style="display:block; margin:0 auto;" title="Powerslide_GOG_nGlide_001.png, janv. 2013"  height="215" width="242" /></p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_nGlide_002.png" alt="Powerslide_GOG_nGlide_002.png" style="display:block; margin:0 auto;" title="Powerslide_GOG_nGlide_002.png, janv. 2013"  height="302" width="396" />
Ces vieux jeux étant pensés pour être projetés sur tube cathodique, n'hésitez pas à monter le Gamma de à 1.2. Pensez aussi à conserver les proportions en 4:3, sinon, ça risque de vous donner le mal de mer durant les virages.</p>


<p>Pour le reste: A fond!</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_amd_override_001.png" title="Powerslide_GOG_amd_override_001.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_amd_override_001_m.jpg" alt="Powerslide_GOG_amd_override_001.png" style="display:block; margin:0 auto;" title="Powerslide_GOG_amd_override_001.png, janv. 2013"  height="299" width="560" /></a></p>
<center><i>J'ai également overridé tous les paramètres à fond au niveau du driver, ça coute pas cher.</i></center>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_menu.png" title="Powerslide_GOG_menu.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_menu_m.jpg" alt="Powerslide_GOG_menu.png" style="display:block; margin:0 auto;" title="Powerslide_GOG_menu.png, janv. 2013"  height="420" width="560" /></a></p>
<center><i>Le circuit. Souvenirs souvenirs... <img src="/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></i></center>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_logo_3dfx_en_aa.png" title="Powerslide_GOG_logo_3dfx_en_aa.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_logo_3dfx_en_aa_m.jpg" alt="Powerslide_GOG_logo_3dfx_en_aa.png" style="display:block; margin:0 auto;" title="Powerslide_GOG_logo_3dfx_en_aa.png, janv. 2013"  height="315" width="560" /></a></p>
<center><i>Avouez que vous l'aviez oublié celui là. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></i></center>



<p>Mais aussitôt l'accelerateur poussé, je déchante.</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_001.jpg" title="Powerslide_GOG_001.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_001_m.jpg" alt="Powerslide_GOG_001.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_001.jpg, janv. 2013"  height="420" width="560" /></a></p>


<p>Premier virage: Bim! Raté. Second virage: Bim! Reraté... (Je me redresse sur mon siège: putain... o_O).</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_002.jpg" title="Powerslide_GOG_002.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_002_m.jpg" alt="Powerslide_GOG_002.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_002.jpg, janv. 2013"  height="420" width="560" /></a></p>


<p>Après 30 minutes de jeu, le constat est sans appel: Les jeux étaient bien plus durs AAAAAvant, alors que j'étais beaucoup plus jeune et que je n'avais pas noté de difficulté particulière. Au contraire, j'avais gardé le sentiment d'un jeu d'arcade... Et le pire c'est que c'est cette combinaison (voiture/circuit) qui était utilisé pour te "vendre" le jeu. <img src="/blog/themes/blueSilenceCustom/smilies/seSentCon.gif" alt=":seSentCon:" class="smiley" /></p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_003.jpg" title="Powerslide_GOG_003.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_003_m.jpg" alt="Powerslide_GOG_003.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_003.jpg, janv. 2013"  height="420" width="560" /></a></p>


<p>Sur le premier tour d'un nouveau circuit, il y a de forte chance que vous passiez plus de temps sur le dos que sur les roues. Au début ça fait bizarre mais après on se surprend à se lancer un défi à chaque découverte d'un circuit: "Celui là, je roule doucement et je me ramasse pas!", et puis non... <img src="/blog/themes/blueSilenceCustom/smilies/onSeFendLaPoire.gif" alt=":onSeFendLaPoire:" class="smiley" /></p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_004.jpg" title="Powerslide_GOG_004.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_004_m.jpg" alt="Powerslide_GOG_004.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_004.jpg, janv. 2013"  height="420" width="560" /></a></p>


<p>Et c'est au bout d'une première heure qu'on commence à comprendre que négocier un virage est en fait une affaire de maitre et c'est ce que ce jeu exige: De la maitrise.</p>


<p>Puis tout devient naturel, on se met à sourire lorsqu'on double un adversaire sans le toucher sur un virage pris a la perfection.</p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_005.jpg" title="Powerslide_GOG_005.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_005_m.jpg" alt="Powerslide_GOG_005.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_005.jpg, janv. 2013"  height="420" width="560" /></a></p>
<center><i>Là, ça ne se voit pas mais je suis en train de partir completement à droite... <img src="/blog/themes/blueSilenceCustom/smilies/cyberjo.gif" alt=":nevroz:" class="smiley" /> </i></center>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/Powerslide_GOG_006.jpg" title="Powerslide_GOG_006.jpg"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_01_11_Powerslide_Sur_GOG/.Powerslide_GOG_006_m.jpg" alt="Powerslide_GOG_006.jpg" style="display:block; margin:0 auto;" title="Powerslide_GOG_006.jpg, janv. 2013"  height="420" width="560" /></a></p>


<p>Notez qu'un mode multijoueur est dispo en IPX, Modem (des trucs de vieux) mais surtout: TCP/IP. Vous devriez donc pouvoir jouer contre un/des amis (à qui vous aurez suffisamment bourré le mou je suppose) sur internet en <a href="http://forum.hardware.fr/hfr/WindowsSoftware/redirection-ip-serveur-sujet_266697_1.htm" hreflang="fr">bricolant un peu</a>. <img src="/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></p>


<h3>Lapin d'musiques?</h3>

<p>Durant mes premières parties, j'ai pu constater que la musique était absente (les mauvaises langues diront qu'aux vues de la qualité musicale du titre ce n'est pas plus mal <img src="/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /> ), malgré mes allez-retour dans les options. En fouillant le dossier du jeu, je vois des mp3 contenants, justement, les musiques. J’envoie un mail au support pour leur faire remarquer mon soucis sans trop y croire (après tout, je m'en fout, quand je joue à des jeux comme ça c'est du Nirvanna ou du Vitalic qui tourne derrière).</p>


<p>Et c'est à ma grande surprise que quelques heures plus tard, le support m'indique avoir corrigé le soucis et m'invite a retélécharger le jeu...</p>


<p>Et ça fonctionne! <img src="/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>


<p>C'est donc avec plaisir que je me suis plongé quelques soirées dans ce jeu bien fun qui s'apparente plus a un jeu de dérapage qu'un "jeu de voiture" et que j'ai pu apprécier le travail et la réactivité de GOG.</p>


<h3>GOG c'est bien mais...</h3>

<p>...la liste des jeux en français est finalement assez maigre. C'est bien dommage d'ailleurs...</p>


<p>Je vous propose donc un site alternatif français qui c'est lancé dans le même business: <a href="http://www.dotemu.com/fr" hreflang="fr">DotEmu</a>.</p>


<p>Bon, le catalogue est moins fournit (je trouve qu'il complète bien celui de GOG), mais la plupart des jeux proposés le sont en français (Les Fallout, Gobliiins, Les Commandos, etc...).</p>


<p>En espérant que ce billet coup de cœur rappel des souvenirs à certains...</p>


<p>A bientôt!</p>
<center><i><img src="/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></i></center>



<h3>Liens</h3>
<ul>
<li><a href="http://www.grospixels.com/site/powerslide.php" hreflang="fr">Test de Powerslide sur Grospixels</a></li>
<li><a href="http://www.emunova.net/veda/test/1050.htm" hreflang="fr">Test de Powerslide sur Emunova</a></li>
</ul>


feed_id: urn:md5:9bf448d41828ce5285db9e2a01c7ec40
title: Deex VRay Arsenal, un petit tool qui fait gagner beaucoup de temps
uri: Deex-VRay-Arsenal-un-petit-tool-qui-fait-gagner-beaucoup-de-temps
url:
http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-un-petit-tool-qui-fait-gagner-beaucoup-de-temps

content:
<p><img src="media/8866d0ad.VRay_Arsenal_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_tn.png" alt="VRay_Arsenal_tn.png" style="float:left; margin: 0 1em 1em 0;" title="VRay_Arsenal_tn.png, janv. 2013"  height="150" width="150" />Ça fait un moment que j’entends Damien (alias <a href="http://deex.info/" hreflang="en">Deex</a>) parler de son tool. J'ai même eu l'occasion d'être sur la même prod que lui quand il réfléchissait aux grandes lignes. Quand il m'a dit que son outil était enfin fini, je n'ai pas pu m’empêcher de lui demander une licence pour tester ça. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>L'idée de ce billet est de présenter les principales <em>features</em> d'<a href="http://arsenal.deex.info/" hreflang="en">Arsenal</a>. Vous allez voir que malgré une approche qui peut sembler un peu trop user friendly, cette outil est un vrai outil de production qui facilite pas mal le boulot.</p>


<p>C'est 'tipar mon canard! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>    <blockquote><p>Note: Avant de commencer je vous invite à cocher la case <em>Use V-Ray VFB</em> dans l'onglet <em>VRay Common</em> des <em>Render Settings</em>:</p></blockquote>


<p><img src="media/dde82e54.VRay_Arsenal_012_useVRay_frameBuffer.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_012_useVRay_frameBuffer.png" alt="VRay_Arsenal_012_useVRay_frameBuffer.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_012_useVRay_frameBuffer.png, janv. 2013"  height="369" width="428" /></p>


<p>Ceci vous donnera accès à une sorte de <em>Render View</em> spécial VRay qui permet (en plus de pas mal de choses) de visualiser directement les passes (en haut à gauche).</p>


<p><img src="media/5a69fd22.VRay_Arsenal_011_frameBuffer.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_011_frameBuffer.png" alt="VRay_Arsenal_011_frameBuffer.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_011_frameBuffer.png, janv. 2013"  height="137" width="331" /></p>


<p><img src="media/b5bed629.VRay_Arsenal_sampleImage.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_sampleImage.png" alt="VRay_Arsenal_sampleImage.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_sampleImage.png, janv. 2013"  height="319" width="301" /></p>
<center><i>Mon image de test: Une HDR de <a href="http://www.hdrlabs.com/sibl/archive.html">sIBL</a>, et beaucoup de talent! <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></i></center>



<h3>L'installation</h3>


<p>J'ai trouvé <a href="http://arsenal.deex.info/wordpress/documentation/installation/" hreflang="en">l'installation</a> un peu rebutante. Ce n'est pas dans ce qu'on à l'habitude de voir avec la plupart des scripts.</p>


<p>En premier lieu, il faut installer PyQt ce qui, en temps normal, n'est pas une mince affaire (en particulier sous Windows). Heureusement, un installeur "pas prise de tête" est proposé sur le site. C'est bien senti.</p>


<p>L'installation du tool à proprement parler est, quant à elle, pensé pour simplifier l’intégration en prod (via des variables d'environnements) mais peut se révéler assez rebutante pour les gens n'ayant pas forcément l'habitude de jouer avec leur <em>Maya.env</em>. D'autant que je suis sur qu'il aurait été possible de faire une installation "à l'ancienne" (les scripts dans le dossier <em>script</em>, les shelves dans le dossier <em>shelves</em>, etc...), c'est juste que ce n'est pas forcément propre et qu'à chaque MAJ ça aurait été un peu plus compliqué alors qu'avec le système actuel, il suffit de remplacer un seul dossier. <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<h3>La fenêtre de base</h3>

<p>Quand on ouvre, on a ça:</p>


<p><img src="media/05cc01c2.VRay_Arsenal_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_001.png" alt="VRay_Arsenal_001.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_001.png, janv. 2013"  height="933" width="536" /></p>


<p>Nous passerons les onglets en revu plus bas.</p>


<p>Il y a un bouton <em>épingler</em>. Une fois coche, Arsenal restera au devant de vos fenêtres. Sinon, il se comporte comme une fenêtre Maya.</p>


<p>Il y a aussi le bouton <em>close</em> en bas dont je ne vous ferais pas l'affront de vous expliquer l'utilité. <img src="media/e7107ccf.reflexionIntense.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflexionIntense.gif" alt=":reflexionIntense:" class="smiley" /></p>


<p>Il y a trois onglets que nous allons voir dans l'ordre:</p>
<ul>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-un-petit-tool-qui-fait-gagner-beaucoup-de-temps#pass">Pass</a>, qui regroupe les <em>Render Layer</em> de Maya et le système de passe de VRay. Leur utilisation combinées étant fréquente.</li>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-un-petit-tool-qui-fait-gagner-beaucoup-de-temps#quality">Quality</a>, qui est une feature fort pratique à l'utilisation: Un slider, de 0 a 99 pour augmenter ou diminuer la qualité du rendu via une augmentation progressive de vos paramètres de rendu.</li>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-un-petit-tool-qui-fait-gagner-beaucoup-de-temps#toolbox">ToolBox</a>, qui regroupe pleins de petits outils qui font gagner pas mal de temps.</li>
</ul>

<h3>L'onglet <em>Pass</em> <a name="pass"></a></h3>


<p>Sur la partie haute vous avez, tout bêtement, les <em>Render Layer</em> de Maya (injustement nommé "Pass" dans les trois boutons de gauche). Cliquez sur un de ces <em>Render Layer</em> vous le sélectionne de la même façon que Maya. C'est juste pour gagner du temps. Pour des rendus ne nécessitant pas de passes complexes vous ne devriez pas en avoir besoins.</p>


<p>Notez que vous pouvez faire un <em>Set global to on</em> sur vos <em>RenderLayers</em> directement depuis cette fenêtre (voir <a href="http://download.autodesk.com/global/docs/maya2013/en_us/index.html?url=files/Rendering_nodes_Render_Layer_render_attributes.htm,topicNumber=d30e656262" hreflang="en">doc Maya</a>).</p>


<p>Rentrons maintenant dans la partie la plus intéressante. <img src="media/94b95129.popcorn.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/popcorn.gif" alt=":popcorn:" class="smiley" /></p>


<h4>Properties control</h4>


<p><img src="media/d4731f41.VRay_Arsenal_onglet_propertiesControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_onglet_propertiesControl.png" alt="VRay_Arsenal_onglet_propertiesControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_onglet_propertiesControl.png, janv. 2013"  height="607" width="473" /></p>


<p>Ce système est extrêmement rapide pour préparer vos passes.</p>


<p>C'est très (très) simple:</p>
<ul>
<li>Vous sélectionnez un objet/groupe, vous faites <strong>Add</strong> et hop!</li>
<li>Vous voulez supprimez un objet/groupe? <strong>Remove</strong>!</li>
<li>Vous voulez voir les objets ayant une propriété particulière? <strong>Select</strong>!</li>
</ul>

<p>C'est à la fois limpide mais aussi beaucoup plus rapide que la méthode "conventionnelle" visant à gérer ces propriétés de manière granuleuse sur les groupes/objets. Ici, le système est inversé: Vous gérez les objets en fonction de leurs propriété.</p>


<p>Je trouve ça beaucoup plus clair. <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>Voici une explication rapide des différentes <em>properties</em>. Pour plus de détails, se référer à la <a href="http://arsenal.deex.info/wordpress/documentation/" hreflang="en">documentation officielle</a>.</p>


<h5>Black hole</h5>

<p>Les objets ayant cette <em>property</em> ne seront pas affiché dans le rendu (ils seront noir) et leur alpha sera vide.</p>


<p><strong>Receive shadow</strong>: Les objet <strong>Black hole</strong> ayant cette <em>property</em> recevront les ombres et les répercuteront dans leurs alphas (pour un sol par exemple).</p>


<h5>GI</h5>
<ul>
<li><strong>Generate off</strong>: Les objets ayant cette <em>property</em> ne seront pas considéré lors de la génération de l'illumination globale (pour séparer la <strong>GI</strong> entre les personnages et le décors par exemple).</li>
<li><strong>Receive off</strong>: Les objets ayant cette <em>property</em> ne recevront aucune illumination indirects.</li>
</ul>

<h5>Visibility</h5>
<ul>
<li><strong>Primary off</strong>:  Les objets ayant cette <em>property</em> ne seront pas visibles sur les rayons primaires (ils seront donc visibles dans les reflections/refractions/GI).</li>
<li><strong>Reflection off</strong>:  Les objets ayant cette <em>property</em> ne seront pas visibles dans les rayons de reflections (peut être pratique pour empêcher un objet complexe de se refléter si il n'apporte pas grand chose au rendu final).</li>
<li><strong>Refraction off</strong>:  Les objets ayant cette <em>property</em> ne seront pas visibles dans les rayons de refractions.</li>
</ul>

<h5>Shadows</h5>

<p><strong>Cast off</strong>:  Les objets ayant cette <em>property</em> ne projetteront pas d'ombres.</p>


<h4>On fly control</h4>


<p><img src="media/f7b118b5.VRay_Arsenal_002_onFlyControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_002_onFlyControl.png" alt="VRay_Arsenal_002_onFlyControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_002_onFlyControl.png, janv. 2013"  height="447" width="475" /></p>


<p>Je ne suis pas adepte des terminologies utilisées dans cet onglet. Je vais donc essayer d’être clair. <img src="media/edc4ddb7.gne.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/gne.gif" alt=":gne:" class="smiley" /></p>


<h5>Light select</h5>

<p>Ici on cherchera à sortir des passes par light ou pour toutes les lights. Ces <em>pass</em> seront nommé sous la forme <em>nomDeMaLightShape_normal</em>,  <em>nomDeMaLightShape_diffuse</em>, etc...</p>
<ul>
<li><strong>Manual</strong>: Si vous souhaitez sortir les "contributions" uniquement pour certaines lights données, c'est ici que vous le ferez.
<ul>
<li><strong>Normal</strong>: Et c'est là ou ça prête pas mal à confusion: <em>Normal</em> ici ce n'est pas la normale au sens vecteur mais normal au sens "classique". C'est donc une passe contenant toute l'illumination direct d'une light. C'est tout. Notez que c'est la terminologie utilisé par VRay...</li>
<li><strong>Diffuse</strong>: <em>Pass</em> d'éclairage direct de la light ne contenant que les informations de diffusion.</li>
<li><strong>Raw</strong>: <em>Pass</em> contenant les informations "brut" de l'éclairage direct de la light</li>
<li><strong>Specular</strong>: <em>Pass</em> de spéculaire pour la light donnée.</li>
</ul></li>
<li><strong>Automatic</strong>: Disons que si vous avez comptez de toute façon sortir toute les passes pour toutes les lights de la scène, passez directement par là. Vous pouvez également combiner le mode <strong>Automatic</strong> pour un type de passe avec le mode <strong>Manual</strong> pour un autre type de passe.
<ul>
<li><strong>Specular</strong>: Sort toute les <em>pass</em> de spéculaire pour toute les lights de la scène.</li>
<li><strong>Raw</strong>: Idem que <strong>Specular</strong> mais pour le <strong>Raw</strong>.</li>
<li><strong>Diffuse</strong>: Idem mais pour la <strong>Diffuse</strong>.</li>
<li><strong>Normal</strong>: Idem mais pour la passe <strong>Normal</strong>.</li>
</ul></li>
</ul>
<h5>Arsenal settings</h5>

<p>Ici on a mes options préférées. Même si on ne peut pas deviner à quoi elles servent au premier abord. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>
<ul>
<li><strong>VrayMtl Lambert</strong>: Cocher cette case transformera, à la volé, au moment du rendu, tout les matériaux de votre scène en <em>VrayMtl Lambert</em>, ce qui est très pratique pour vérifier son éclairage globale. La ou cette option se distingue d'un <em>RenderLayer</em> avec un <em>material override</em>, c'est que les materiaux conserveront leur displacement/bump/normalmap si ils en ont.</li>
<li><strong>Material ID on fly</strong>: Cocher cette case génèrera des <em>Material ID</em> à la volé au moment du rendu en utilisant les noms des matériaux (sans les namespaces) comme "référence". Ainsi, vous obtiendrez toujours la même couleur de <em>Material ID</em> tant votre material porte le même nom. Bien entendu, il faut avoir créé un <em>Render Element</em> de type <em>Material ID</em>. Notez également que cette feature est compatible avec les VRayblendMaterial: Si vous avez blendé plusieurs materials (avec des masques) dans un VRayblendMaterial, chaque material aura son ID propre dans la pass.</li>
<li><strong>Proxy Objects ID on fly</strong>: Même principe que pour les <em>Material ID</em> mais cette fois dans le cas des proxy VRay.</li>
</ul>

<h4>Matte control</h4>


<p><img src="media/e2f5739c.VRay_Arsenal_003_matteControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_003_matteControl.png" alt="VRay_Arsenal_003_matteControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_003_matteControl.png, janv. 2013"  height="252" width="473" /></p>


<p>Celui là aussi je l'aime bien tellement il est simple! <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>Le principe est de générer des passes de "masque". Vous savez? Les masques RGB:</p>


<p><img src="media/d40bd42d.VRay_Arsenal_013_passMask.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_013_passMask.png" alt="VRay_Arsenal_013_passMask.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_013_passMask.png, janv. 2013"  height="369" width="324" /></p>


<p>En gros:</p>
<ul>
<li>Vous faites <strong>Create new</strong>.</li>
<li>Vous donnez un nom à votre passe de mask (<strong>Mask name</strong>). Si vous ne donnez pas de noms à votre passe de masque elle sera supprimée. <img src="media/57cd5fc6.alkap.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/alkap.gif" alt=":mitraille:" class="smiley" /></li>
<li>Vous sélectionnez un/des objets/groupes.</li>
<li>Vous faites <strong>add in red</strong> (ou green/blue).</li>
<li>Vous rendez et vous avez votre passe de mask.</li>
<li>Vous pouvez recommencer la manœuvre pour une autre passe.</li>
</ul>

<p>C'est tellement simple que je ne vois même pas quoi ajouter! <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>Ah si! Ce systeme outrepasse une limitation de VRay. Exemple:</p>
<ul>
<li>Vous avez un objet_A avec un ID 1.</li>
<li>Un objet_B avec un ID 2.</li>
<li>Ces deux objets sont dans un group avec ID 3.</li>
<li>Créez un <em>Render Element</em> <em>Multi Matte</em> et passez le <em>Red object ID</em> à 3.</li>
<li>Rendez et regardez votre passe de multimatte.</li>
</ul>
<p>Elle est noire. Pourquoi? Parce que VRay ayant remarqué que les objets dans le groupe ont un object ID, il ne les affiche pas dans la passe.</p>


<p>Avec le systeme de Arsenal, si vous demandez à ce que le groupe soit rouge, il sera rouge!</p>


<h4>FastControl</h4>


<p><img src="media/d2845f4a.VRay_Arsenal_004_fastControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_004_fastControl.png" alt="VRay_Arsenal_004_fastControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_004_fastControl.png, janv. 2013"  height="183" width="474" /></p>


<p>Cet onglet rassemble juste les principales options de VRay pour les activer/désactiver rapidement.</p>


<h3>L'onglet <em>Quality</em> <a name="quality"></a></h3>


<p><img src="media/ff7789fe.VRay_Arsenal_005_qualityTab.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_005_qualityTab.png" alt="VRay_Arsenal_005_qualityTab.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_005_qualityTab.png, janv. 2013"  height="773" width="492" /></p>
<center><i>Un gros slider qui change de couleur! :D</i></center>



<p>Ici on est clairement dans la partie qui plaira au personnes qui ne sont pas forcément des as du rendu. Et pourtant, vous allez voir qu'il peut très largement faire de l’œil à des personnes ayant l'habitude de modifier leurs paramètres à la main. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>La première chose à faire pour activer tout ça est de cliquer sur <strong>Save actual settings</strong> qui se chargera de mettre de coté vos paramètres actuels, puis sur <strong>Optimize</strong> pour mettre en place les différentes expressions. A partir de ce moment là, vous pouvez commencer à modifier le slider principale pour faire varier la qualité du rendu.</p>


<h4>Preset Type</h4>


<p>Ici, on parle plus de configuration du slider que de <em>Preset</em>. Il y a deux <em>Preset Type</em>:</p>
<ul>
<li><em>deeX_interior</em></li>
<li><em>deeX_exterior</em></li>
</ul>
<p>Ces deux choix représentent la majorité des cas de lighting.</p>


<p>Les presets en question sont de simple fichier texte que vous pouvez retrouver dans:</p>
<pre class="bash bash">C:\Users\Narann\Documents\maya\deeXVRayArsenal\<span style="color: #000000;">2013</span>\win64\scripts\presets</pre>

<p>Ces fichiers, à la syntaxe relativement simple, permettent de piloter les ranges (min et max) des attributs de VRay qui seront ensuite modifié par votre slider. Si je ne dis pas de bêtises, la relation entre le slider et les paramètres qu'il drive est <a href="http://fr.wikipedia.org/wiki/Logarithme" hreflang="fr">logarithmique</a> pour éviter que les paramètres n'explosent vos temps de rendus quand vous commencer à vous monter haut dans le slider. <img src="media/00461682.1420.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>


<p>Si la possibilité de créer ces propres presets n’intéressera surement pas les lighters <del>du dimanche</del> occasionnels, le fait de pouvoir mettre sois même ces paramètres <em>min</em> et <em>max</em> à piloter peut être très intéressant pour les lighters à poil dûr qui ont leurs petites habitudes. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></p>


<p>D’ailleurs, il aurait presque fallu que cette outil soit indépendant de VRay pour pouvoir, par exemple, piloter Mental Ray. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


<blockquote><p>Si vous souhaitez empêcher la modification d'un attribut par Arsenal il suffit de le locker.</p></blockquote>


<h4>Offset quality</h4>


<p>On a ici une très bonne initiative. L'idée étant d'appliquer un offset au slider pour certains paramètres.</p>


<p>Par exemple, supposons que mon slider soit à <em>50</em>. Je trouve que le sampling est un peu sensible et augmente les temps de rendu trop rapidement. Pourtant, je suis satisfait du reste.... Qu'à cela ne tienne, il me suffit de cocher la case <strong>Image sampler</strong> puis de taper <em>-10</em> pour que les paramètres du sampler s'applique comme si mon slider globale était à <em>40</em>! <img src="media/d52870c6.youplaBoum.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/youplaBoum.gif" alt=":youplaBoum:" class="smiley" /></p>


<h4>Optimize material(s)</h4>


<p>Encore une initiative intéressante: Vous déterminer deux valeurs extrêmes de subdivision (sampling), cliquez sur le bouton <strong>Optimize material(s)</strong> et Arsenal va déterminer la valeur à utiliser en fonction de la valeur de <strong>Glossiness</strong> du material.</p>


<p>Attention toutefois, le système est un peu trop "bête". Si une texture est connecté au paramètre de glossiness, la valeur subdiv est déterminé en fonction de la valeur de l'attribut, même si elle ne correspond à rien en temps que tel. Une option telle que <em>skip connected</em> pourrait être intéressante.</p>


<p>Notez la checkbox à droite <strong>LayerMode</strong>. Si vous la cocher avant de cliquer sur le bouton <strong>Optimize material(s)</strong> et que vous êtes dans un <em>RenderLayer</em> (autre que le <em>masterLayer</em>), les attributs seront modifié uniquement sur le <em>RenderLayer</em> en cours.</p>


<h4>Optimize light(s)</h4>


<p>Pas sur que ce bouton soit très utile. Pour l'instant il ne fait que passer le paramètre de Subdiv des VRayLights de la scène à 5...</p>


<h3>L'onglet <em>ToolBox</em> <a name="toolbox"></a></h3>


<p><img src="media/47fb251f.VRay_Arsenal_006_toolBoxTab.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_006_toolBoxTab.png" alt="VRay_Arsenal_006_toolBoxTab.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_006_toolBoxTab.png, janv. 2013"  height="707" width="494" /></p>


<p>Ici vous trouverez des petits outils très spécifiques.</p>


<h4>Proxy</h4>

<p>Les <a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm" hreflang="en">VRayProxy</a> sont une petite merveille. On les a utilisés sur <a href="http://www.allocine.fr/film/fichefilm_gen_cfilm=178179.html" hreflang="fr">Or Noir</a> pour faire des cycles d'animation de cheval changeant de vitesse.</p>


<h5>Multi proxy importer</h5>

<p>Ce bouton permet d'importer plusieurs VRayProxy car, aussi surprenant que cela puisse paraitre, il n'est pas possible de faire cela en standard...</p>


<h5>Shader auto connect</h5>

<p>Quand vous exportez un VRayProxy, des "slots d'assignations" y sont créés. Le principe est de pouvoir conserver, à l’intérieur du proxy, les assignations de vos shaders pour les réassigner.</p>


<p>Une fois le VRayProxy réimporté dans votre scène, vous pouvez lui appliquer un <a href="http://www.spot3d.com/vray/help/maya/150R1/vraymeshmtl_params.htm" hreflang="en">VRayMeshMaterial</a> (pour info, il est déjà créé au moment de l'import). Ce material affichera les différents slots d'assignations de votre proxy pour y connecter vos propres shaders.</p>


<p>Le bouton <strong>Shader auto connect</strong> permet de reconnecter automatiquement les shaders en fonction de leur noms, ce qui évite d'avoir à le faire sois même. Sur des proxy ayant des dizaines voir des centaines d'assignations, c'est plutôt pratique...</p>


<h5>Ignore namespace</h5>

<p>Cette case permet d'ignorer les namespaces des shaders de votre scène pour les réassigner au proxys. Dans le principe, cela permet d'avoir ces shaders en référence externe (avec un namespace) sans pour autant que ça ne pose problème de les reconnecter via leur noms.</p>


<h4>ID</h4>

<p>Une fois de plus, ici nous avons des outils pour assigner très rapidement des ID aux matériaux et aux objets.</p>


<p>L’intérêt est ensuite de sortir ces ID sous forme de passe à donner à vos amis du compositing.</p>


<h4>Material ID</h4>


<p><img src="media/ec88b911.VRay_Arsenal_008_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_008_materialID.png" alt="VRay_Arsenal_008_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_008_materialID.png, janv. 2013"  height="431" width="383" /></p>

<ul>
<li><strong>Add on</strong>: Permet d'appliquer les attributs de <em>Material ID</em> aux materials sélectionnés/tout les materials/tout les shading engine.</li>
<li><strong>Set on</strong>: Applique un ID unique aux attributs de <em>Material ID</em> des materials sélectionnés/tout les materials/tout les shading engine. Ce numéro est généré aléatoirement en se servant du nom du material. Cette méthode est à double tranchant: Si vous changez le nom d'un material puis que vous recliquez sur <em>Set on</em>, la couleur de son ID changera également. Notez que la checkbox <strong>Material ID on fly</strong> de l'onglet <em>Pass</em>/<em>On fly control</em> fait la même chose directement à la volée. :)</li>
<li><strong>Remove on</strong>: Supprime les attributs de <em>Material ID</em> des materials sélectionnés/tous les materials/tous les shading engine.</li>
</ul>

<p><img src="media/67fcbd1a.VRay_Arsenal_014_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_014_materialID.png" alt="VRay_Arsenal_014_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_014_materialID.png, janv. 2013"  height="115" width="528" /></p>


<p>Dernier point, pour que tout cela fonctionne, n'oubliez pas de créer une pass (un <em>Render Element</em>) de <em>Material ID</em>:</p>


<p><img src="media/a3a3b1a5.VRay_Arsenal_007_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_007_materialID.png" alt="VRay_Arsenal_007_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_007_materialID.png, janv. 2013"  height="568" width="437" /></p>


<h4>Object ID</h4>

<p>Même principe que pour les <em>Material ID</em> mais au niveau des objets.</p>


<p><img src="media/95efe5f1.VRay_Arsenal_015_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_015_objectID.png" alt="VRay_Arsenal_015_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_015_objectID.png, janv. 2013"  height="84" width="451" /></p>


<p><img src="media/47e12d57.VRay_Arsenal_010_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_010_objectID.png" alt="VRay_Arsenal_010_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_010_objectID.png, janv. 2013"  height="621" width="570" /></p>
<center><i>Notez la différence avec la passe de ''Material ID''.</i></center>


<p>Chaque objet aura un identifiant différent.</p>


<p>Une fois de plus, n'oubliez pas de créer le <em>Render Element</em> <em>Object ID</em>:</p>


<p><img src="media/a0f89467.VRay_Arsenal_009_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_009_objectID.png" alt="VRay_Arsenal_009_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_009_objectID.png, janv. 2013"  height="549" width="429" /></p>


<h4>Material control</h4>

<p>Cette partie vous permet d'appliquer quelques valeurs clefs à tous les materials/aux material sélectionnés en un seul clique.</p>
<ul>
<li>Reflection/Refraction Subdivs</li>
<li>Reflection/Refraction Interpolation</li>
<li>Reflection/Refraction Max depth</li>
</ul>

<p>Une option <strong>Trace</strong> (Reflection/Refraction) pour activer/désactiver complètement le raytracing aurait put être intéressante ici. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<h4>Lights control</h4>

<p>On peut pas faire plus simple: Appliquer une valeur de <strong>Shadow subdivs</strong> à toutes les lights/les lights sélectionnées de la scène en un clique.</p>


<h3>Techniquement, comment ça marche?</h3>

<p>Hahaha! La particularité de cet outil est de ne pas modifier votre scène quand vous générez les passes (Sauf les <em>RenderLayers</em> de Maya bien évidement), que vous faites du "On the fly" ou même du Matte.</p>


<p>Mais alors? Comment qu'il fait? <img src="media/9346b45f.confused0028.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/confused0028.gif" alt=":gne2:" class="smiley" /></p>


<p>Et bien il utilise une feature de VRay que je rêverai de voir généralisé sur tout les moteurs tant elle est monstrueuse en terme de possibilités: L'API Python <a href="http://www.spot3d.com/vray/help/maya/150R1/render_scene_access.htm" hreflang="en">VRay Scene Access</a>.</p>


<p>Je quote la doc, c'est très clair:</p>

<blockquote><p>The V-Ray scene access python API allows you to modify the V-Ray scene after it is translated by the V-Ray for Maya translator, and before it is rendered and/or exported to a .vrscene file.
The scene access API allows you to expand the V-Ray for Maya translator by providing custom translation for constructs that are not recognized by V-Ray, or for modifying the scene before rendering without changing the original Maya scene.</p></blockquote>

<p>Boum! Rien que ça! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>En gros, ça permet de piloter le moteur avant le rendu. On peut donc imaginer des trucs de dingue comme générer une scène directement dans VRay, à la volé, sans avoir recours à un fichier vrscene. Pour ceux qui ont déjà travaillé avec Renderman, ça veut dire fini la génération des RIB bien lourd qui ne servent qu'une fois. Ici, on peut piloter VRay via du Python!</p>


<p>J'ai posé la question sur <a href="http://forum.nvidia-arc.com/showthread.php?8097-Python-to-controle-mental-ray" hreflang="en">le forum de Nvidia ARC</a> (ancien Mental Image) tant je trouvais ça génial mais je ne suis pas sur que ça change grand chose. <img src="media/13e2620a.triste.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/triste.gif" alt=":triste:" class="smiley" /></p>


<p>Bref, l'outil de Damien utilise ça, et c'est ce qui lui permet de conserver une scène Maya propre et de pouvoir intervenir directement au niveau de VRay avant le rendu.</p>


<h3>Conclusion</h3>

<p>Pour avoir testé le truc de fond en comble je peut vous assurez qu'il vaut (très) largement son prix (69€! :bravo:).</p>

<ul>
<li>Le temps gagné à préparer ses passes est monstrueux et vous évite d'avoir à passer par toutes les fenêtres de VRay.</li>
<li>Le fait de pouvoir contrôler les objets en fonction de leurs <em>properties</em> et pas l'inverse est tout ce qu'il a de plus simple.</li>
<li>La gestion des Mattes RGB est aussi très simple.</li>
<li>Des Material/Object ID on the fly qui marchent en quelques cliques... Il ne reste aucun prétexte pour ne pas les utiliser.</li>
<li>La VRayMtlLambert on the fly meriterai une section à elle toute seule tant elle peut être pratique.</li>
<li>Le Quality slider va loin avec les preset et les offsets.</li>
</ul>

<p>Ce qu'il manque:</p>
<ul>
<li>Pouvoir exporter son "set de passe" dans un fichier texte pour l'importer plus tard (c'est prevu!).</li>
<li>Encore plus d'options <em>On the fly</em> (Je suis fan du principe).</li>
<li>Une API Python aussi simple à utiliser que les boutons. Genre <em>arsenal.pass.propertiesControl.blackHole.add("myObject")</em>. Mais à part moi je ne suis pas sûr que ça serve à grand monde! <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></li>
</ul>

<p>Bon, je vends <del>un peu</del> complètement le truc mais oui: Il vaut le coup! <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<p>Au delà du fait que je vous invite à vous ruer sur cet outil, j'espère que si vous le possédez déjà, cette présentation/tuto vous permettra d'aller encore plus loin! :)</p>


<p>A bientôt!</p>

<center><i><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></i></center>


feed_id: urn:md5:a1d4379e3684e05628c9d310dc5c3e01
title: Déplacer récursivement un fichier vers un emplacement qui n'existe pas (encore)
uri: Déplacer-récursivement-un-fichier-vers-un-emplacement-qui-n-existe-p
url:
http://www.fevrierdorian.com/blog/post/2013/02/08/Deplacer-recursivement-un-fichier-vers-un-emplacement-qui-n-existe-pas-%28encore%29

content:
<p><img src="http://www.fevrierdorian.com/blog/public/logos/Python_logo_150.png" alt="Python_logo_150.png" style="float:left; margin: 0 1em 1em 0;" title="Python_logo_150.png, mar. 2009"  height="150" width="150" />C'est rien du tout mais à chaque fois que je dois déplacer un fichier vers un dossier qui n'existe pas je me retape cette fonction à la mano avec les désagrément que peut engendrer l'utilisation des <em>os.mkdir</em> et <em>os.rename</em>. <img src="/blog/themes/blueSilenceCustom/smilies/casseTeteMur.gif" alt=":casseTeteMur:" class="smiley" /></p>


<p>Comme ce genre de fonction peut intéresser des gens je la met ici pour en faire profiter tout le monde (afin de participer activement et agrandir cette intelligence collective qu'est l'internet... Pourquoi je dis ça? Euh... Et bien en fait j'essais de grapiller quelques lignes sinon le bloc du code se place mal... <img src="/blog/themes/blueSilenceCustom/smilies/seSentCon.gif" alt=":seSentCon:" class="smiley" /> )</p>    <p>Vous allez voir que c'est assez simple et facilement modifiable.</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> recursivelyMoveFile<span style="color: black;">&#40;</span>srcFile, dstFile<span style="color: black;">&#41;</span> :
&nbsp;
	curFolderPath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">sep</span>	<span style="color: #808080; font-style: italic;"># get the os separator. &quot;/&quot; on linux.</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># we regenerate the folder path we want to create the file in and check, at every step the folder exists</span>
	<span style="color: #ff7700;font-weight:bold;">for</span> folder <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>dstFile<span style="color: black;">&#41;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">sep</span><span style="color: black;">&#41;</span> :
&nbsp;
		curFolderPath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>curFolderPath, folder<span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span>curFolderPath<span style="color: black;">&#41;</span> :
&nbsp;
			<span style="color: #dc143c;">os</span>.<span style="color: black;">mkdir</span><span style="color: black;">&#40;</span>curFolderPath<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #dc143c;">os</span>.<span style="color: black;">rename</span><span style="color: black;">&#40;</span>srcFile, dstFile<span style="color: black;">&#41;</span></pre>


<p>Vous voyez? Rien de bien sorcier. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>Notez que la fonction ne vérifie rien du tout. Soyez donc vigilant avec le <em>os.rename</em>.</p>


<p>Bon... Comme je suis gentil je vous propose une fonction blindé anti-pythonic pour le coup (pour les copieurs/colleurs foux qui ne prennent pas le temps de lire <img src="/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /> )</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> recursivelyMoveFile<span style="color: black;">&#40;</span>srcFile, dstFile<span style="color: black;">&#41;</span> :
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>srcFile<span style="color: black;">&#41;</span> :
		<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;srcFile is not a file -&gt; %s&quot;</span>, srcFile<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>dstFile<span style="color: black;">&#41;</span> :
		<span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dstFile already exist -&gt; %s&quot;</span>, dstFile<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
	curFolderPath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">sep</span>	<span style="color: #808080; font-style: italic;"># get the os separator. &quot;/&quot; on linux.</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># we regenerate the folder path we want to create the file in and check, at every step the folder exists</span>
	<span style="color: #ff7700;font-weight:bold;">for</span> folder <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>dstFile<span style="color: black;">&#41;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">sep</span><span style="color: black;">&#41;</span> :
&nbsp;
		curFolderPath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>curFolderPath, folder<span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span>curFolderPath<span style="color: black;">&#41;</span> :
&nbsp;
			<span style="color: #dc143c;">os</span>.<span style="color: black;">mkdir</span><span style="color: black;">&#40;</span>curFolderPath<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #dc143c;">os</span>.<span style="color: black;">rename</span><span style="color: black;">&#40;</span>srcFile, dstFile<span style="color: black;">&#41;</span></pre>


<p>Codez bien! (Et vite surtout! <img src="/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /> )</p>


feed_id: urn:md5:cab3340e2aee80c7934ba48337a5594a
title: Combiner les importons avec le Final Gather
uri: Combiner-les-importons-avec-le-Final-Gather
url: http://www.fevrierdorian.com/blog/post/2013/02/10/Combiner-les-importons-avec-le-Final-Gather
content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_002_29sec_tn.png" alt="fg_render_002_29sec_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fg_render_002_29sec_tn.png, fév. 2013"  height="150" width="150" />Ne vous est il jamais arrivé d'avoir un éclairage un peu vicieux ou monsieur <em>Final Gather</em> vous propose un bloblotage du pire effet? La seule solution étant souvent de monter les temps de rendu (quand c'est encore possible ^^') pour cacher la misère.</p>


<p>Et encore, parfois, monter tous les paramètres comme un goret n'est pas suffisant, tout simplement parce que le <em>Final Gather</em> ne peut pas gérer ce cas.</p>


<p>Depuis peu, une solution permettant de régler drastiquement (mais pas toujours) ce soucis a été mise au point: C'est les importons.</p>    <p>L'utilisation des importons est plus large qu'une simple variante du <em>Final Gather</em>. Ils s'inscrivent comme une évolution importante (c'est le cas de le dire) de l'illumination globale de mental ray.</p>


<h3>Dans un premier temps, configurer un <em>Final Gather</em> correct.</h3>

<p>La question sur comment configurer le <em>Final Gather</em> n'est pas simple tant le résultat peut être variable suivant la scène. Je vais partir du principe qu'on ne souhaite pas un <em>Final Gather</em> parfait mais un "effet" de <em>Final Gather</em> (une illumination indirect sur un seul rebond). Je vous invite à regarder <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/node76.html#opt:finalgather_trace_depth" hreflang="en">la doc</a>.</p>


<h4>L'accuracy</h4>

<p>C'est le nombre de sample envoyé dans la scène PAR point de <em>Final Gather</em> pour déterminer la valeur de l'illumination en ce point. Si il n'y en a pas assez, le point en question ne sera pas stable. On peu le mettre à 200-500 pour la plupart des cas mais on est parfois obliger de monter sur des valeurs proches de 1000 sur des cas vraiment extrême.</p>


<p>Si vous avez une valeur de <em>point density</em> élevé, l<em>'accuracy</em> peut drastiquement augmenter le temps de rendu.</p>


<h4>Point density</h4>

<p>C'est un facteur du nombre de point de <em>Final Gather</em> shoote depuis la camera. Une valeur de 2.0 double le nombre de point de <em>Final Gather</em> à calculer et donc, le temps de génération du <em>Final Gather</em>.</p>


<p>C'est le premier paramètre que je vous invite à augmenter avant de booster l<em>'accuracy</em>. Gardez à l'esprit que l<em>'accuracy</em> fait effet d'exposant. Ne faites pas varier l'un sans prendre en compte la valeur de l'autre. Une valeur de 10 sur un rendu de prod avec des surfaces de couleur uniforme est envisageable. Avec des textures, les variations peuvent ne pas sauter au yeux et on peu pratiquement rester sur du 2.0-5.0.</p>


<h4>Point interpolation</h4>

<p>C'est le nombre de point de <em>Final Gather</em> qui seront interpolés pour renvoyer une valeur d'illumination indirect au sample qui le demande. Cette valeur change drastiquement l'allure visuelle du <em>Final Gather</em>. Plus il y a d'interpolation, plus c'est doux mais aussi plus ça flick en cas d'animation si le <em>Final Gather</em> n'est pas baké. Si votre scène a un éclairage contrasté, je vous conseille de descendre cette valeur pour rendre le bloblotage général moins visible (plus granuleux disons) on peut tout à fait la mettre à 1.</p>


<p>Notez que vous pouvez augmenter cette valeur en parallèle de votre <em>point density</em>, car plus vous avez de point, plus vous pouvez les interpoler sans que le flicking ne soit trop visible.</p>


<h4>Le reste</h4>

<p>En vrac je fait les choses suivantes:</p>
<ul>
<li><em>Secondary Diffuse Bounce</em>: 0</li>
<li><em>Reflection</em>, <em>Refraction</em> et <em>Max Trace Depth</em> (du <em>Final Gather</em> toujours): 0</li>
</ul>

<p>Pourquoi tout ça à zéro? Parce qu'au delà d'augmenter les temps de rendu et les potentiels artefacts, un seul diffuse bounce suffit à créer un "effet" d'illumination indirect convaincant.</p>

<ul>
<li>Si vous faites de l'animation mettez le mode <em>multiframe</em> (<em>Optimize for Animation</em> dans Maya).</li>
<li>Si vous voulez un <em>Final Gather</em> en brute force, passer en <em>force</em> (<em>No FG Caching</em>). Pour chaque sample, un nouveau point de <em>Final Gather</em> sera créé. Bien entendu, c'est (très) long.</li>
</ul>

<p>Je ne vais pas développer, c’était principalement un rappel. Passons au Importons! <img src="/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<h3>Les importons c'est quoi?</h3>

<p>Je pourrais passer pas mal de temps à tenter d'expliquer ce que sont les importons mais je trouve que <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/importons.html" hreflang="en">la documentation officielle</a> explique cela très clairement. Je vous propose une traduction:
Les importons sont des "particules virtuelles". Sur certains aspects, ils sont similaire aux photons: Ils rebondissent dans la scène.
Il y a toutefois des différences significatives: Contrairement aux photons, les importons ne distribuent pas d’énergie.
Au lieu de cela, ils contiennent une couleur décrivant avec quel facteur une illumination à un point donné contribuerait à l'image finale.
De ce fait, ils fournissent des information au moteur pour l'aider gérer ses calculs de manière à obtenir une image d'une meilleur qualité visuelle tout en diminuant les ressources nécessaires.</p>


<p>Contrairement aux photons, les importons sont émis depuis la camera et rebondissent vers les lights. C'est le fonctionnement inverse des photons.
Cela dit, le fonctionnement interne des lights fait qu'il est possible d'appliquer un photon shader aux importons.
Pour des raisons de simplicité, mental ray n'introduit pas de nouveau type de shader mais permet d'utiliser les photons shaders pour les importons.</p>


<p>Les importons servent de mécanisme supplémentaire qui améliore la qualité et les performances du rendu.
Il fait office de mécanisme principale pour driver la qualité des irradiance particles.
Les importons peuvent également êtres utilisé pour améliorer la qualité des photon maps d'illumination globale.
Ils permettent de réduire drastiquement la taille (et donc, la vitesse de consultation) des photon map en procédant à un merging adaptatif déterminé via les importons.
Un tel mécanisme adaptatif est supérieur au merging fixe déjà existant.</p>


<p>Si ils sont activés, les importons sont shootés avant que la photon map ne soit créé.
Ils sont utilisés durant la creation de la photon map d'illumination globale.
Comme ils ne sont pas d'utilisation autre que la recherche des photons pertinents, les importons sont jetés une fois que la photon map est créée.</p>


<p>L'importons map est contrôlé par les <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/node76.html#importon" hreflang="en">options</a> de rendu de la scène. <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/limitations.html#importon" hreflang="en">Certaines limitations</a> sont connus.</p>


<p>En gros, vous l'avez compris, on "shoot" des particules puis la camera qu'on fait rebondir dans la scène et on détermine quelles sont les zones de la scène qui on de l'importance "visuelle" dans l'image final. De ce fait, on est capable de savoir quelle sont les zones de la scène qu'il va être important de sampler/"finalgatheurer" et on oublie les autres. Le <em>Final Gather</em> était jusqu'à présent très bête, mais avec les importons, il l'est beaucoup moins. <img src="/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /></p>


<h3>Autodesk, encore et toujours</h3>

<p>Bon, ça commence à me saouler de leur taper dessus mais vous allez voir qu'une fois encore on bataille contre son soft pour faire marcher le truc...
Pour une raison qui m’échappe totalement, Autodesk a décidé que si l'utilisateur cochait <em>Final Gather</em>, il n'avait pas d’intérêt à cocher <em>Importons</em> (ni <em>Irradiance Particles</em>). L'option devient donc grisée.
Oui, c'est stupide. Le choix a due être fait un jour, sans trop lire la documentation et n'a jamais été changé depuis (sont ils seulement au courant?).
Bref, on ne va pas s’éterniser, je vous invite très fortement à télécharger mon tool <a href="Mhttp://forums.cgsociety.org/showthread.php?f=87&amp;t=971719" hreflang="en">enjoyMentalRayStringOptions</a> pour pouvoir outrepasser les limitations imposées par Maya.</p>


<p>Dans la mesure ou cocher <em>Final Gather</em> désactive les importons, il faut cocher <em>Final Gather</em> depuis les <em>Render Settings</em> de Maya PUIS <em>Importons</em> depuis mon interface... L'inverse désactiverait les Importons.</p>


<p>Notez qu'a chaque fois que vous relancez la fenêtre <em>Render Settings</em>, le <em>Final Gather</em> désactive les importons... Gardez la donc ouverte! (Oui oui, je sais... <img src="/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> )</p>


<p>Il existe aussi un tool que je n’ai pas teste mais qui se veut complètement intégré à Maya. Il est présenté <a href="https://elementalray.wordpress.com/2012/08/10/new-maya-rendering-ui-testing/" hreflang="en">ici</a> et la page du script est <a href="https://code.google.com/p/maya-render-settings-mental-ray/" hreflang="en">ici</a>.</p>


<h3>Et le petit tuto!</h3>


<p>Une fois que vous avez compris la partie ci dessus, vous allez voir que c'est très (très) rapide! :D</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_001.png" alt="fg_001.png" style="display:block; margin:0 auto;" title="fg_001.png, fév. 2013"  height="209" width="411" /></p>
<center><i>PIF Cocher le FG!</i></center>



<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_002.png" alt="fg_002.png" style="display:block; margin:0 auto;" title="fg_002.png, fév. 2013"  height="204" width="483" /></p>
<center><i>PAF cocher les importons!</i></center>



<p>BOUM Lancez le rendu! <img src="/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_001_27sec.png" title="fg_render_001_27sec.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/.fg_render_001_27sec_m.jpg" alt="fg_render_001_27sec.png" style="display:block; margin:0 auto;" title="fg_render_001_27sec.png, fév. 2013"  height="315" width="560" /></a></p>
<center><i>Avant... (27sec)</i></center>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_002_29sec.png" title="fg_render_002_29sec.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/.fg_render_002_29sec_m.jpg" alt="fg_render_002_29sec.png" style="display:block; margin:0 auto;" title="fg_render_002_29sec.png, fév. 2013"  height="315" width="560" /></a></p>
<center><i>Après... (29sec)</i></center>


<p>On constate une nette amélioration au niveau des artefacts sur les murs. En effet, mental ray a projeté ses Final Gathers Points en prenant en compte l'importance (calculé au début du rendu) de ces points dans l'image finale.</p>


<p>Je vous invite aussi à regarder le log en mode <em>Progess</em> pour vous assurer que les Importons sont bien shoote depuis la camera.</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_003.png" alt="fg_003.png" style="display:block; margin:0 auto;" title="fg_003.png, fév. 2013"  height="310" width="209" /></p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_004.png" alt="fg_004.png" style="display:block; margin:0 auto;" title="fg_004.png, fév. 2013"  height="163" width="468" /></p>


<h3>Conclusion</h3>

<p>J'espère que ces petites explications vous aiderons à améliorer vos rendu en <em>Final Gather</em>. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>A bientôt!</p>

<center><i><img src="/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></i></center>


feed_id: urn:md5:fbc178cca3b83e95a05a222f2eb7d735
title: Combine importons with Final Gather (English Translation)
uri: Combine-importons-with-Final-Gather-(English-Translation)
url:
http://www.fevrierdorian.com/blog/post/2013/02/10/Combine-importons-with-Final-Gather-English-Translation

content:
<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_002_29sec_tn.png" alt="fg_render_002_29sec_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fg_render_002_29sec_tn.png, fév. 2013"  height="150" width="150" />This is an english translation of a <a href="http://www.fevrierdorian.com/blog/post/2013/02/10/Combiner-les-importons-avec-le-Final-Gather">ticket I wrote</a> few days ago.</p>


<p>Have you ever had a lighting where mister <em>Final Gather</em> give you a scene with a whole dirty flicking? The only solution is often to increase render settings and so, render times (when it is still possible ^^') to hide the misery.</p>


<p>And yet, sometimes, increase all settings like a pig is not enough, simply because <em>Final Gather</em> can not handle your case.</p>


<p>A solution to drastically solve (but not always) this problem exists: Importons.</p>    <p>Importons are more than a simple <em>Final Gather</em> variation. They fit in a significant change in the way mental ray will deal with global illumination and sampling in general.</p>


<h3>First step, get a correct <em>Final Gather</em>.</h3>


<p>The question on how to configure the <em>Final Gather</em> is not straightforward as the results can deeply change depending on the scene. I'm going to assume we don't want a perfect <em>Final Gather</em> but an "effect" of <em>Final Gather</em> (indirect illumination in one bounce). I invite you to look at <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/node76.html#opt:finalgather_trace_depth" hreflang="en">the documentation</a>.</p>


<h4>Accuracy</h4>

<p>It's the number of samples send through the scene for each point of <em>Final Gather</em> to determine the value of the illumination at this point. If there is not enough, the actual point will not be stable. We can set it to 200-500 for most cases, but sometime you need to go on values close to 1000 in really extreme cases.</p>


<p>If you have a high <em>point density</em> value, <em>accuracy</em> car drastically increase render times.</p>


<h4>Point density</h4>

<p>This is a factor of the number of <em>Final Gather</em> points shoot from the camera. A value of 2.0 doubles the number of <em>Final Gather</em> points to compute, and so, double the <em>Final Gather</em> generation time.</p>



<p>This is the first parameter that I invite you to increase before boost the <em>accuracy</em>. Keep in mind that <em>accuracy</em> has an exponent effect. Do not change one without taking care the value of the other. A value of 10 on a production render with flat surfaces of uniform color is possible. With textures, variations can be less visible and you can almost stay on the little values like 2.0-5.0.</p>



<h4>Point interpolation</h4>

<p>This is the number of <em>Final Gather</em> points that will be interpolated to return a value of indirect illumination to the projected sample. This value drastically changes the visual appearance of <em>Final Gather</em>. The more interpolation is, the more <em>Final Gather</em> is smooth but more it flick in animation if it's not bake. If your scene has high contrasted lighting, I suggest you go down this value to make the flicking generally less visible (more granular). We can put 1 if needed.</p>



<p>Note that you can increase this value at the same time as <em>point density</em>, because the more you have points, the more you can interpolate and keep flicking invisible.</p>


<h4>For the rest...</h4>

<p>I do the following things:</p>
<ul>
<li><em>Secondary Diffuse Bounce</em>: 0</li>
<li><em>Reflection</em>, <em>Refraction</em> and <em>Max Trace Depth</em> (of <em>Final Gather</em> of course): 0</li>
</ul>

<p>Why all of this to zero? Because beyond to increase rendering time and potential artifacts, one diffuse bounce is enough to create a convincing "effect" of indirect illumination.</p>

<ul>
<li>If you are doing animation, set the <em>multiframe</em> mode (<em>Optimize for Animation</em> in Maya).</li>
<li>If you want a brute force <em>Final Gather</em>, switch to <em>force</em> (<em>No FG Caching</em>). For each sample, a new <em>Final Gather</em> point will be created. Of course, this is (very) long.</li>
</ul>

<p>I will not spend much time on this, it was mainly a reminder. Let's talk about Importons! <img src="/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<h3>What importons are?</h3>

<p>I could spend a lot of time trying to explain what the importons are but I think <a href="http://docs.autodesk.com/MENTALRAY/2013/ENU/mental-ray-help/files/manual/importons.html" hreflang="en">the official documentation</a> is very clear. Just read it! <img src="/blog/themes/blueSilenceCustom/smilies/sign0012.gif" alt=":RTFM:" class="smiley" /></p>


<p>Basically, you guessed it, mental ray "shoot" particles from camera that bounces in the scene and determines which areas of the scene have "visual" importance in the final image. Therefore, mental ray is able to "know" which areas of the scene will be important to sample and forget the others. Until now, <em>Final Gather</em> was very silly, but with the importons, it is much less. <img src="/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /></p>


<h3>Autodesk, again and again and...</h3>

<p>Well, I starts to get bored to slug them all the time but you will see that, once again, we fight against Maya to run the thing...
For an unknown reason, Autodesk has decided that if the user tick <em>Final Gather</em>, he had no interest to tick <em>Importons</em> (neither <em>Irradiance Particles</em>). This option becomes grayed out.
Yes, that's stupid... I suppose choice has been made one day, without paid to much attention to the documentation and has never been change since (are they only aware of?).
So, we will not speak about this too much, I invite you to use my tool <a href="Mhttp://forums.cgsociety.org/showthread.php?f=87&amp;t=971719" hreflang="en">enjoyMentalRayStringOptions</a> to go through Maya's limitations.</p>


<p>Insofar tick <em>Final Gather</em> disables importons, you need to tick <em>Final Gather</em> in <em>Render Settings</em> THEN <em>Importons</em> from my interface... Reverse would disables <em>Importons</em>...</p>


<p>Notice that each time you restart <em>Render Settings</em> window, <em>Final Gather</em> will disable <em>Importons</em>... So keep it open! (Yes yes, I know... <img src="/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> )</p>


<p>There is also a tool that I have not tested but who aim to fully integrate with Maya and should solve this problem. It is shown <a href="https://elementalray.wordpress.com/2012/08/10/new-maya-rendering-ui-testing/" hreflang="en">here</a> and the page of the script is <a href="https://code.google.com/p/maya-render-settings-mental-ray/" hreflang="en">here</a>.</p>


<h3>And the tiny tutorial!</h3>


<p>Once you've understand the above part, you will see it's quite easy! :D</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_001.png" alt="fg_001.png" style="display:block; margin:0 auto;" title="fg_001.png, fév. 2013"  height="209" width="411" /></p>
<center><i>DIM Tick FG!</i></center>



<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_002.png" alt="fg_002.png" style="display:block; margin:0 auto;" title="fg_002.png, fév. 2013"  height="204" width="483" /></p>
<center><i>DAM Tick importons!</i></center>



<p>DOOM Launch the render! <img src="/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>


<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_001_27sec.png" title="fg_render_001_27sec.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/.fg_render_001_27sec_m.jpg" alt="fg_render_001_27sec.png" style="display:block; margin:0 auto;" title="fg_render_001_27sec.png, fév. 2013"  height="315" width="560" /></a></p>
<center><i>Before... (27sec)</i></center>



<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_render_002_29sec.png" title="fg_render_002_29sec.png"><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/.fg_render_002_29sec_m.jpg" alt="fg_render_002_29sec.png" style="display:block; margin:0 auto;" title="fg_render_002_29sec.png, fév. 2013"  height="315" width="560" /></a></p>
<center><i>After... (29sec)</i></center>


<p>There is a clear improvement in artifacts on the walls. Indeed, mental ray shoot it <em>Final Gather</em> points taking into account the importance (calculated at the beginning of the render) of these points in the final image.</p>


<p>I also invite you to look at the log in <em>Progress</em> mode to ensure <em>Importons</em> are well shooted through the camera</p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_003.png" alt="fg_003.png" style="display:block; margin:0 auto;" title="fg_003.png, fév. 2013"  height="310" width="209" /></p>


<p><img src="http://www.fevrierdorian.com/blog/public/billets/2013_02_10_FG_Importons/fg_004.png" alt="fg_004.png" style="display:block; margin:0 auto;" title="fg_004.png, fév. 2013"  height="163" width="468" /></p>


<p>Importons are very fast to shoot through camera so don't hesitate to use them! <img src="/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>


<h3>Conclusion</h3>


<p>I hope this little explanations will help you to improve your renders with <em>Final Gather</em>. <img src="/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>See you!</p>

<center><i><img src="/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></i></center>


feed_id: urn:md5:212f5e2b8e46bf1b868a9437b8f0afe4
title: Les User Attributes de VRay
uri: Les-User-Attributes-de-VRay
url: http://www.fevrierdorian.com/blog/post/2013/02/17/Les-User-Attributes-de-VRay
content:
<p><img src="media/8980c15c.user_attr_vray_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_tn.png" alt="user_attr_vray_tn.png" style="float:left; margin: 0 1em 1em 0;" title="user_attr_vray_tn.png, fév. 2013"  height="150" width="150" />Voici un tuto que je voulais faire depuis pas mal de temps. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>VRay propose, depuis un bon moment maintenant, d'utiliser des attributs par objet pour contrôler certaines valeurs. Ça peut aller assez loin mais bien souvent, ce sont les shaders qui en profite. L'idée est d'appliquer un seul et unique shader à un grand nombre d'objet, mais que chaque objet ait des attributs "spéciaux" avec une valeur bien particulière qui se verront appliquer sur les attributs du shader. Si vous vous rappelez bien, je <a href="http://www.fevrierdorian.com/blog/post/2011/04/16/Mental-ray-3.9-Les-User-Data-Shaders-ou-Shader-Package">vous avais présenté</a> une feature similaire sous mental ray (Les User Data).</p>


<p>Mais avant même de faire ça, ce tuto va vous expliquer comment exporter puis importer des vrmesh et refaire des assignations de shader à l’intérieur des-dits vrmesh! Bref, un gros programme! <img src="media/2e1ef912.bravo.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bravo.gif" alt=":bravo:" class="smiley" /></p>    <h3>Les vrmesh (ou proxy)</h3>


<h4>C'est quoi?</h4>

<p>Pour faire très brièvement: Vous connaissez le principe du tiling des textures? (Non? <a href="http://www.fevrierdorian.com/blog/post/2009/01/14/Le-mappage-en-m%C3%A9moire-des-textures-dans-Mental-Ray-expliqu%C3%A9-%28Memory-mapped-textures%29.">Hop! Hop! Hop!</a> Et plus vite que ça! <img src="media/f1f7d503.nannan.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nannan.gif" alt=":nannan:" class="smiley" /> ) Et bien le principe est le même, mais pour de la géométrie: Les vrmesh sont des mesh "prêt à être raycasté". La géométrie y est stocké dans une grille (voxel).</p>


<p>Ainsi, vous ne chargerez que "la boite" nécessaire au rendu. Votre vrmesh peut faire une taille astronomique, seul les éléments nécessaire au calcul seront chargé/déchargé à la volé. Au même titre que les maps tilé, ceci a pour effet d'augmenter les IO sur vos disques mais vous donne une énorme flexibilité.</p>


<p>N'ayez donc pas peur de la taille, les vrmesh sont fait pour! :D</p>


<h4>Pratique</h4>

<p>On va faire simple, voici une scène avec deux cycle d'animation de 24 frames:</p>


<p><a href="media/f9eea4c8.user_attr_vray_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_001.png" title="user_attr_vray_001.png"><img src="media/3fd074a7..user_attr_vray_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/.user_attr_vray_001_m.jpg" alt="user_attr_vray_001.png" style="display:block; margin:0 auto;" title="user_attr_vray_001.png, fév. 2013"  height="346" width="560" /></a></p>
<center><i>Ça ne se voit pas mais ces deux bonhommes marchent! <img src="media/38d91e93.onSeFendLaPoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/onSeFendLaPoire.gif" alt=":onSeFendLaPoire:" class="smiley" /></i></center>



<p>A cette étape, le principe est d'assigner à chaque "groupe de shader", un shader quelconque. C'est le nom qui importe car c'est ce nom là qui sera stocké dans le vrmesh:</p>


<p><img src="media/bb205d9f.user_attr_vray_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_002.png" alt="user_attr_vray_002.png" style="display:block; margin:0 auto;" title="user_attr_vray_002.png, fév. 2013"  height="159" width="549" /></p>
<center><i>"lambert5" ça aurait dû être "bras" mais je suis complètement passé à coté. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></i></center>



<p>Même si ce n'est pas obligatoire, essayez de garder une cohérence dans les noms entre tous vos objets. Ainsi, si vous avez des personnages de foule à exporter. Assignez leur à tous les shaders "bras", "corp", "tete", "cheuveux", "tenuHaut", "tenuBas", etc... Avec un peut de script, vous gagnerez du temps plus tard.</p>


<p>Sélectionnez le groupe de mesh que vous souhaitez exporter:</p>


<p><img src="media/5651de61.user_attr_vray_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_003.png" alt="user_attr_vray_003.png" style="display:block; margin:0 auto;" title="user_attr_vray_003.png, fév. 2013"  height="92" width="253" /></p>


<p>Puis allez dans <em>Create/V-Ray/Create proxy</em>:</p>


<p><img src="media/c0e670bb.user_attr_vray_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_004.png" alt="user_attr_vray_004.png" style="display:block; margin:0 auto;" title="user_attr_vray_004.png, fév. 2013"  height="489" width="420" /></p>


<p>Vous arrivez devant une interface <del>horrible</del> sobre:</p>


<p><img src="media/804e0241.user_attr_vray_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_005.png" alt="user_attr_vray_005.png" style="display:block; margin:0 auto;" title="user_attr_vray_005.png, fév. 2013"  height="582" width="576" /></p>


<p>Cochez <em>Export animation</em>. Si votre mesh est animé et que vous envisagez d'utiliser du motion blur sur votre rendu final, cochez aussi <em>Export velocity</em>. Les deux valeurs vont créer l’intervalle qui permettra de calculer le vecteur de direction à stocker dans les vertex. C'est à partir de ça que VRay calculera le motion blur de la géométrie. Soyez vigilant sur cet intervalle. On peu avoir des (mauvaises) surprises. Si vous ne comptez pas rendre avec du motion blur, décochez cette options, se sera des informations en moins à stocker dans la géométrie.</p>


<p>Dans mon cas j'ai aussi coché <em>Use playback range</em> mais avisez en fonction. <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>Avec <em>Face in preview</em>, Chaos Group nous gratifie une fois de plus d'une petite feature à priori anodine mais très intéressante en pratique: Le principe est de sauver les index de <em>n</em> face qui seront affiché dans le viewport plus tard.</p>


<p>Quand on fait des proxy, principalement pour alléger sa scène, on se retrouve souvent à devoir gérer des grosses bouding box à la place. Si le pipeline le permet, vous aurez peut être même un proxy fait par un autre département (on ne compte même pas de temps nécessaire). La, les bonhommes de Chaos Group ont eux la réflexion très intéressante: "Pourquoi pas faire un proxy sympa, qui correspond à quelque chose mais vraiment allégé?". Le pari est entièrement réussi, vous verrez ça plus tard. :)</p>


<p>Si vous souhaitez réimporter directement le proxy nouvellement créé, vous pouvez, si vous le voulez cliquer sur <em>Automatically create proxies</em>.</p>


<p>Pour le reste, je vous conseil vivement de regarder <a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm#export_gui" hreflang="en">la doc</a>.</p>


<p>Une fois que c'est fait, on clique sur <em>Create Proxy</em>!</p>


<p>Faites ça pour tout les personnages que vous avez à exporter.</p>

<center><img src="media/f0159d47.longBar.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/longBar.png" alt=":longBar:" class="smiley" /></center>



<p>Pour importer tout ça:</p>


<p><img src="media/b1e4c606.user_attr_vray_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_006.png" alt="user_attr_vray_006.png" style="display:block; margin:0 auto;" title="user_attr_vray_006.png, fév. 2013"  height="109" width="431" /></p>


<p><img src="media/ce1c29ea.user_attr_vray_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_007.png" alt="user_attr_vray_007.png" style="display:block; margin:0 auto;" title="user_attr_vray_007.png, fév. 2013"  height="201" width="333" /></p>


<p>Tadaaaa:</p>


<p><img src="media/f12b8b3f.user_attr_vray_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_008.png" alt="user_attr_vray_008.png" style="display:block; margin:0 auto;" title="user_attr_vray_008.png, fév. 2013"  height="398" width="349" /></p>


<p><img src="media/d62ed0ad.user_attr_vray_009.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_009.png" alt="user_attr_vray_009.png" style="display:block; margin:0 auto;" title="user_attr_vray_009.png, fév. 2013"  height="446" width="538" /></p>


<p>Et voilà nos 100 faces par objet. Ça claque hein? <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<p>Plus sérieusement, vous pouvez en mettre des centaines, votre viewport ne bronchera pas. De plus, ces proxys correspondent au modèle final. L'approximation vous gênera beaucoup moins qu'un model low ou pire, une bounding box.</p>


<p>Mais allons zyeuter les options:</p>


<p><img src="media/7b7c45eb.user_attr_vray_010.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_010.png" alt="user_attr_vray_010.png" style="display:block; margin:0 auto;" title="user_attr_vray_010.png, fév. 2013"  height="711" width="522" /></p>


<p>Si on coche <em>Bounding box</em>:</p>


<p><img src="media/ddbecb75.user_attr_vray_011.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_011.png" alt="user_attr_vray_011.png" style="display:block; margin:0 auto;" title="user_attr_vray_011.png, fév. 2013"  height="389" width="418" /></p>
<center><i>Pour les nostalgiques. <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></i></center>



<p>Si vous n'êtes pas satisfait de l'approximation, Chaos Group a pensé à vous: <em>Show whole mesh</em>:</p>


<p><img src="media/f5a6ed79.user_attr_vray_012.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_012.png" alt="user_attr_vray_012.png" style="display:block; margin:0 auto;" title="user_attr_vray_012.png, fév. 2013"  height="309" width="257" /></p>


<p>Les autres options sont plus spécifique. Je ne rentre pas plus dans les détails. Si ça vous intéresse: <a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm#parameters" hreflang="en"><img src="media/9ca8344d.sign0012.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sign0012.gif" alt=":RTFM:" class="smiley" /></a>.</p>


<p>Notez juste que la vitesse de l'animation est configurable (animable aussi! <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /> ) et que dans notre cas (et la plupart des cas) elle est cyclique (<em>Loop</em>).</p>


<p>Allez dans les onglets plus à droite. VRay nous a déjà connecté un shader et...</p>


<p><img src="media/8a6a00fe.user_attr_vray_013.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_013.png" alt="user_attr_vray_013.png" style="display:block; margin:0 auto;" title="user_attr_vray_013.png, fév. 2013"  height="419" width="520" /></p>


<p>Oh miracle! Nos slots sont là! <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>Vous n'aurez plus qu'a drag and droper les shaders à utiliser.</p>


<p>Notez qu'à trop vouloir être gentil, VRay nous créé un shader pour chaque vrmesh importé. Sauf que si vous importez deux fois le même vrmesh, vous aurez deux shaders qui font là même chose. N'hésitez pas à en virer un et à appliquer un seul shader par type de vrmesh.</p>


<p>Maintenant passons aux choses sérieuses! <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /></p>


<h3>Les User Attributes</h3>


<p>Sélectionnez le node de <em>transform</em> d'un des vrmesh et ajoutez y des <em>User attributes</em>:</p>


<p><img src="media/77930387.user_attr_vray_014.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_014.png" alt="user_attr_vray_014.png" style="display:block; margin:0 auto;" title="user_attr_vray_014.png, fév. 2013"  height="171" width="439" /></p>


<p>Dans ces <em>User attributes</em> (paumé tout en bas de votre <em>Attribute Editor</em>) ajoutez la chose suivante:</p>
<pre class="bash bash"><span style="color: #007800;">casquetteColor</span>=<span style="color: #000000;">1</span>,<span style="color: #000000;">1</span>,<span style="color: #000000;">0</span>;</pre>


<p><img src="media/74bd2d43.user_attr_vray_015.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_015.png" alt="user_attr_vray_015.png" style="display:block; margin:0 auto;" title="user_attr_vray_015.png, fév. 2013"  height="82" width="522" /></p>


<p>Là normalement vous commencez à comprendre. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<p>Sur le second, créez une valeur similaire:</p>


<p><img src="media/3a00e9db.user_attr_vray_016.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_016.png" alt="user_attr_vray_016.png" style="display:block; margin:0 auto;" title="user_attr_vray_016.png, fév. 2013"  height="77" width="517" /></p>


<p>Maintenant créez un shader, un <em>blinn</em> dans mon exemple (Oui, je sais, c'est mal). Donnez lui un nom clair (ça va vite devenir le foutoir dans vos connections donc c'est vous qui voyez <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /> ):</p>


<p><img src="media/b821088f.user_attr_vray_017.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_017.png" alt="user_attr_vray_017.png" style="display:block; margin:0 auto;" title="user_attr_vray_017.png, fév. 2013"  height="119" width="224" /></p>


<p>Ajoutez un node <em>VRayUserColor</em> et entrez la valeur de votre attribut:</p>


<p><img src="media/8ab6097f.user_attr_vray_018.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_018.png" alt="user_attr_vray_018.png" style="display:block; margin:0 auto;" title="user_attr_vray_018.png, fév. 2013"  height="134" width="394" /></p>


<p><img src="media/eb433448.user_attr_vray_019.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_019.png" alt="user_attr_vray_019.png" style="display:block; margin:0 auto;" title="user_attr_vray_019.png, fév. 2013"  height="289" width="517" /></p>


<p>Mettez la couleur par défaut qui vous convient. Ce sera la couleur utilisé si le <em>User Attribute</em> n'est pas présent/valide.</p>


<p>Vous avez des exemples de syntax juste en dessous du node (encore une bonne idée).</p>


<p>Connectez ce node à la <em>color</em> de votre shader (dommage que Maya n'utilise pas la <em>default color</em> dans l'hypershade, ça serait toujours plus sympa qu'un truc tout noir.</p>


<p><img src="media/efa861d7.user_attr_vray_020.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_020.png" alt="user_attr_vray_020.png" style="display:block; margin:0 auto;" title="user_attr_vray_020.png, fév. 2013"  height="139" width="395" /></p>


<p>Connectez votre shader aux deux <em>VRayMeshMaterial</em>, dans le slot... "casquette":</p>


<p><img src="media/71f215c6.user_attr_vray_022.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_022.png" alt="user_attr_vray_022.png" style="display:block; margin:0 auto;" title="user_attr_vray_022.png, fév. 2013"  height="333" width="515" /></p>


<p><img src="media/47d71b1c.user_attr_vray_021.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_021.png" alt="user_attr_vray_021.png" style="display:block; margin:0 auto;" title="user_attr_vray_021.png, fév. 2013"  height="223" width="367" /></p>


<p>Puis rendez:</p>


<p><img src="media/2c4c40ac.user_attr_vray_023.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_023.png" alt="user_attr_vray_023.png" style="display:block; margin:0 auto;" title="user_attr_vray_023.png, fév. 2013"  height="433" width="597" /></p>
<center><i><a href="http://www.youtube.com/watch?v=8RLPG88u3lM">La musique de victoire</a> (à écouter avec <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /> )</i></center>



<p>Faîtes pareil pour tous les shaders (sauf le corp qu'on se garde pour après <img src="media/990690f6.whistle2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /> ):</p>


<p><img src="media/ea76eeba.user_attr_vray_024.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_024.png" alt="user_attr_vray_024.png" style="display:block; margin:0 auto;" title="user_attr_vray_024.png, fév. 2013"  height="144" width="502" /></p>


<p><img src="media/d4336934.user_attr_vray_025.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_025.png" alt="user_attr_vray_025.png" style="display:block; margin:0 auto;" title="user_attr_vray_025.png, fév. 2013"  height="426" width="564" /></p>


<p>Bon, voilà pour les couleurs. Vous pouvez faire de même avec les <em>VRayUserScalar</em> et les attributs à virgule.</p>


<p>Maintenant attaquons nous au corp:</p>


<p><img src="media/9e4c8911.user_attr_vray_026.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_026.png" alt="user_attr_vray_026.png" style="display:block; margin:0 auto;" title="user_attr_vray_026.png, fév. 2013"  height="189" width="357" /></p>
<center><i>Juste un node de file.</i></center>



<p>Imaginons que vous ayez quatre textures:</p>
<ul>
<li>checker_default.png</li>
<li>checker_four.png</li>
<li>checker_etc.png</li>
</ul>


<p>La seule variable dans votre texture se situe à la fin (et, pourquoi pas, dans le chemin).</p>


<p>Mettez donc ça dans votre chemin de fichier:</p>


<p><img src="media/1f26f745.user_attr_vray_027.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_027.png" alt="user_attr_vray_027.png" style="display:block; margin:0 auto;" title="user_attr_vray_027.png, fév. 2013"  height="64" width="354" /></p>


<p>Et appliquez la variable à vos différents <em>User Attributes</em>:</p>


<p><img src="media/22fdd4e5.user_attr_vray_028.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_028.png" alt="user_attr_vray_028.png" style="display:block; margin:0 auto;" title="user_attr_vray_028.png, fév. 2013"  height="61" width="506" /></p>


<p><img src="media/4409df8e.user_attr_vray_029.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_029.png" alt="user_attr_vray_029.png" style="display:block; margin:0 auto;" title="user_attr_vray_029.png, fév. 2013"  height="69" width="518" /></p>


<p>Rendez!</p>


<p><img src="media/1368d6e0.user_attr_vray_030.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_030.png" alt="user_attr_vray_030.png" style="display:block; margin:0 auto;" title="user_attr_vray_030.png, fév. 2013"  height="428" width="567" /></p>
<center><i><a href="http://www.youtube.com/watch?v=8RLPG88u3lM">On se la remet?</a></i></center>



<p>Et si on s'enflamme un peu:
<img src="media/5e16da71.user_attr_vray_031.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_031.png" alt="user_attr_vray_031.png" style="display:block; margin:0 auto;" title="user_attr_vray_031.png, fév. 2013"  height="520" width="681" /></p>


<p><img src="media/0869791c.user_attr_vray_032.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_032.png" alt="user_attr_vray_032.png" style="display:block; margin:0 auto;" title="user_attr_vray_032.png, fév. 2013"  height="417" width="579" /></p>


<p>Si vous êtes amené à faire souvent (ou pas) des foules, vous devriez serieusement envisager cette solution.</p>


<h3>Petites notes</h3>

<p>Mine de rien, et comme les <em>User Data</em> de mental ray, c'est un peu laborieux à mettre en place. Mais si vous ou un collègue savez scripter, il n'est pas trop difficile de mettre ça en place sur une production.</p>


<p>On me souffle à l'oeillette qu'il se peut (c'est non confirmé donc à prendre avec des pincettes) que Deex (que je remercie pour m'avoir fait découvrir VRay) intègre ça à <a href="http://arsenal.deex.info/" hreflang="en">Arsenal</a>. On peut donc espérer un truc simple (mais soyez pas trop pressé <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /> ).</p>


<h3>Conclusion</h3>


<p>J’espère que ce tuto assez costaud vous aidera dans vos productions.</p>


<p>A bientot!</p>


<p>Dorian</p>

<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:288cc3302d771adb7dbd633856095452
title: Deex VRay Arsenal, a small tool that saves a lot of time (English Traduction)
uri: Deex-VRay-Arsenal-a-small-tool-that-saves-a-lot-of-time-(English-Trad
url:
http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-a-small-tool-that-saves-a-lot-of-time

content:
<p><img src="media/8866d0ad.VRay_Arsenal_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_tn.png" alt="VRay_Arsenal_tn.png" style="float:left; margin: 0 1em 1em 0;" title="VRay_Arsenal_tn.png, janv. 2013"  height="150" width="150" />It's been a while since I heard Damien (aka <a href="http://deex.info/" hreflang="en">Deex</a>) talk about his tool. I even had the opportunity to be on the same production when he thought the main line. When he told me that his tool was finally done, I could not help but ask him a license to test it out. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>The idea of this post is to present the main features of Arsenal. You will see that despite an approach that may seem a little too user friendly, this tool is a true production tool that make the job quite easier.</p>


<p>Let's go! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>    <blockquote><p>Notice: Before we start, I invite you to check <em>Use V-Ray VFB</em> in the <em>VRay Common</em> tab of the <em>Render Settings</em> panel:</p></blockquote>


<p><img src="media/dde82e54.VRay_Arsenal_012_useVRay_frameBuffer.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_012_useVRay_frameBuffer.png" alt="VRay_Arsenal_012_useVRay_frameBuffer.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_012_useVRay_frameBuffer.png, janv. 2013"  height="369" width="428" /></p>


<p>This will give you access to a kind of special VRay <em>Render View</em> that allows you (in addition to a lot of things) to directly visualize passes (top left).</p>


<p><img src="media/5a69fd22.VRay_Arsenal_011_frameBuffer.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_011_frameBuffer.png" alt="VRay_Arsenal_011_frameBuffer.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_011_frameBuffer.png, janv. 2013"  height="137" width="331" /></p>


<p><img src="media/b5bed629.VRay_Arsenal_sampleImage.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_sampleImage.png" alt="VRay_Arsenal_sampleImage.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_sampleImage.png, janv. 2013"  height="319" width="301" /></p>
<center><i>My test imaget: A HDR from <a href="http://www.hdrlabs.com/sibl/archive.html">sIBL</a>, and a lot of talent! <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></i></center>



<h3>Installation</h3>


<p>I thought <a href="http://arsenal.deex.info/wordpress/documentation/installation/" hreflang="en">installation</a> was "special" in some part. This is not what we are used to see in common scripts.</p>


<p>First, you must install PyQt which most of the time is not an easy task (especially on Windows). Fortunately, an "easy" installer is available on the website. It's pretty cool!</p>


<p>The tool installation has been, designed to simplify the production integration (using environment variables), but can be quite daunting for people who are not necessarily used to play with their <em>Maya.env</em> file. Especially since I'm sure he would have been possible to have a "old school" install (scripts in the <em>script</em> folder, the shelves in the <em>shelves</em> folder, etc ... ), but this wouldn't have been so clean and it would have been a bit more complicated to deal with every update then with the current way, you just need to replace one folder. <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>



<h3>The main window</h3>

<p>When you launch it, you've got this:</p>


<p><img src="media/05cc01c2.VRay_Arsenal_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_001.png" alt="VRay_Arsenal_001.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_001.png, janv. 2013"  height="933" width="536" /></p>


<p>We will talk about tabs bellow.</p>


<p>There is a <em>spin</em> button. Once ticked, Arsenal will "stay at the top". Else, it behave like a Maya window.</p>


<p>There also is a <em>close</em> button at the bottom I would not insult you explain the purpose. <img src="media/e7107ccf.reflexionIntense.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflexionIntense.gif" alt=":reflexionIntense:" class="smiley" /></p>


<p>There is three tabs we will see in the order:</p>
<ul>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-a-small-tool-that-saves-a-lot-of-time#pass">Pass</a>, which regroup Maya <em>Render Layers</em> and the VRay pass system. Their both combined use is common.</li>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-a-small-tool-that-saves-a-lot-of-time#quality">Quality</a>, which is a very usefull feature: A slider, from 0 to 99 to increase or decrease render quality using a gradual modification of your render settings.</li>
<li><a href="http://www.fevrierdorian.com/blog/post/2013/02/07/Deex-VRay-Arsenal-a-small-tool-that-saves-a-lot-of-time#toolbox">ToolBox</a>, which regroup a lot of tiny tools that save a lot of time.</li>
</ul>

<h3>L'onglet <em>Pass</em> <a name="pass"></a></h3>


<p>On the top part, it's just  Maya <em>Render Layer</em> (unjustly named "Pass" in the three buttons on the left). Click on one of these <em>Render Layer</em> select it the same way Maya does. It's just a time saver. For renderers that don't need complex passes you should not need them.</p>


<p>Notice you can do a <em>Set global to on</em> directly on your <em>RenderLayers</em> from this window (see the <a href="http://download.autodesk.com/global/docs/maya2013/en_us/index.html?url=files/Rendering_nodes_Render_Layer_render_attributes.htm,topicNumber=d30e656262" hreflang="en">Maya doc</a>).</p>


<p>Let's go now through the most interesting part. <img src="media/94b95129.popcorn.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/popcorn.gif" alt=":popcorn:" class="smiley" /></p>


<h4>Properties control</h4>


<p><img src="media/d4731f41.VRay_Arsenal_onglet_propertiesControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_onglet_propertiesControl.png" alt="VRay_Arsenal_onglet_propertiesControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_onglet_propertiesControl.png, janv. 2013"  height="607" width="473" /></p>


<p>This system is extremly fast to prepare your passes.</p>


<p>It's quite (quite) simple:</p>
<ul>
<li>You select an object/group, you do a <strong>Add</strong> and presto!</li>
<li>You want to remove an object/group? <strong>Remove</strong>!</li>
<li>You want to see objets having a particular property? <strong>Select</strong>!</li>
</ul>

<p>It's at once clear and also much faster than the "conventional" method aimed to manage these properties in grainy way on the groups/objects. Here, the system is reversed: You handle objects based on their property.</p>


<p>I find it much clearer. <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>Here is an quick explaination of the differentes <em>propertties</em>. For more details, refer to the <a href="http://arsenal.deex.info/wordpress/documentation/" hreflang="en">official documentation</a>.</p>


<h5>Black hole</h5>

<p>Objects having this <em>property</em> will not be shown in the render (their will be black) and their alpha will be empty.</p>


<p><strong>Receive shadow</strong>: <strong>Black hole</strong> objects having this <em>property</em> will recieve shadows and store it in their alpha (example: a ground).</p>


<h5>GI</h5>
<ul>
<li><strong>Generate off</strong>: Object with this <em>property</em> will not be used during the global illumination step (exmple: separate <strong>GI</strong> between characters and the set).</li>
<li><strong>Receive off</strong>: Object with this <em>property</em> will not recieve any indirect illumination.</li>
</ul>

<h5>Visibility</h5>
<ul>
<li><strong>Primary off</strong>:  Object with this <em>property</em> will not be visible in primary rays (their will be visible in reflections/refractions/GI).</li>
<li><strong>Reflection off</strong>:  Object with this <em>property</em> will not be visible in reflection rays (can be used to provide complex object to be reflected if it doesn't bring something to the final render).</li>
<li><strong>Refraction off</strong>:  Object with this <em>property</em> will not be visible in refraction rays.</li>
</ul>

<h5>Shadows</h5>

<p><strong>Cast off</strong>:  Les objets ayant cette <em>property</em> ne projetteront pas d'ombres.
<strong>Cast off</strong>:  Object with this <em>property</em> will not project shadows.</p>


<h4>On fly control</h4>


<p><img src="media/f7b118b5.VRay_Arsenal_002_onFlyControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_002_onFlyControl.png" alt="VRay_Arsenal_002_onFlyControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_002_onFlyControl.png, janv. 2013"  height="447" width="475" /></p>


<p>I'm not a big fan of terminologies used in this tab (even if it is VRay one). I'll try to be clear. <img src="media/edc4ddb7.gne.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/gne.gif" alt=":gne:" class="smiley" /></p>


<h5>Light select</h5>

<p>Here we will try to render passes by light or for every lights. This <em>passes</em> will be named as <em>nameOfYourLightShape_normal</em>,  <em>nameOfYourLightShape_diffuse</em>, etc...</p>
<ul>
<li><strong>Manual</strong>: If you want to render "contributions" for given lights only, it is here that you will.
<ul>
<li><strong>Normal</strong>: And this is where it lends quite confusing: Here, <em>Normal</em> is not the normal from a vector direction sense but normal within the meaning "classic". It is therefore a pass containing all the direct illumination of one light. That's all. Note that this is the terminology used in VRay...</li>
<li><strong>Diffuse</strong>: A direct lighting <em>Pass</em> of a light, with only diffuse informations.</li>
<li><strong>Raw</strong>: A <em>pass</em> that contain "raw" direct lighting informations of the light.</li>
<li><strong>Specular</strong>: A specular <em>pass</em> of the given light.</li>
</ul></li>
<li><strong>Automatic</strong>: Say that if you intend to render all the passes for all lights in the scene, go directly there. You can also combine <strong>Automatic</strong> mode for a specific pass with <strong>Manual</strong> mode for another specific pass.
<ul>
<li><strong>Specular</strong>: Render all specular <em>passes</em> for every light in the scene.</li>
<li><strong>Raw</strong>: Same as <strong>Specular</strong> but for the <strong>Raw</strong>.</li>
<li><strong>Diffuse</strong>: Same but for the <strong>Diffuse</strong> pass.</li>
<li><strong>Normal</strong>: Same but for the <strong>Normal</strong> pass.</li>
</ul></li>
</ul>
<h5>Arsenal settings</h5>






















<p>Here are my favorite options. Even if you can't really guess what they are at first. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>
<ul>
<li><strong>VrayMtl Lambert</strong>: Tick this case will transform to <em>VrayMtl Lambert</em>, on the fly and during the render, every materials of your scene, which is really usefull to check your global lighting. The point where this way differ from the <em>material override</em> with <em>RenderLayer</em>, it's materials will still have their displacement/bump/normal if their have one.</li>
<li><strong>Material ID on fly</strong>: Tick this case will generate <em>Material ID</em> on the fly, when the render start, using material names (without namespaces) as "seed". So, you will always have the same <em>Material ID</em> color as your material has the same name. Of course, you must have a <em>Material ID</em> in your <em>Render Element</em>. Note this feature is compatible with <em>VRayblendMaterial</em>: If you blend many materials (with mask) in a <em>VRayblendMaterial</em>, each material will have it own ID in the pass.</li>
<li><strong>Proxy Objects ID on fly</strong>: Same as <em>Material ID</em> but this time with VRay proxy.</li>
</ul>

<h4>Matte control</h4>


<p><img src="media/e2f5739c.VRay_Arsenal_003_matteControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_003_matteControl.png" alt="VRay_Arsenal_003_matteControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_003_matteControl.png, janv. 2013"  height="252" width="473" /></p>


<p>This one I also love it as it's simple! <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>Principe is to generate "mask" passes. You know? RGB mask:</p>


<p><img src="media/d40bd42d.VRay_Arsenal_013_passMask.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_013_passMask.png" alt="VRay_Arsenal_013_passMask.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_013_passMask.png, janv. 2013"  height="369" width="324" /></p>


<p>Roughly:</p>
<ul>
<li>You click <strong>Create new</strong>.</li>
<li>You give a name to you mask pass (<strong>Mask name</strong>). If you don't give a name to your mask pass, it will be removed. <img src="media/57cd5fc6.alkap.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/alkap.gif" alt=":mitraille:" class="smiley" /></li>
<li>You select a/some objects/groups.</li>
<li>You click <strong>add in red</strong> (or green/blue).</li>
<li>You render and you have you mask pass!</li>
<li>You can do this again for another pass.</li>
</ul>

<p>It's as simple I don't even know what to add! <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>Oh yes! This system bypasses a VRay limitation. Example:</p>
<ul>
<li>You have a object_A with ID 1.</li>
<li>A object_D with ID 2.</li>
<li>This two objects are in a group with ID 3.</li>
<li>Create a <em>Multi Matte</em> <em>Render Element</em> and set <em>Red object ID</em> to 3.</li>
<li>Render and look at your multimatte pass.</li>
</ul>
<p>It is black! Why? Because as VRay notice objects in group have an object ID, it doesn't show them in the pass.</p>


<p>With the Arsenal system, if you want to have a red group, it will be red!</p>


<h4>FastControl</h4>


<p><img src="media/d2845f4a.VRay_Arsenal_004_fastControl.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_004_fastControl.png" alt="VRay_Arsenal_004_fastControl.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_004_fastControl.png, janv. 2013"  height="183" width="474" /></p>


<p>This tab just gather main VRay options to quickly activate/desactivate them.</p>


<h3><em>Quality</em> tab <a name="quality"></a></h3>


<p><img src="media/ff7789fe.VRay_Arsenal_005_qualityTab.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_005_qualityTab.png" alt="VRay_Arsenal_005_qualityTab.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_005_qualityTab.png, janv. 2013"  height="773" width="492" /></p>
<center><i>A big slider which change of color! :D</i></center>



<p>Here we are in the area that peoples who are not really render guru should enjoy. And yet, you will see it can definitely pleased peoples who are used to change their settings manually. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>The first thing to do to activate all of this is to click on <strong>Save actual settings</strong> which will save your current settings, and on <strong>Optimize</strong> to setup different expressions. From this point, you can start to change the main slider to vary render quality.</p>


<h4>Preset Type</h4>


<p><em>Preset Type</em> are more about slider configuration than "preset". There is two <em>Preset Type</em>:</p>
<ul>
<li><em>deeX_interior</em></li>
<li><em>deeX_exterior</em></li>
</ul>
<p>This two choices represent a majority of lighting case.</p>


<p>Presets are simple texte file that can be found in:</p>
<pre class="bash bash">C:\Users\Narann\Documents\maya\deeXVRayArsenal\<span style="color: #000000;">2013</span>\win64\scripts\presets</pre>

<p>This files, with very simple syntax, are used to drive ranges (min and max) of VRay attributes which will be then modified by your slider. If I don't talk nonsense, the relationship between the slider and settings it drive is <a href="https://en.wikipedia.org/wiki/Logarithm" hreflang="en">logarithmic</a> to avoid settings burn render times when you start to increase too much the slider. <img src="media/00461682.1420.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>


<p>If the opportunity to create it own presets will probably doesn't interest occasional lighters, being able to set these <em>min</em> and <em>max</em> parameters manually can be very interesting for VRay gurus having their little habits. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></p>


<p>Moreover, it would have been great to see this tool independent of VRay to drive, for example, Mental Ray. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


<blockquote><p>If you want to prevent Arsenal modifications on a specific attribute, just lock it.</p></blockquote>


<h4>Offset quality</h4>


<p>Here we have a very good idea. Principe is to apply an offset to the slider for some parameters.</p>


<p>For example, my slider is suppose to be <em>50</em>. I think sampling is a bit sensitive and increases the rendering time too quickly. However, I am satisfied with the rest... So, I just check the <strong>Image sampler</strong> then type <em>-10</em> for the settings of the sampler applies as if my overall slider was <em>40</em>! Brillant! <img src="media/d52870c6.youplaBoum.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/youplaBoum.gif" alt=":youplaBoum:" class="smiley" /></p>


<h4>Optimize material(s)</h4>


<p>Another interesting idea: You determine two extrem subdivision values (sampling), click <strong>Optimize material(s)</strong> button and Arsenal will determine the value to use based on <strong>Glossiness</strong> value of the material. More it's gloss, more you need samples.</p>


<p>Notice the checkbox right to <strong>LayerMode</strong>. If you check it before clicking <strong>Optimize material(s)</strong> button and you are in a <em>RenderLayer</em> (other than  <em>masterLayer</em>) attributes will changed only on the current <em>RenderLayer</em>.</p>

<h4>Optimize light(s)</h4>


<p>I'm not sure this button is very useful. For now it only set every VRayLights Subdiv parameter to 5...</p>


<h3><em>ToolBox</em> tab <a name="toolbox"></a></h3>


<p><img src="media/47fb251f.VRay_Arsenal_006_toolBoxTab.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_006_toolBoxTab.png" alt="VRay_Arsenal_006_toolBoxTab.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_006_toolBoxTab.png, janv. 2013"  height="707" width="494" /></p>


<p>Here you will find small very specific tools.</p>


<h4>Proxy</h4>

<p><a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm" hreflang="en">VRayProxy</a> are a marvel. We used them on <a href="http://www.fevrierdorian.com/blog/post/2013/02/07/url=http://www.imdb.com/title/tt1701210/" title="url=http://www.imdb.com/title/tt1701210/">url=http://www.imdb.com/title/tt170...</a>Day Of The Falcon<a href="http://www.fevrierdorian.com/url" title="/url">/url</a> to make horse animation cycles shifting speed.</p>


<h5>Multi proxy importer</h5>

<p>This button allows you to import multiple VRayProxy because, as surprising as it may seem, it is not possible to do this in standard... You need to import VRayProxy one by one...</p>


<h5>Shader auto connect</h5>

<p>When you export a VRayProxy, the "assignation slots" are created. Principle is to store, inside the proxy, shader assignations for reassign your shaders later.</p>


<p>Once VRayProxy reimported into your scene, you can apply a <a href="http://www.spot3d.com/vray/help/maya/150R1/vraymeshmtl_params.htm" hreflang="en">VRayMeshMaterial</a> (FYI, it's already created when you import). This material will show different slots assignments for your proxy to connect your own shaders.</p>


<p><strong>Shader auto connect</strong> button can automatically reconnect shaders based on their names, which avoids having to do it yourself. On proxy with tens or hundreds of assignments, it is rather convenient...</p>


<h5>Ignore namespace</h5>

<p>This box allows you to ignore shader namespaces of your scene when reassigning to the proxies. In principle, this allows you to have these shaders in external references (with a namespace) without have problems for reconnect using their names.</p>


<h4>ID</h4>

<p>Once again, here we have tools to quickly assign IDs to materials and objects.</p>


<p>Goal is then to release this IDs as passes to give to your compositing friends.</p>


<h4>Material ID</h4>


<p><img src="media/ec88b911.VRay_Arsenal_008_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_008_materialID.png" alt="VRay_Arsenal_008_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_008_materialID.png, janv. 2013"  height="431" width="383" /></p>

<ul>
<li><strong>Add on</strong>: Used to apply <em>Material ID</em> attributes to selected materials/all materials/all shading engine.</li>
<li><strong>Set on</strong>: Apply a unique ID to <em>Material ID</em> attributes for the selected materials/all materials/all shading engine. This number is generated randomly using the material name. This method has double side: If you change the name of the material them you click again on <em>Set on</em>, it ID color will change likewise. Notice <strong>Material ID on fly</strong> checkbox from <em>Pass</em>/<em>On fly control</em> do the same thing directly on the fly! :)</li>
<li><strong>Remove on</strong>: Supprime les attributs de <em>Material ID</em> des materials sélectionnés/tous les materials/tous les shading engine.</li>
<li><strong>Remove on</strong>: Remove <em>Material ID</em> attributes from selected materials/all materials/all shading engine.</li>
</ul>

<p><img src="media/67fcbd1a.VRay_Arsenal_014_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_014_materialID.png" alt="VRay_Arsenal_014_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_014_materialID.png, janv. 2013"  height="115" width="528" /></p>


<p>Last point, to make this work, don't forget to create a <em>Material ID</em> pass (<em>Render Element</em>):</p>


<p><img src="media/a3a3b1a5.VRay_Arsenal_007_materialID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_007_materialID.png" alt="VRay_Arsenal_007_materialID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_007_materialID.png, janv. 2013"  height="568" width="437" /></p>


<h4>Object ID</h4>

<p>Same as <em>Material ID</em> but at the objects level.</p>


<p><img src="media/95efe5f1.VRay_Arsenal_015_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_015_objectID.png" alt="VRay_Arsenal_015_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_015_objectID.png, janv. 2013"  height="84" width="451" /></p>


<p><img src="media/47e12d57.VRay_Arsenal_010_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_010_objectID.png" alt="VRay_Arsenal_010_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_010_objectID.png, janv. 2013"  height="621" width="570" /></p>
<center><i>Notice difference with the ''Material ID'' pass.</i></center>


<p>Each object will have a differente id.</p>


<p>Once again, don't forget to create <em>Object ID</em> <em>Render Element</em>:</p>


<p><img src="media/a0f89467.VRay_Arsenal_009_objectID.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_01_15_VRay_Arsenal/VRay_Arsenal_009_objectID.png" alt="VRay_Arsenal_009_objectID.png" style="display:block; margin:0 auto;" title="VRay_Arsenal_009_objectID.png, janv. 2013"  height="549" width="429" /></p>


<h4>Material control</h4>

<p>This part allows you to apply some key values on selected/all materials in one click.</p>
<ul>
<li>Reflection/Refraction Subdivs</li>
<li>Reflection/Refraction Interpolation</li>
<li>Reflection/Refraction Max depth</li>
</ul>

<p>A <strong>Trace</strong> option (Reflection/Refraction) to completly activate/desactivate raytracing would be interesting here. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<h4>Lights control</h4>

<p>It can't be easier: Apply a <strong>Shadow subdivs</strong> value to selected/all lights of the scene in one click.</p>


<h3>Techniquement, comment ça marche?
How it work technically?</h3>

<p>Hahaha! The particularity of this tool is to not change your scene when you generate passes (Except Maya <em>RenderLayers</em> of course), when you do some "On the fly" stuff or even Matte.</p>


<p>But then? How is it doing? <img src="media/9346b45f.confused0028.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/confused0028.gif" alt=":gne2:" class="smiley" /></p>


<p>Well, it uses a feature of VRay I'll dream of seeing widespread throughout render engines as it increase pipeline possibilities: The Python API <a href="http://www.spot3d.com/vray/help/maya/150R1/render_scene_access.htm" hreflang="en">VRay Scene Access</a>.</p>


<p>I quote the documentation as it's very clear:</p>

<blockquote><p>The V-Ray scene access python API allows you to modify the V-Ray scene after it is translated by the V-Ray for Maya translator, and before it is rendered and/or exported to a .vrscene file.
The scene access API allows you to expand the V-Ray for Maya translator by providing custom translation for constructs that are not recognized by V-Ray, or for modifying the scene before rendering without changing the original Maya scene.</p></blockquote>

<p>Boum! Chaos Group guys are genius! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>Roughly, it allow you to drive the renderer before (during?) the render. So we can imagine crazy stuff like generate scenes directly in VRay, on the fly, without using heavy vrscene file. For those who have worked with Renderman, it means no more generation of heavy RIBs you use only once. Here, you can control VRay using Python!</p>


<p>I asked for a similar feature on <a href="http://forum.nvidia-arc.com/showthread.php?8097-Python-to-controle-mental-ray" hreflang="en">Nvidia ARC forum</a> (formerly Mental Image) as I thought it was a great idea but I'm not sure it changes much. <img src="media/13e2620a.triste.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/triste.gif" alt=":triste:" class="smiley" /></p>


<p>So, Damien's tool uses it, and that's what allows him to keep a clean Maya scene and be able to act directly at VRay level, before rendering.</p>


<h3>Conclusion</h3>

<p>For having test the thing thoroughly I can assure you it worth every penny (69€! :bravo:).</p>

<ul>
<li>Time saved preparing passes is terrible and you don't have to go through all the VRay menus.</li>
<li>The ability to control objects according their <em>properties</em> is quite natural.</li>
<li>RGB Mattes management is also easy.</li>
<li>On the fly Material/Object ID working in few clicks... You have no more excuse for not using them.</li>
<li>On the fly VRayMtlLambert deserves a section all by itself as it can be practical.</li>
<li>Quality slider preset and offsets system can go far.</li>
<li>Deex will continue to add stuff.</li>
</ul>

<p>What is missing:</p>
<ul>
<li>Ability to export you "pass set" in a text file for later import (planned!).</li>
<li>More <em>On the fly</em> options (I'm a big fan of this!)</li>
<li>A Python API as easy to use than this buttons. Like <em>arsenal.pass.propertiesControl.blackHole.add("myObject")</em>. But except me, I'm not sure any one will find this useful... <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></li>
</ul>

<p>OK, I sell <del>a little</del> completely the thing but yes: It's worth it! <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<p>Beyond the fact that I invite you to jump into this tool, I hope that, if you already have it, this presentation/tutorial will allow you to go further! :)</p>


<p>See you!</p>

<center><i><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></i></center>


feed_id: urn:md5:f058c64e76d2cee538cad90e272c3b63
title: VRay User Attributes (English Translation)
uri: VRay-User-Attributes-(English-Translation)
url: http://www.fevrierdorian.com/blog/post/2013/02/17/VRay-User-Attributes-English-Translation
content:
<p><img src="media/8980c15c.user_attr_vray_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_tn.png" alt="user_attr_vray_tn.png" style="float:left; margin: 0 1em 1em 0;" title="user_attr_vray_tn.png, fév. 2013"  height="150" width="150" />Here is a tutorial I wanted to do for quite some time. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>For a long time now, VRay can use per object attributes to control some values. It can go far but often, this values are used in shaders. The general idea is to apply a single and unique shader to a big number of object, but that each object had some "special" attributes with value in them that will be applied to the shader. If you remember, <a href="http://www.fevrierdorian.com/blog/post/2011/04/16/Mental-ray-3.9-Les-User-Data-Shaders-ou-Shader-Package">I presented (french)</a> a similar feature for mental ray (User Data).</p>


<p>But before doing that, this tutorial will explain how to export/import vrmesh then redo shader assignments directly within the vrmesh! As you can see, we have a lot to do! <img src="media/2e1ef912.bravo.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bravo.gif" alt=":bravo:" class="smiley" /></p>    <h3>vrmeshs (aka proxy)</h3>


<h4>What?</h4>

<p>Briefly: You know the principle of texture tiling? (No? <a href="http://www.fevrierdorian.com/blog/post/2009/01/14/Le-mappage-en-m%C3%A9moire-des-textures-dans-Mental-Ray-expliqu%C3%A9-%28Memory-mapped-textures%29.">Hop! Hop! Hop! (french)</a> :Nannan: ) Well, principle is the same, but for geometry: Vrmesh are "ready to raycast" meshes. Geometry is stored in a grid (voxel).</p>


<p>So you only load necessary "box" to render. Your vrmesh can be huge, only the elements necessary for the calculation will be loaded/unloaded on the fly. As well as tiled maps, this increase your disk IO but gives you great flexibility.</p>


<p>Don't be afraid because of the size, vrmesh are done for! :D</p>


<h4>Practice</h4>

<p>Let's do simple, here is a scene with to 24 frame animation cycles:</p>


<p><a href="media/f9eea4c8.user_attr_vray_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_001.png" title="user_attr_vray_001.png"><img src="media/3fd074a7..user_attr_vray_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/.user_attr_vray_001_m.jpg" alt="user_attr_vray_001.png" style="display:block; margin:0 auto;" title="user_attr_vray_001.png, fév. 2013"  height="346" width="560" /></a></p>
<center><i>You can't see it but they are walking! <img src="media/38d91e93.onSeFendLaPoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/onSeFendLaPoire.gif" alt=":onSeFendLaPoire:" class="smiley" /></i></center>



<p>At this step, principle is to assign, to each "shader group", an ordinary shader (lambert is fine). Name is the importante part because it will be stored in the vrmesh with it assigned faces:</p>


<p><img src="media/bb205d9f.user_attr_vray_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_002.png" alt="user_attr_vray_002.png" style="display:block; margin:0 auto;" title="user_attr_vray_002.png, fév. 2013"  height="159" width="549" /></p>
<center><i>"lambert5" should have been "arms" but I've completely missed it. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></i></center>



<p>Even though this is not required, try to keep coherence in names between all your objects. So, if you have characters crowd to export. Assign them all shaders "arm", "corp", "head", "Hair", "tenuHaut", "tenuBas", etc ... With a bit of script, you will save time later.</p>


<p>Select mesh group you want to export:</p>


<p><img src="media/5651de61.user_attr_vray_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_003.png" alt="user_attr_vray_003.png" style="display:block; margin:0 auto;" title="user_attr_vray_003.png, fév. 2013"  height="92" width="253" /></p>


<p>Then go in <em>Create/V-Ray/Create proxy</em>:</p>


<p><img src="media/c0e670bb.user_attr_vray_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_004.png" alt="user_attr_vray_004.png" style="display:block; margin:0 auto;" title="user_attr_vray_004.png, fév. 2013"  height="489" width="420" /></p>


<p>You will have a <del>horrible</del> quite sober interface:</p>


<p><img src="media/804e0241.user_attr_vray_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_005.png" alt="user_attr_vray_005.png" style="display:block; margin:0 auto;" title="user_attr_vray_005.png, fév. 2013"  height="582" width="576" /></p>


<p>Select <em>Export animation</em>. If your mesh is animated and you plan to use motion blur on your final render, select <em>Export velocity</em>. The two values will create the interval to calculate direction vectors to be stored in the vertices. VRay will calculate the motion blur geometry from this informations. Be careful on this interval. You can expect some (bad) surprises. If you don't go with motion blur, deselect this option. This will store less information in the geometry.</p>


<p>In my case I also select <em>Use playback range</em> but advise accordingly to your case. <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>With <em>Face in preview</em>, Chaos Group provide us what look like a small and trivial feature but very interesting in practice: The idea is to save <em>n</em> face indices that will be displayed in the viewport later.</p>


<p>When doing proxy, mainly to lighten a scene, we often have to manage large bouding box. Depending on the pipeline, you may even have a proxy made by another department. Here, Chaos Group guys had a very interesting reflection: "Why not make a cool proxy corresponding to the real geometry?". The bet is entirely successful, you will see that later. :)</p>


<p>If you want to import directly the newly created proxy, you can select <em>Automatically create proxies</em>.</p>


<p>For the rest, I strongly advise you to read the <a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm#export_gui" hreflang="en">documentation</a>.</p>


<p>Once that's done, click on <em>Create Proxy</em>!</p>


<p>Proceed this steps for every characters you want to export.</p>

<center><img src="media/f0159d47.longBar.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/longBar.png" alt=":longBar:" class="smiley" /></center>



<p>To import all this:</p>


<p><img src="media/b1e4c606.user_attr_vray_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_006.png" alt="user_attr_vray_006.png" style="display:block; margin:0 auto;" title="user_attr_vray_006.png, fév. 2013"  height="109" width="431" /></p>


<p><img src="media/ce1c29ea.user_attr_vray_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_007.png" alt="user_attr_vray_007.png" style="display:block; margin:0 auto;" title="user_attr_vray_007.png, fév. 2013"  height="201" width="333" /></p>


<p>Tadaaaa:</p>


<p><img src="media/f12b8b3f.user_attr_vray_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_008.png" alt="user_attr_vray_008.png" style="display:block; margin:0 auto;" title="user_attr_vray_008.png, fév. 2013"  height="398" width="349" /></p>


<p><img src="media/d62ed0ad.user_attr_vray_009.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_009.png" alt="user_attr_vray_009.png" style="display:block; margin:0 auto;" title="user_attr_vray_009.png, fév. 2013"  height="446" width="538" /></p>


<p>And now our 100 faces per object. Slap it right? <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<p>Seriously, you can import hundreds of them, your viewport does not flinch. In addition, these proxies correspond to the final model. This approximation should less bother you than a low model or worse, a bounding box.</p>


<p>Now let's look at this options:</p>


<p><img src="media/7b7c45eb.user_attr_vray_010.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_010.png" alt="user_attr_vray_010.png" style="display:block; margin:0 auto;" title="user_attr_vray_010.png, fév. 2013"  height="711" width="522" /></p>


<p>If we select <em>Bounding box</em>:</p>


<p><img src="media/ddbecb75.user_attr_vray_011.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_011.png" alt="user_attr_vray_011.png" style="display:block; margin:0 auto;" title="user_attr_vray_011.png, fév. 2013"  height="389" width="418" /></p>
<center><i>For nostalgic. <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></i></center>



<p>If you are not satisfied with the approximation, Chaos Group has got you covered: <em>Show whole mesh</em>:</p>


<p><img src="media/f5a6ed79.user_attr_vray_012.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_012.png" alt="user_attr_vray_012.png" style="display:block; margin:0 auto;" title="user_attr_vray_012.png, fév. 2013"  height="309" width="257" /></p>


<p>Other options are more specific. I will not go into detail. If you're interested: <a href="http://www.spot3d.com/vray/help/maya/150R1/vrayproxy_params.htm#parameters" hreflang="en"><img src="media/9ca8344d.sign0012.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sign0012.gif" alt=":RTFM:" class="smiley" /></a>.</p>


<p>Just notice animation speed is customisable (anim is possible too! <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /> ) and that in our case (and most cases) it's <em> Loop</em>.</p>


<p>Go tabs on the right. VRay has already connected a shader and...</p>


<p><img src="media/8a6a00fe.user_attr_vray_013.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_013.png" alt="user_attr_vray_013.png" style="display:block; margin:0 auto;" title="user_attr_vray_013.png, fév. 2013"  height="419" width="520" /></p>


<p>Oh miracle! Our slots are there! <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>You will just have to drag and drop shaders to use.</p>


<p>Note that trying too hard to be nice, VRay create a shader for each imported vrmesh. But if you import twice the same vrmesh, you will have two similar shaders. Don't hesitate to remove one and apply a single shader for each vrmesh "source".</p>


<p>Now let's get serious! <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /></p>


<h3>User Attributes</h3>


<p>Select the <em>transform</em> node of one vrmesh you have and add <em>User attributes</em>:</p>


<p><img src="media/77930387.user_attr_vray_014.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_014.png" alt="user_attr_vray_014.png" style="display:block; margin:0 auto;" title="user_attr_vray_014.png, fév. 2013"  height="171" width="439" /></p>


<p>In these <em>User attributes</em> (lost at the bottom of your <em>Attribute Editor</em>) add the following:</p>
<pre class="bash bash"><span style="color: #007800;">casquetteColor</span>=<span style="color: #000000;">1</span>,<span style="color: #000000;">1</span>,<span style="color: #000000;">0</span>;</pre>


<p><img src="media/74bd2d43.user_attr_vray_015.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_015.png" alt="user_attr_vray_015.png" style="display:block; margin:0 auto;" title="user_attr_vray_015.png, fév. 2013"  height="82" width="522" /></p>


<p>There, you should begin to understand. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<p>On the second, create a similar value:</p>


<p><img src="media/3a00e9db.user_attr_vray_016.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_016.png" alt="user_attr_vray_016.png" style="display:block; margin:0 auto;" title="user_attr_vray_016.png, fév. 2013"  height="77" width="517" /></p>


<p>Now create a shader, a <em>blinn</em> in my example (Yes, I know it's bad). Give it a clear name (it will quickly become a mess in your connections so it's up to you <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /> ):</p>


<p><img src="media/b821088f.user_attr_vray_017.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_017.png" alt="user_attr_vray_017.png" style="display:block; margin:0 auto;" title="user_attr_vray_017.png, fév. 2013"  height="119" width="224" /></p>


<p>Add a <em>VRayUserColor</em> node then enter your attribute value:</p>


<p><img src="media/8ab6097f.user_attr_vray_018.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_018.png" alt="user_attr_vray_018.png" style="display:block; margin:0 auto;" title="user_attr_vray_018.png, fév. 2013"  height="134" width="394" /></p>


<p><img src="media/eb433448.user_attr_vray_019.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_019.png" alt="user_attr_vray_019.png" style="display:block; margin:0 auto;" title="user_attr_vray_019.png, fév. 2013"  height="289" width="517" /></p>


<p>Set the default color you want. It will be the color used if <em>User Attribute</em> is not present/valid.</p>


<p>You have some syntax examples just below the node (another good idea).</p>


<p>Connect this node to the <em>color</em> attribute of your shader (it's a shame the <em>default color</em> is not used in the hypershade, it would be a nicer than a black hole).</p>


<p><img src="media/efa861d7.user_attr_vray_020.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_020.png" alt="user_attr_vray_020.png" style="display:block; margin:0 auto;" title="user_attr_vray_020.png, fév. 2013"  height="139" width="395" /></p>


<p>Connect your shader to both <em>VRayMeshMaterial</em>, in the "casquette" slot:</p>


<p><img src="media/71f215c6.user_attr_vray_022.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_022.png" alt="user_attr_vray_022.png" style="display:block; margin:0 auto;" title="user_attr_vray_022.png, fév. 2013"  height="333" width="515" /></p>


<p><img src="media/47d71b1c.user_attr_vray_021.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_021.png" alt="user_attr_vray_021.png" style="display:block; margin:0 auto;" title="user_attr_vray_021.png, fév. 2013"  height="223" width="367" /></p>


<p>Then render:</p>


<p><img src="media/2c4c40ac.user_attr_vray_023.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_023.png" alt="user_attr_vray_023.png" style="display:block; margin:0 auto;" title="user_attr_vray_023.png, fév. 2013"  height="433" width="597" /></p>
<center><i><a href="http://www.youtube.com/watch?v=8RLPG88u3lM">Victory song</a> (to listen with <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /> )</i></center>



<p>Do the same for all shaders (except "corp" that we keep for after <img src="media/990690f6.whistle2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /> ):</p>


<p><img src="media/ea76eeba.user_attr_vray_024.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_024.png" alt="user_attr_vray_024.png" style="display:block; margin:0 auto;" title="user_attr_vray_024.png, fév. 2013"  height="144" width="502" /></p>


<p><img src="media/d4336934.user_attr_vray_025.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_025.png" alt="user_attr_vray_025.png" style="display:block; margin:0 auto;" title="user_attr_vray_025.png, fév. 2013"  height="426" width="564" /></p>


<p>Well, those are for colors. You can do the same with <em>VRayUserScalar</em> and floatting point value.</p>


<p>Now we start the body ("corp"):</p>


<p><img src="media/9e4c8911.user_attr_vray_026.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_026.png" alt="user_attr_vray_026.png" style="display:block; margin:0 auto;" title="user_attr_vray_026.png, fév. 2013"  height="189" width="357" /></p>
<center><i>Just a file node.</i></center>



<p>Supposing you have four textures:</p>
<ul>
<li>checker_default.png</li>
<li>checker_four.png</li>
<li>checker_etc.png</li>
</ul>


<p>The only variable in your texture is located at the end (and, why not, in the path).</p>


<p>Put this in your file path:</p>


<p><img src="media/1f26f745.user_attr_vray_027.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_027.png" alt="user_attr_vray_027.png" style="display:block; margin:0 auto;" title="user_attr_vray_027.png, fév. 2013"  height="64" width="354" /></p>


<p>Then apply this variable to your different <em>User Attributes</em>:</p>


<p><img src="media/22fdd4e5.user_attr_vray_028.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_028.png" alt="user_attr_vray_028.png" style="display:block; margin:0 auto;" title="user_attr_vray_028.png, fév. 2013"  height="61" width="506" /></p>


<p><img src="media/4409df8e.user_attr_vray_029.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_029.png" alt="user_attr_vray_029.png" style="display:block; margin:0 auto;" title="user_attr_vray_029.png, fév. 2013"  height="69" width="518" /></p>


<p>Render!</p>


<p><img src="media/1368d6e0.user_attr_vray_030.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_030.png" alt="user_attr_vray_030.png" style="display:block; margin:0 auto;" title="user_attr_vray_030.png, fév. 2013"  height="428" width="567" /></p>
<center><i><a href="http://www.youtube.com/watch?v=8RLPG88u3lM">Once again?</a></i></center>



<p>And if we have no limit:
<img src="media/5e16da71.user_attr_vray_031.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_031.png" alt="user_attr_vray_031.png" style="display:block; margin:0 auto;" title="user_attr_vray_031.png, fév. 2013"  height="520" width="681" /></p>


<p><img src="media/0869791c.user_attr_vray_032.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_02_17_Les_User_Attributes_de_VRay/user_attr_vray_032.png" alt="user_attr_vray_032.png" style="display:block; margin:0 auto;" title="user_attr_vray_032.png, fév. 2013"  height="417" width="579" /></p>


<p>If you often do crowds, you should seriously consider this solution.</p>


<h3>Notice</h3>

<p>I think, as mental ray <em>User Data</em>, it's a bit cumbersome to deal with. But if you or your colleague is scripter, it is not too difficult to put it up on a production.</p>


<p>I breath the poppy it may (this is unconfirmed so take with a grain of salt) Deex (whom I thank for making me discover VRay) integrates a simple way to deal with them in <a href="http://arsenal.deex.info/" hreflang="en">Arsenal</a> (but dont be too hasty <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /> ).</p>


<h3>Conclusion</h3>


<p>I hope this tutorial will help you in your productions.</p>


<p>See you!</p>


<p>Dorian</p>

<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:92070cf095ad4a8188940b424f02707b
title: Geometry voxelization using Maya Python API (English Translation)
uri: Geometry-voxelization-using-Maya-Python-API-(English-Translation)
url: http://www.fevrierdorian.com/blog/post/2013/03/16/Geometry-voxelization-using-Maya-Python-API
content:
<p><img src="media/4de9ae20.voxel_vray_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_vray_tn.png" alt="voxel_vray_tn.png" style="float:left; margin: 0 1em 1em 0;" title="voxel_vray_tn.png, mar. 2013"  height="150" width="150" />Yet another little script only aimed to use the Maya API. <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>The idea is to reproduce the voxel geometric effect you may have <a href="http://www.bilderzucht.de/blog/3d-pixel-voxel/" hreflang="en">already seen</a>.</p>


<p>Nothing too serious and it probably already exists and maybe faster. To be honest, I did not even look. The goal is again to use the API. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>    <h3>Principe</h3>

<p>Before we begin, know that this problem is a textbook case. There are a thousands of ways to solve it and each method has these pro and con. <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>The method chosen here is simple: For each vertex of the geometry, we find the position "in cube unit" and generates a cube.</p>


<p>The only dificulty with this implementation is, once the vertex position recovered, to know where must be the center of the cube. <img src="media/fb7f2cd8.seSentCon.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/seSentCon.gif" alt=":seSentCon:" class="smiley" /></p>


<p><a href="media/95bae7a5.voxel_vray.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_vray.png" title="voxel_vray.png"><img src="media/327e2389..voxel_vray_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/.voxel_vray_m.jpg" alt="voxel_vray.png" style="display:block; margin:0 auto;" title="voxel_vray.png, mar. 2013"  height="420" width="560" /></a></p>


<h3>The code</h3>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">OpenMaya</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">OpenMaya</span>
&nbsp;
voxelStep = <span style="color: #ff4500;">1.0</span>
&nbsp;
sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span>
&nbsp;
inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span>
pointArray = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
inMesh.<span style="color: black;">getPoints</span><span style="color: black;">&#40;</span>pointArray, <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span><span style="color: black;">&#41;</span>
&nbsp;
grpName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>pointArray.<span style="color: black;">length</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> :
&nbsp;
	cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
	cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
	cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
&nbsp;
	cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
		<span style="color: #ff7700;font-weight:bold;">continue</span>
	<span style="color: #ff7700;font-weight:bold;">else</span> :
		voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span>
&nbsp;
	myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpName<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span></pre>


<h3>Explainations</h3>

<pre class="python python">sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Basically, a <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_selection_list.html,topicNumber=cpp_ref_class_m_selection_list_html" hreflang="en">MSelectionList</a> is a list of MObject.</p>


<p>I never really understood what the term "selection" meant in this context as it actually does not "select" anything. <img src="media/f566509c.bete.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bete.gif" alt=":bete:" class="smiley" /></p>


<p>The particularity of a <em>MSelectionList</em> is to retrieve the <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MObject</a> of a Maya node from its name, what we will do later.</p>

<pre class="python python">dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>It is always difficult to explain to begginers what is a DAG and a DAG path. <img src="media/edc4ddb7.gne.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/gne.gif" alt=":gne:" class="smiley" /></p>


<p>As a large summary:</p>
<ul>
<li>DAG: This is the Maya "hierarchy" (parent/child).</li>
<li>DAG path: This is the "path" of a node through the hierarchy (and thus, having all these transformations).</li>
</ul>

<p>Many Maya API functions require DAG path to work.</p>


<p>For example, you can't retrieve world space coordinates of shape node's vertices if you don't know the path by which you get there. Two instances have only one shape node but it is indeed two different DAG path and world space coordinates of one vertex can have two possible values depending "from where we go".</p>

<pre class="python python">sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span></pre>

<p>We add the Maya object "pSphere1" in the <em>MSelectionList</em> and we retrieve its DAG path (zero is the index in the list).</p>


<p>So we've "converted" "pSphere1" (that doesn't mean anything in Maya API) in true <em>MObject</em>.</p>

<pre class="python python">inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span></pre>

<p>By default, all what you get from the API are <em>MObjects</em>. In general, we check the <em>MObject</em> type using <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MObject.apiType()</a> or <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_dag_node.html,topicNumber=cpp_ref_class_m_fn_dag_node_html" hreflang="en">MObject.hasFn()</a>.</p>


<p>But here we assume the user provide a mesh. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<p>The <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MFnMesh</a> class allow you to deal with a "true" programming object from which we will be able to get informations. It's a <em>function set</em>.</p>


<p>I invite you to read <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">the documentation</a> to understand the how and why of <em>function sets</em>.</p>


<p>So we have a _inMesh_ that we will use to retrieve mesh's vertices.</p>

<pre class="python python">pointArray = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
inMesh.<span style="color: black;">getPoints</span><span style="color: black;">&#40;</span>pointArray, <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span><span style="color: black;">&#41;</span></pre>

<p>The first line creates a <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html" hreflang="en">MPointArray</a> to store our mesh vertices positions.</p>


<p>And the second line fills the array with vertices coordinates world space (position relative to the center of the scene, not the center of the object itself).</p>

<pre class="python python">grpName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre>

<p>Here we only create an empty group that will store cubes we will create later. It is just more convenient to delete a group with everything in it than select all the cubes manually. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>

<pre class="python python">voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>We create a list which will be used to store identifiers (or keys) of areas where cubes have already been generated. I return below.</p>

<pre class="python python">cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep</pre>

<p>And here are the small lines that does everything. You'll see, it is very simple.</p>


<p>So, what are we trying to do with this?</p>


<p>Let's suppose the desired size cubes is 2.0.</p>


<p>It comes across a vertex set with a X value of 10.2. Of course, we will not put our cube in the center of the vertex (10.2). We would not get the desired effect at all. <img src="media/f1f7d503.nannan.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nannan.gif" alt=":nannan:" class="smiley" /></p>


<p>We need the exact position of the cube. We must "count the number of cube."</p>


<p>How do I know what is the 10.2 distance in cube size 2.0? By simply: 10.2/2.0 = 5.1.</p>


<p>As we cann't have 5.1 cubes, we round using the round() function. In the case of round(5.1), we have 5 (5.7 would give 6).</p>


<p>So now we know that if we create a cube of size 2.0, you should move it 5 times its size to make it emcompass the vertex. We then multiply the rounded value (5) by the size of a cube (2) to obtain a new position: The position of the cube, not wedged on the vertex but keyed to the voxel grid.</p>


<p>And voila! Now you know!  <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>We did this for the three axes.</p>

<pre class="python python">cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
	<span style="color: #ff7700;font-weight:bold;">continue</span>
<span style="color: #ff7700;font-weight:bold;">else</span> :
	voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span></pre>

<p>Here, we create a "hash" (a string) of the cube position and we store it in a list. That way, if we fall on a vertex which, once rounded, is in the same places than an already existing cube, it does not create it (no duplicates! :hehe:).</p>


<p>Although method seems <del>a little</del> very odd (convert vertex positions to string), I felt it was the easiest way to manage a unknown sized grid without too many lines of code.</p>


<p>But if you have another one short and quick to implement, don't hesitate to share. : D</p>

<pre class="python python">myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpName<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span></pre>

<p>After all of this, everything is simple:</p>
<ul>
<li>We create our cube from it desired size (2.0).</li>
<li>We applied a bevel on it because it looks good. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></li>
<li>We parent it to the group.</li>
<li>We place it to the calculated position.</li>
</ul>

<p>And start again for another vertex!</p>


<p><img src="media/07f86864.voxel_maya_api_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_maya_api_001.png" alt="voxel_maya_api_001.png" style="display:block; margin:0 auto;" title="voxel_maya_api_001.png, mar. 2013"  height="387" width="382" /></p>


<p><img src="media/529aa798.voxel_maya_api_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_maya_api_002.png" alt="voxel_maya_api_002.png" style="display:block; margin:0 auto;" title="voxel_maya_api_002.png, mar. 2013"  height="598" width="616" /></p>


<p>Again: This script is not optimized at all, it is a rough prototype for training purpose, not a production tool. Just give it a heavy mesh to realize. <img src="media/7c977e83.mechantCrash.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mechantCrash.gif" alt=":mechantCrash:" class="smiley" /></p>


<h3>Conclusion</h3>


<p>This express ticket is over.</p>


<p>As you see, principle is quite simple. Well, once again we could have done this differently and probably more effective (try with <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=a5b3f852a00f3dc096c136cbe04057733" hreflang="en">MFnMesh.allIntersections</a>).</p>


<p>Personally, playing with the Maya API always amuses me so much. :)</p>


<p>See you!</p>

<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>



<h3>EDIT 2013/03/17</h3>

<p>I couldn't resist to try <a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=aa6c4717b168258664d399fb92e2cdcee" hreflang="en">MFnMesh.allIntersections()</a>. There is a well more optimized version (with acceleration structure <a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=aa6c4717b168258664d399fb92e2cdcee" hreflang="en">MFnMesh.autoUniformGridParams()</a>).</p>


<p>The main difference between the previous one and this one is we don't go through each vertex anymore but we project rays through a grid instead (X, Y, Z).</p>


<p>The second difference is the code work on a animated mesh (1 to 24 here). You should test, the effect is cool. :)</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">OpenMaya</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">OpenMaya</span>
&nbsp;
startFrame = <span style="color: #ff4500;">1</span>
endFrame = <span style="color: #ff4500;">24</span>
&nbsp;
voxelSize = <span style="color: #ff4500;">20.0</span>
voxelStep = <span style="color: #ff4500;">0.5</span>
&nbsp;
sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span>
&nbsp;
inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span>
&nbsp;
grpReelNames = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> curTime <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>startFrame, endFrame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> :
	grpName = <span style="color: #483d8b;">&quot;frameGrp_%s&quot;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>curTime<span style="color: black;">&#41;</span>
	grpReelName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>name=grpName, empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">0.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime-<span style="color: #ff4500;">0.1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">1.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">0.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	grpReelNames<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span> = grpReelName
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> grpReelName <span style="color: #ff7700;font-weight:bold;">in</span> grpReelNames :
	<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">cmds</span>.<span style="color: black;">objExists</span><span style="color: black;">&#40;</span>grpReelName<span style="color: black;">&#41;</span> :
		<span style="color: #dc143c;">cmds</span>.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>grpReelName<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> curTime <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>startFrame, endFrame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> :
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span>curTime<span style="color: black;">&#41;</span>
&nbsp;
	voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;">#I use while just because xrange with floats is impossible</span>
	i = -voxelSize/<span style="color: #ff4500;">2.0</span>
	<span style="color: #ff7700;font-weight:bold;">while</span> i <span style="color: #66cc66;">&lt;</span>= voxelSize/<span style="color: #ff4500;">2.0</span> :
&nbsp;
		j = -voxelSize/<span style="color: #ff4500;">2.0</span>
		<span style="color: #ff7700;font-weight:bold;">while</span> j <span style="color: #66cc66;">&lt;</span>= voxelSize/<span style="color: #ff4500;">2.0</span> :
			<span style="color: #ff7700;font-weight:bold;">for</span> axis <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;zSide&quot;</span>, <span style="color: #483d8b;">&quot;ySide&quot;</span>, <span style="color: #483d8b;">&quot;xSide&quot;</span><span style="color: black;">&#93;</span> :
				z = <span style="color: #ff4500;">0</span>
				y = <span style="color: #ff4500;">0</span>
				x = <span style="color: #ff4500;">0</span>
				zOffset = <span style="color: #ff4500;">0</span>
				zDir = <span style="color: #ff4500;">0</span>
				yOffset = <span style="color: #ff4500;">0</span>
				yDir = <span style="color: #ff4500;">0</span>
				xOffset = <span style="color: #ff4500;">0</span>
				xDir = <span style="color: #ff4500;">0</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> axis == <span style="color: #483d8b;">&quot;zSide&quot;</span> :
					x = i
					y = j
					zOffset = <span style="color: #ff4500;">10000</span>
					zDir = -<span style="color: #ff4500;">1</span>
				<span style="color: #ff7700;font-weight:bold;">elif</span> axis == <span style="color: #483d8b;">&quot;ySide&quot;</span> :
					x = i
					z = j
					yOffset = <span style="color: #ff4500;">10000</span>
					yDir = -<span style="color: #ff4500;">1</span>
				<span style="color: #ff7700;font-weight:bold;">elif</span> axis == <span style="color: #483d8b;">&quot;xSide&quot;</span> :
					y = i
					z = j
					xOffset = <span style="color: #ff4500;">10000</span>
					xDir = -<span style="color: #ff4500;">1</span>
&nbsp;
				raySource = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatPoint</span><span style="color: black;">&#40;</span> x+xOffset, y+yOffset, z+zOffset <span style="color: black;">&#41;</span>
				rayDirection = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatVector</span><span style="color: black;">&#40;</span>xDir, yDir, zDir<span style="color: black;">&#41;</span>
				faceIds=<span style="color: #008000;">None</span>
				triIds=<span style="color: #008000;">None</span>
				idsSorted=<span style="color: #008000;">False</span>
				space=<span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span>
				maxParam=<span style="color: #ff4500;">99999999</span>
				testBothDirections=<span style="color: #008000;">False</span>
				accelParams=inMesh.<span style="color: black;">autoUniformGridParams</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
				sortHits=<span style="color: #008000;">False</span>
				hitPoints = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
				hitRayParam=<span style="color: #008000;">None</span>
				hitFacePtr = <span style="color: #008000;">None</span><span style="color: #808080; font-style: italic;">#OpenMaya.MScriptUtil().asIntPtr()</span>
				hitTriangle=<span style="color: #008000;">None</span>
				hitBary1=<span style="color: #008000;">None</span>
				hitBary2=<span style="color: #008000;">None</span>
&nbsp;
				hit = inMesh.<span style="color: black;">allIntersections</span><span style="color: black;">&#40;</span>raySource,
								rayDirection,
								faceIds,
								triIds,
								idsSorted,
								space,
								maxParam,
								testBothDirections,
								accelParams,
								sortHits,
								hitPoints,
								hitRayParam,
								hitFacePtr,
								hitTriangle,
								hitBary1,
								hitBary2<span style="color: black;">&#41;</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> hit :
					<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
				<span style="color: #808080; font-style: italic;"># for each interestected points</span>
				<span style="color: #ff7700;font-weight:bold;">for</span> k <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>hitPoints.<span style="color: black;">length</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> :
&nbsp;
					cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
					cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
					cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
&nbsp;
					cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
						<span style="color: #ff7700;font-weight:bold;">continue</span>
					<span style="color: #ff7700;font-weight:bold;">else</span> :
						voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span>
&nbsp;
					myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpReelNames<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
			j += voxelStep
		i += voxelStep</pre>
<center><i>Sorry for the horizontal code. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></i></center>


<p>I don't explain this version because I think if you understood the previous one, you shouldn't have too much problems with this one. <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p>


<h3>EDIT 2013/03/19</h3>

<p>Justin Israel <a href="https://groups.google.com/d/msg/python_inside_maya/1pYjnkTB5l0/JUFgz8LSD-gJ" hreflang="en">caught my attention</a> about my <em>voxelIdList</em>. I've learn something so I share his message with you:</p>


<p>If you are using it as a lookup for the hash of previously seen items, using a list is going to be progressively slower and slower over time as the list grows, because doing "x in list" is O(n) complexity. You might want to use a set():</p>

<pre class="python python">voxelIdSet = <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
...
<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdSet :
    <span style="color: #ff7700;font-weight:bold;">continue</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    voxelIdSet.<span style="color: black;">add</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span></pre>


<p>A set is O(1) complexity, so doing "x in set" will instantly find the item by its hash, as opposed to have to scan the entire list looking for an equality match.</p>


feed_id: urn:md5:d298e12473f80efc972d74e54de4a4ed
title: Voxelisation polygonale via l'API Python Maya
uri: Voxelisation-polygonale-via-l-API-Python-Maya
url: http://www.fevrierdorian.com/blog/post/2013/03/16/Voxelisation-polygonale-via-l-API-Python-Maya
content:
<p><img src="media/4de9ae20.voxel_vray_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_vray_tn.png" alt="voxel_vray_tn.png" style="float:left; margin: 0 1em 1em 0;" title="voxel_vray_tn.png, mar. 2013"  height="150" width="150" />Et encore un petit script prétexte à utilisation de l'API Maya. <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<p>L’idée est de reproduire l'effet de géométrie en voxel que vous avez peut être <a href="http://www.bilderzucht.de/blog/3d-pixel-voxel/" hreflang="en">déjà observe</a>.</p>


<p>Rien de bien méchant et ça existe surement déjà et en plus rapide. Pour tout vous dire, je n'ai même pas cherché. Le but est encore une fois d'utiliser l'API. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>    <h3>Principe</h3>

<p>Avant de commencez, sachez que ce problème est un cas d’école. Il y a mille et une façons de le résoudre, chaque méthode ayant ces avantages et ces inconvénients. <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>La méthode choisi ici est la plus simple: Pour chaque vertex de la géométrie, on trouve la position "arrondi au cube près" et on génère un cube.</p>


<p>La seule difficulté de cette implémentation est, une fois la position du vertex récupéré, de savoir ou doit être le centre du cube. <img src="media/fb7f2cd8.seSentCon.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/seSentCon.gif" alt=":seSentCon:" class="smiley" /></p>


<p><a href="media/95bae7a5.voxel_vray.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_vray.png" title="voxel_vray.png"><img src="media/327e2389..voxel_vray_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/.voxel_vray_m.jpg" alt="voxel_vray.png" style="display:block; margin:0 auto;" title="voxel_vray.png, mar. 2013"  height="420" width="560" /></a></p>


<h3>Le code</h3>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">OpenMaya</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">OpenMaya</span>
&nbsp;
voxelStep = <span style="color: #ff4500;">1.0</span>
&nbsp;
sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span>
&nbsp;
inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span>
pointArray = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
inMesh.<span style="color: black;">getPoints</span><span style="color: black;">&#40;</span>pointArray, <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span><span style="color: black;">&#41;</span>
&nbsp;
grpName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>pointArray.<span style="color: black;">length</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> :
&nbsp;
	cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
	cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
	cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
&nbsp;
	cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
		<span style="color: #ff7700;font-weight:bold;">continue</span>
	<span style="color: #ff7700;font-weight:bold;">else</span> :
		voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span>
&nbsp;
	myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpName<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span></pre>


<h3>Les explications</h3>

<pre class="python python">sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Fondamentalement, une <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_selection_list.html,topicNumber=cpp_ref_class_m_selection_list_html" hreflang="en">MSelectionList</a> est une liste de MObject.</p>


<p>Je n'ai jamais vraiment compris ce que la notion de "sélection" voulait dire avec cet objet car il ne "sélectionne" rien. <img src="media/f566509c.bete.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bete.gif" alt=":bete:" class="smiley" /></p>


<p>La particularité d'une <em>MSelectionList</em> c'est de pouvoir récupérer le <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MObject</a> d'un node Maya depuis son nom, ce qu'on fait plus loin.</p>

<pre class="python python">dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>C'est toujours assez difficile d'expliquer ce qu'est le DAG de Maya et encore plus un DAG path. <img src="media/edc4ddb7.gne.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/gne.gif" alt=":gne:" class="smiley" /></p>


<p>Pour faire un gros résumé:</p>
<ul>
<li>DAG: C'est la "hiérarchie" (parent/enfant) de Maya.</li>
<li>DAG path: C'est le "chemin" d'un node en passant par la hiérarchie (et donc, en ayant toutes ces transformations).</li>
</ul>

<p>Beaucoup de fonctions de l'API Maya nécessitent un DAG path pour pouvoir fonctionner.</p>


<p>Par exemple, on ne peut récupérer les coordonnées dans l'espace des vertices d'un node de shape si on ne connait pas le chemin par lequel on y arrive. Deux instances ont un seul node de shape mais il s'agit bien de deux DAG path différents et les coordonnes dans l’espace du même vertex auront deux valeurs possibles suivant "par ou on passe".</p>

<pre class="python python">sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span></pre>

<p>On ajoute l'object Maya "pSphere1" dans la <em>MSelectionList</em> et on récupère son DAG path (le zéro étant l'index dans la liste de sélection).</p>


<p>Nous avons donc "converti" "pSphere1" (qui ne veut rien dire en API Maya) en vrai <em>MObject</em>.</p>

<pre class="python python">inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span></pre>

<p>Par défaut, tout ce qu'on récupère dans l'API ce sont des <em>MObjects</em>. En général, on vérifie le type du <em>MObject</em> via un <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MObject.apiType()</a> ou <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_dag_node.html,topicNumber=cpp_ref_class_m_fn_dag_node_html" hreflang="en">MObject.hasFn()</a></p>


<p>Mais là on part du principe que le user a bien donné une mesh. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>


<p>La fonction <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">MFnMesh</a> permet d'avoir à disposition un "vrai" objet (en terme programmation j'entend) sur lequel on va pouvoir agir pour récupérer des informations. C'est un <em>function set</em>.</p>


<p>Je vous invite a lire <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_object.html,topicNumber=cpp_ref_class_m_object_html" hreflang="en">la documentation</a> afin de comprendre le comment du pourquoi des <em>function sets</em>.</p>


<p>Nous avons donc un object _inMesh_ qui va nous servir a récupérer les vertices de notre mesh.</p>

<pre class="python python">pointArray = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
inMesh.<span style="color: black;">getPoints</span><span style="color: black;">&#40;</span>pointArray, <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span><span style="color: black;">&#41;</span></pre>

<p>La première ligne créée un tableau de point <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html" hreflang="en">MPointArray</a> pour accueillir les positions des vertices de notre mesh.</p>


<p>Et la second ligne remplit le tableau avec les coordonne des vertices en espace monde (position par rapport au centre de la scène, non par rapport au centre de l'objet lui même).</p>

<pre class="python python">grpName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre>

<p>Ici on ne fait que créer un groupe vide qui accueillera les cubes que nous allons créer par la suite. C'est juste qu'il est plus pratique de supprimer un groupe avec tout dedans que de sélectionner tous les cubes à la pogne. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>

<pre class="python python">voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>On créé une liste qui servira a stocker les identifiant (ou code) des zones ou les cubes on déjà été générés. J'y reviens plus bas.</p>

<pre class="python python">cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>pointArray<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep</pre>


<p>Et voici la petite ligne qui fait tout. Vous allez voir, elle est très simple.</p>


<p>Alors, qu'est ce qu'on cherche à faire avec ça?</p>


<p>On va partir du principe que la taille voulue des cubes fait 2.0.</p>


<p>On tombe sur un vertex positionné en X à 10.2. Bien entendu, on ne va pas placer notre cube au centre du vertex (à 10.2). On n'obtiendrais pas du tout l'effet voulu.  <img src="media/f1f7d503.nannan.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nannan.gif" alt=":nannan:" class="smiley" /></p>


<p>Il nous faut la position exacte du cube. Il faut "comptez en nombre de cube".</p>


<p>Comment savoir à quoi correspond la distance 10.2 en cube de taille 2.0? En faisant tout simplement: 10.2/2.0. Soit 5.1.</p>


<p>Comme on ne peut pas avoir 5.1 cubes, on arrondi via la fonction round(). Dans le cas de round(5.1), on obtient 5 (5.7 aurait donne 6).</p>


<p>On sait donc maintenant que si on crée un cube de taille 2.0, il faut le déplacer de 5 fois sa taille pour qu'il englobe le vertex. On multiplie donc la valeur arrondi (5) par la taille d'un cube (2) pour obtenir une nouvelle position: La position du cube, non plus calée sur le vertex mais calée sur la grille du voxel.</p>


<p>Et voila, vous avez capté!  <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>On fait ça pour les trois axes.</p>

<pre class="python python">cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
	<span style="color: #ff7700;font-weight:bold;">continue</span>
<span style="color: #ff7700;font-weight:bold;">else</span> :
	voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span></pre>

<p>Ici, on créé une "signature" (en string) de la position du cube et on la stock dans une liste. Comme ça, si on retombe sur un vertex qui, une fois arrondi, se retrouve au même endroits qu'un cube déjà existant, on ne le crée pas (pas de doublons! :hehe:).</p>


<p>Bien que cette manière de faire <del>semble un peu</del> est très bizarre (convertir les positions des vertex en string), j'ai eu l'impression que c’était la méthode la plus simple pour gérer une grille dont on ne connait pas la taille sans trop de lignes de code.</p>


<p>Mais si vous en avez une autres assez rapide à mettre en place, n’hésitez pas. :D</p>

<pre class="python python">myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpName<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span></pre>

<p>Après c'est simple:</p>
<ul>
<li>On créé notre cube de la taille voulu (2.0).</li>
<li>On lui applique un bevel parce que ça rend bien. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></li>
<li>On le parente au groupe.</li>
<li>On le place à la position calculée plus tôt.</li>
</ul>

<p>Et on repart pour un autre vertex!</p>


<p><img src="media/07f86864.voxel_maya_api_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_maya_api_001.png" alt="voxel_maya_api_001.png" style="display:block; margin:0 auto;" title="voxel_maya_api_001.png, mar. 2013"  height="387" width="382" /></p>


<p><img src="media/529aa798.voxel_maya_api_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_16_voxel_maya_api/voxel_maya_api_002.png" alt="voxel_maya_api_002.png" style="display:block; margin:0 auto;" title="voxel_maya_api_002.png, mar. 2013"  height="598" width="616" /></p>


<p>Encore une fois: Ce script n'est pas optimisé du tout, c'est plus un prototype grossier qu'un outil de prod. Il suffit de lui donner un mesh un peu lourd pour s'en rendre compte. <img src="media/7c977e83.mechantCrash.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mechantCrash.gif" alt=":mechantCrash:" class="smiley" /></p>


<h3>Conclusion</h3>


<p>Ainsi s’achève ce billet express.</p>


<p>Vous avez vue, c'est assez bête dans le principe. Bon, encore une fois on aurait pu faire différemment et surement plus efficace (essayez avec <a href="http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=a5b3f852a00f3dc096c136cbe04057733" hreflang="en">MFnMesh.allIntersections()</a>).</p>


<p>Personnellement, jouer avec l'API Maya m'amuse toujours autant. :)</p>


<p>A bientôt!</p>

<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>



<h3>EDIT 2013/03/17</h3>

<p>Je n'ai pas pu résister à l'appel de la méthode <a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=aa6c4717b168258664d399fb92e2cdcee" hreflang="en">MFnMesh.allIntersections()</a>. Voici donc une version bien plus optimisé que précédemment (avec structure d’accélération <a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/index.html?url=cpp_ref/class_m_fn_mesh.html,topicNumber=cpp_ref_class_m_fn_mesh_html,hash=aa6c4717b168258664d399fb92e2cdcee" hreflang="en">MFnMesh.autoUniformGridParams()</a>).</p>


<p>La principale différence comparé au code précédent est qu'ici nous ne passons plus par chaque vertex mais nous envoyons des rayon sur trois grille (X, Y, Z).</p>


<p>La seconde différence est que ce code fonctionne sur un mesh animé (1 a 24 ici). Testez, l'effet est assez sympa. :)</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">OpenMaya</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">OpenMaya</span>
&nbsp;
startFrame = <span style="color: #ff4500;">1</span>
endFrame = <span style="color: #ff4500;">24</span>
&nbsp;
voxelSize = <span style="color: #ff4500;">20.0</span>
voxelStep = <span style="color: #ff4500;">0.5</span>
&nbsp;
sel = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSelectionList</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
dagPath = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MDagPath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
sel.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pSphere1&quot;</span><span style="color: black;">&#41;</span>
sel.<span style="color: black;">getDagPath</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, dagPath<span style="color: black;">&#41;</span>
&nbsp;
inMesh = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFnMesh</span><span style="color: black;">&#40;</span> dagPath <span style="color: black;">&#41;</span>
&nbsp;
grpReelNames = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> curTime <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>startFrame, endFrame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> :
	grpName = <span style="color: #483d8b;">&quot;frameGrp_%s&quot;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>curTime<span style="color: black;">&#41;</span>
	grpReelName = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span>name=grpName, empty=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">0.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime-<span style="color: #ff4500;">0.1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">1.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setKeyframe</span><span style="color: black;">&#40;</span>grpReelName+<span style="color: #483d8b;">&quot;.visibility&quot;</span>, value=<span style="color: #ff4500;">0.0</span>, <span style="color: #dc143c;">time</span>=<span style="color: black;">&#91;</span>curTime+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	grpReelNames<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span> = grpReelName
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> grpReelName <span style="color: #ff7700;font-weight:bold;">in</span> grpReelNames :
	<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">cmds</span>.<span style="color: black;">objExists</span><span style="color: black;">&#40;</span>grpReelName<span style="color: black;">&#41;</span> :
		<span style="color: #dc143c;">cmds</span>.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>grpReelName<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> curTime <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>startFrame, endFrame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> :
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span>curTime<span style="color: black;">&#41;</span>
&nbsp;
	voxelIdList = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;">#I use while just because xrange with floats is impossible</span>
	i = -voxelSize/<span style="color: #ff4500;">2.0</span>
	<span style="color: #ff7700;font-weight:bold;">while</span> i <span style="color: #66cc66;">&lt;</span>= voxelSize/<span style="color: #ff4500;">2.0</span> :
&nbsp;
		j = -voxelSize/<span style="color: #ff4500;">2.0</span>
		<span style="color: #ff7700;font-weight:bold;">while</span> j <span style="color: #66cc66;">&lt;</span>= voxelSize/<span style="color: #ff4500;">2.0</span> :
			<span style="color: #ff7700;font-weight:bold;">for</span> axis <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;zSide&quot;</span>, <span style="color: #483d8b;">&quot;ySide&quot;</span>, <span style="color: #483d8b;">&quot;xSide&quot;</span><span style="color: black;">&#93;</span> :
				z = <span style="color: #ff4500;">0</span>
				y = <span style="color: #ff4500;">0</span>
				x = <span style="color: #ff4500;">0</span>
				zOffset = <span style="color: #ff4500;">0</span>
				zDir = <span style="color: #ff4500;">0</span>
				yOffset = <span style="color: #ff4500;">0</span>
				yDir = <span style="color: #ff4500;">0</span>
				xOffset = <span style="color: #ff4500;">0</span>
				xDir = <span style="color: #ff4500;">0</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> axis == <span style="color: #483d8b;">&quot;zSide&quot;</span> :
					x = i
					y = j
					zOffset = <span style="color: #ff4500;">10000</span>
					zDir = -<span style="color: #ff4500;">1</span>
				<span style="color: #ff7700;font-weight:bold;">elif</span> axis == <span style="color: #483d8b;">&quot;ySide&quot;</span> :
					x = i
					z = j
					yOffset = <span style="color: #ff4500;">10000</span>
					yDir = -<span style="color: #ff4500;">1</span>
				<span style="color: #ff7700;font-weight:bold;">elif</span> axis == <span style="color: #483d8b;">&quot;xSide&quot;</span> :
					y = i
					z = j
					xOffset = <span style="color: #ff4500;">10000</span>
					xDir = -<span style="color: #ff4500;">1</span>
&nbsp;
				raySource = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatPoint</span><span style="color: black;">&#40;</span> x+xOffset, y+yOffset, z+zOffset <span style="color: black;">&#41;</span>
				rayDirection = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatVector</span><span style="color: black;">&#40;</span>xDir, yDir, zDir<span style="color: black;">&#41;</span>
				faceIds=<span style="color: #008000;">None</span>
				triIds=<span style="color: #008000;">None</span>
				idsSorted=<span style="color: #008000;">False</span>
				space=<span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MSpace</span>.<span style="color: black;">kWorld</span>
				maxParam=<span style="color: #ff4500;">99999999</span>
				testBothDirections=<span style="color: #008000;">False</span>
				accelParams=inMesh.<span style="color: black;">autoUniformGridParams</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
				sortHits=<span style="color: #008000;">False</span>
				hitPoints = <span style="color: #dc143c;">OpenMaya</span>.<span style="color: black;">MFloatPointArray</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
				hitRayParam=<span style="color: #008000;">None</span>
				hitFacePtr = <span style="color: #008000;">None</span><span style="color: #808080; font-style: italic;">#OpenMaya.MScriptUtil().asIntPtr()</span>
				hitTriangle=<span style="color: #008000;">None</span>
				hitBary1=<span style="color: #008000;">None</span>
				hitBary2=<span style="color: #008000;">None</span>
&nbsp;
				hit = inMesh.<span style="color: black;">allIntersections</span><span style="color: black;">&#40;</span>raySource,
								rayDirection,
								faceIds,
								triIds,
								idsSorted,
								space,
								maxParam,
								testBothDirections,
								accelParams,
								sortHits,
								hitPoints,
								hitRayParam,
								hitFacePtr,
								hitTriangle,
								hitBary1,
								hitBary2<span style="color: black;">&#41;</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> hit :
					<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
				<span style="color: #808080; font-style: italic;"># for each interestected points</span>
				<span style="color: #ff7700;font-weight:bold;">for</span> k <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>hitPoints.<span style="color: black;">length</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> :
&nbsp;
					cubePosX = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">x</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
					cubePosY = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">y</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
					cubePosZ = <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>hitPoints<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">z</span>/voxelStep<span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span>voxelStep
&nbsp;
					cubeId = <span style="color: #483d8b;">&quot;%s%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
&nbsp;
					<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdList :
						<span style="color: #ff7700;font-weight:bold;">continue</span>
					<span style="color: #ff7700;font-weight:bold;">else</span> :
						voxelIdList.<span style="color: black;">append</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span>
&nbsp;
					myCube = <span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyCube</span><span style="color: black;">&#40;</span>width=voxelStep, height=voxelStep,  depth=voxelStep<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">polyBevel</span><span style="color: black;">&#40;</span>myCube, offset=<span style="color: #ff4500;">0.02</span><span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">parent</span><span style="color: black;">&#40;</span>myCube, grpReelNames<span style="color: black;">&#91;</span>curTime<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
					<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span>myCube+<span style="color: #483d8b;">&quot;.translate&quot;</span>, cubePosX, cubePosY, cubePosZ<span style="color: black;">&#41;</span>
			j += voxelStep
		i += voxelStep</pre>
<center><i>Désolé pour le code horizontal. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></i></center>


<p>Je ne fais pas de commentaires supplémentaires car je pense que si vous avez compris le premier code, celui ci est tout aussi simple. <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p>


<h3>EDIT 2013/03/19</h3>

<p>Justin Israel a fait <a href="https://groups.google.com/d/msg/python_inside_maya/1pYjnkTB5l0/JUFgz8LSD-gJ" hreflang="en">une remarque très pertinante</a> concernant ma <em>voxelIdList</em>. J'ai appris un truc ducoup. Je vous traduis son message ici:</p>


<p>Si tu utilise <em>voxelIdList</em> pour chercher la signature d'un cube déjà placé, le fait que ce soit une liste va progressivement ralentir la recherche au fil qu'elle se remplit, car <em>x in list</em> est de complexité O(n). Tu devrais utiliser un <em>set()</em>:</p>

<pre class="python python">voxelIdSet = <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
...
<span style="color: #ff7700;font-weight:bold;">if</span> cubeId <span style="color: #ff7700;font-weight:bold;">in</span> voxelIdSet :
    <span style="color: #ff7700;font-weight:bold;">continue</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    voxelIdSet.<span style="color: black;">add</span><span style="color: black;">&#40;</span>cubeId<span style="color: black;">&#41;</span></pre>


<p>Un type set est de complexité O(1) donc faire un <em>x in set</em> va instantanément trouver l'item depuis sa signature, à l'inverse d'une liste qu'une faut parcourir entièrement.</p>


feed_id: urn:md5:e68c6dff650ea6ca0e998cc3bddeec53
title: Pick a color outside Maya 2011 user interface (Qt) (English Translation)
uri: Pick-a-color-outside-Maya-2011-user-interface-(Qt)-(English-Translatio
url:
http://www.fevrierdorian.com/blog/post/2013/03/28/Pick-a-color-outside-the-Maya-2011-user-interface-Qt-English-Translation

content:
    <p><img src="media/c5338e88.maya_color_picker_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_28_color_picker/maya_color_picker_tn.png" alt="maya_color_picker_tn.png" style="float:left; margin: 0 1em 1em 0;" title="maya_color_picker_tn.png, mar. 2013"  height="150" width="150" />An "ultra express" post!  <img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


<p>The color picker has been modified since Maya 2011 and its transition to Qt and it's now impossible to pick a color outside the Maya interface.</p>


<p>Actually yes, you can! And it's quite easy to do!  <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<p>You just need to select the picker, click anywhere inside Maya interface, keep the left mouse button, and drag outside the interface on the color you want.</p>


<p>I must confess, <a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum/suggestions/2993858-allow-the-color-picker-to-operate-on-anything-visi" hreflang="en">I have not found it myself</a>. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


feed_id: urn:md5:d6833b33a3e32ce6681af0878f388a5c
title: Picker une couleur a l’extérieur de l'interface Maya 2011 (Qt)
uri: Picker-une-couleur-a-l-extérieur-de-l-interface-Maya-2011-(Qt)
url:
http://www.fevrierdorian.com/blog/post/2013/03/28/Picker-une-couleur-a-lext%C3%A9rieur-de-l-interface-Maya-2011-Qt

content:
    <p><img src="media/c5338e88.maya_color_picker_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_03_28_color_picker/maya_color_picker_tn.png" alt="maya_color_picker_tn.png" style="float:left; margin: 0 1em 1em 0;" title="maya_color_picker_tn.png, mar. 2013"  height="150" width="150" />Un billet "ultra express"!  <img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


<p>Depuis Maya 2011 et son passage à Qt, le <em>picker</em> de couleur a été modifié et il n'est plus possible de picker une couleur en dehors de l'interface Maya.</p>


<p>En fait si, et c'est tout con a faire!  <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<p>Il suffit, une fois le <em>picker</em> sélectionné, de cliquer dans l'interface Maya mais de garder le bouton gauche enfoncé et de glisser à l’extérieur de l'interface pour récupérer la couleur qui vous intéresse.</p>


<p>J'avoue, <a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum/suggestions/2993858-allow-the-color-picker-to-operate-on-anything-visi" hreflang="en">je n'ai pas trouvé ça tout seul</a>. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


feed_id: urn:md5:8f8c5c69c764482debe77824365b6210
title: 11 Second Club Mars 2013
uri: 11-Second-Club-Mars-2013
url: http://www.fevrierdorian.com/blog/post/2013/04/23/11-Second-Club-Mars-2013
content:
<iframe src="http://player.vimeo.com/video/64650552" width="580" height="326" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
    <h3>Français</h3>

<p>Camille Campion a gagné le <a href="http://www.11secondclub.com/competitions/march13/winner" hreflang="en">11 Second Club du mois de Mars</a>! <img src="media/2e1ef912.bravo.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bravo.gif" alt=":bravo:" class="smiley" /></p>


<p>C'est moi qui me suis chargé de son lighting. C'était surtout un bon gros prétexte pour bosser le soir sur VRay et rendre de l'anim full CG. <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<p>Les délais étaient tendus (un mois pour tout faire), heureusement que Camille anime rapidement (il ne le dit nulle part parce qu'il est modeste mais il a animé ça en 15 jours!). Les ressources étaient assez limitées (C'est ça... Quand on a l'habitude de bosser avec des render farms, ça fait tout drôle de revenir sur son PC maison. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> ).</p>


<p>Le rigg utilisé fut <a href="http://www.animschool.com/DownloadOffer.aspx" hreflang="en">Malcom</a> (j'en profite pour dire que ce rigg voit ses assignations faites "par face" ce qui est assez gênant au moment du lighting).</p>


<p>Au niveau lighting:</p>
<ul>
<li>Une grosse area light blanche sur la vitre.</li>
<li>Une grosse area light orange dans le bar.</li>
<li>Quelques IES au plafond.</li>
</ul>

<p>Si vous avez regardé <a href="http://www.11secondclub.com/competitions/march13/winner" hreflang="en">la version du 11 Second Club</a>, vous remarquerez que la version de ce billet est plus "orange". En fait, Camille m'a aidé à calculer les images sur sa machine et le profil IES (peu d'utilité à utiliser une IES la dessus, j'en conviens) a été oublié. Donc les quelques lumières IES de la scène ne rendaient rien... <img src="media/554c931e.dtc2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/dtc2.gif" alt=":dtcFuckSmile:" class="smiley" /></p>


<p>Les IES étant subtiles et le temps manquant, on a continué la dessus pour la version 11 Second Club. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></p>


<p>Merci à <a href="http://deex.info/wordpress2/" hreflang="en">Damien Bataille</a> pour ses conseils avisés.</p>


<p>Le compo à été fait sous Nuke.</p>


<h3>English</h3>

<p>Camille Campion won the <a href="http://www.11secondclub.com/competitions/march13/winner" hreflang="en">11 Second Club of March</a>! <img src="media/2e1ef912.bravo.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bravo.gif" alt=":bravo:" class="smiley" /></p>


<p>I've been in charge of its lighting. It was mainly a by opportunity to work with VRay and render full CG animation. <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<p>Deadline was short (a month for everything). Fortunately, Camille is a very quick animator (he don't say this anywhere because it's an humble guy but he animate this in 15 days!). Hardware was also very limited (When you're used to deal with renderfarms, it's weird to go back on your home PC. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> ).</p>


<p>The rigg used was <a href="http://www.animschool.com/DownloadOffer.aspx" hreflang="en">Malcom</a> (I want to say that rigg has its material assignments done ​​"by face" which is quite annoying during lighting).</p>


<p>Lighting</p>
<ul>
<li>A big white area light on the window.</li>
<li>A big orange area light in the bar.</li>
<li>Some IES on the ceil.</li>
</ul>

<p>If you've watch <a href="http://www.11secondclub.com/competitions/march13/winner" hreflang="en">the 11 Second Club version</a>, you will notice the version of this post is more "orange". Acutally, Camille help me to render images on its computer and the IES profile (not so usefull on a such shot, I agree) has been lost. So, the few IES light was actually blacks... <img src="media/554c931e.dtc2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/dtc2.gif" alt=":dtcFuckSmile:" class="smiley" /></p>


<p>As IES effect was subtle and we don't have much time, we continue that way for the 11 Second Club version. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></p>


<p>Thanks to <a href="http://deex.info/wordpress2/" hreflang="en">Damien Bataille</a> for its good advices.</p>


<p>Compositing has been made in Nuke.</p>


feed_id: urn:md5:3db5a45143dd84afde3d8d6788c164f3
title: Houdini sous le capot
uri: Houdini-sous-le-capot
url: http://www.fevrierdorian.com/blog/post/2013/04/24/Houdini-sous-le-capot
content:
<p><img src="media/fec933b1.houdini_sous_le_capot_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_tn.png" alt="houdini_sous_le_capot_tn.png" style="float:left; margin: 0 1em 1em 0;" title="houdini_sous_le_capot_tn.png, mai 2013"  height="150" width="150" />Ceci est la traduction d'<a href="http://forums.odforce.net/index.php?/topic/17105-short-and-sweet-op-centric-lessons/#entry104263" hreflang="en">un billet  de old school</a>, posté il y a quelques mois, qui explique, très clairement, le fonctionnement interne de Houdini. Ce post est une mine d'or et je conseille à quiconque souhaitant s'améliorer sur Houdini d'en prendre connaissance.</p>


<p>Il y a beaucoup de lecture, je me suis permis de mettre des titres et quelques images pour "classer" un peu l'ensemble (le bonhomme aborde beaucoup de chose d'une traite). Alors accrochez-vous! <img src="media/00461682.1420.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>


<p>Bien entendu, si vous êtes totalement débutant sur Houdini il n'est pas forcément pertinent de lire tout ça sans avoir suivi quelques tutos (vous partiriez en courant <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /> ), même succinct sur comment utiliser le soft.</p>    <blockquote><p>Ce que j'aimerais voir plus souvent, comme quelqu'un qui saute d'une application à l'autre (pas complètement débutant donc)... C'est une explication de comment Houdini fonctionne "sous le capot". Il y a des brides d'information un peu partout mais la plupart des tutoriaux se focalisent sur l'effet qu'ils essaient de faire.</p></blockquote>


<p>Il n'y a aucun secret sur comment Houdini fonctionne. Tout ce qui se fait dans Houdini peut être exprimé par un node. Que le node soit un opérateur codé en C++, en VEX (ou les nodes VOP représentant les fonctions VEX), Python, ou bien Digital Asset Houdini (HDA), chaque node fait son boulot et met son résultat en cache. Il n'y a pas de niveau plus bas que les nodes.

Dans Houdini, les nodes sont les routines atomiques/fonctions/programmes les plus bas niveaux. Par exemple, un node de type SOP prend la géométrie entrante et la traite en un bloc, puis cache son résultat qu'on peut visualiser:</p>
<ul>
<li>Dans le viewport.</li>
<li>Via bouton milieu de souris (MMB) sur un node pour connaitre ses statistiques.</li>
<li>Dans la Details View, pour voir les valeurs des attributs.</li>
</ul>
<p>Si il s'agit d'un SOP modificateur, il aura une dépendance sur son node d'entrée. S'il y a un changement en amont, le node actuel sera contraint de s'évaluer. S'il y a un paramètre en référence sur un autre node et que le node est marqué comme "dirty" et affecte ce node, ce node sera contraint de s'évaluer.</p>


<h3>Graph et dépendances</h3>


<p><img src="media/76fd21c1.houdini_sous_le_capot_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_005.png" alt="houdini_sous_le_capot_005.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_005.png, mai 2013"  height="232" width="256" /></p>


<p>Pour expliquer la structure de "cooking" (ndt: dans Houdini, calculer une node se dit "cook") d'un graph de SOP, pour chaque cook (changement de frame, de paramètre, etc...), le graph commence à partir du node en Display/Render (ndt: petit rectangle bleu) puis remonte la chaine à la recherche de nodes ayant changé et évalue les dépendances pour chacun d’entre eux en demandant également à ces nodes s'il y a eu des changements, et ce, jusqu'à ce qu'il atteigne les nodes en tête du graph.</p>


<p>Vous pouvez configurer quelques options dans le <em>Performance Monitor</em> pour forcer Houdini à fonctionner de l'ancienne manière (H11) et voir l'arbre de l'ordre d'évaluation si vous le souhaitez. Faites-le. Il est "obligatoire" que vous le fassiez si vous souhaitez avoir une meilleure compréhension de Houdini. Il faut absolument que vous utilisiez le <em>Performance Monitor</em> si vous voulez voir comment les graphs sont évalués car il se base sur l'ordre de création ainsi que les dépendances. Oui, supprimer et remettre un object peut et va changer l'ordre d'évaluation et peut parfois résoudre des crashs. Si vous n'avez pas encore utilisé le <em>Performance Monitor</em>, alors allez-y. Utilisez-le. N'oubliez cependant pas de le désactiver car il a un impact significatif sur les performances.</p>


<p>Une autre astuce est d'utiliser le bouton milieu de souris (MMB) sur un node pour voir ce qu'il a mis en cache depuis sa dernière évaluation. L'utilisation de la mémoire, les attributs actuellement stockés, etc... Le bouton milieu de souris (MMB) est aussi utilisé que le bouton gauche. Vous pouvez voir si le node est "time dependent" ou non, ce qui aura une incidence sur la façon dont il s'évalue et comment cela affectera ses nodes en dépendance.</p>


<p>Vous pouvez utiliser le bouton droit de souris sur le node et ouvrir la <em>Dependency view</em> de cet opérateur qui vous listera toutes ses références et ses dépendances. Vous pouvez utiliser la touche "d" sur le graph puis, dans le <em>Network Editor Display Options</em>, onglet <em>Dependency</em>, activer un certain nombre d'options (liens et halos) permettant de mieux comprendre les dépendances entre les nodes.</p>


<p><img src="media/5c4bc24d.houdini_sous_le_capot_005_NetworkEditorDisplayOptions.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_005_NetworkEditorDisplayOptions.png" alt="houdini_sous_le_capot_005_NetworkEditorDisplayOptions.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_005_NetworkEditorDisplayOptions.png, mai 2013"  height="429" width="565" /></p>


<p><img src="media/f4879b30.houdini_sous_le_capot_005_LocalDependency.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_005_LocalDependency.png" alt="houdini_sous_le_capot_005_LocalDependency.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_005_LocalDependency.png, mai 2013"  height="260" width="369" /></p>


<h3>Un File System</h3>


<p><img src="media/0fec55a4.houdini_sous_le_capot_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_004.png" alt="houdini_sous_le_capot_004.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_004.png, mai 2013"  height="466" width="237" /></p>


<p>Houdini est un file system, en mémoire, et sur le disque sous la forme d'un fichier "cpio" .hip. Si vous le souhaitez, vous pouvez utiliser un shell puis lancer la commande <code>hexpand</code> sur un fichier .hip. Ceci "étalera" le fichier Houdini sous la forme d'une structure de dossier que vous pouvez lire et modifier si vous le souhaitez. Puis rassembler le tout avec la commande <code>hcollapse</code>.
Si vous voulez vraiment voir comment Houdini fonctionne en bas niveau, c'est par ici qu'il faut commencer. C'est simplement une commande Houdini <code>hscript</code> qui construit les nodes dans les dossiers des nodes eux-mêmes. Chaque node est construit en trois fichiers distincts:</p>
<ul>
<li>Le fichier qui ajoute le node et le connecte aux autres nodes.</li>
<li>Le fichier de paramètre qui définit les paramètres des nodes.</li>
<li>Et un fichier qui récupère les infos supplémentaires du node.</li>
</ul>
<p>Si vous lockez un SOP, les informations de ce node seront rassemblées de manière binaire en un seul et même fichier.</p>


<p>C'est pour cette raison que les fichiers .hip sont très petit et qu'il est inutile et déconseillé de locker ces SOP. Il est préférable de cacher un node sur le disque plutôt que de le locker, mais rien ne vous empêche de le faire. Quand vous ouvrez un fichier .hip, tous les nodes sont ajoutés, connectés, leurs paramètres sont modifiés, et les nodes sont "cookés"/évalués.
Il existe différents types de graph de node et les nodes d'un type spécifique ne fonctionnent que dans le dossier d'un type de node spécifique. C'est ce qui fait qu'on peut se retrouver bloquer un peu partout, surtout si on a l'habitude de travailler avec le <em>Build Desktop</em>, que je n'apprécie pas au passage. Il est conseillé d'avoir un arbre quelque part dans l'interface pour visualiser comment le graph se présente quand vous travaillez. C'est également très pratique pour naviguer rapidement dans votre scène. Le <em>Technical Desktop</em> est un bon choix pour quand on récupère le travail de quelqu'un d'autre car il y a une arborescence et quelques autres volets tels que la Details View, Render Scheduler et autres.
Si vous voulez utiliser le <em>Technical Desktop</em> et comprendre un travail fait avec le <em>Build Desktop</em>, ouvrez simplement graph puis l'onglet Parameter et maintenant le coté droit est identique au <em>Build Desktop</em>, mais vous pouvez voir la <em>Tree View</em> et voir ou les nodes sont mis.</p>


<h3>Technical Desktop</h3>


<p><img src="media/d715bdfb.houdini_sous_le_capot_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_003.png" alt="houdini_sous_le_capot_003.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_003.png, mai 2013"  height="426" width="454" /></p>


<p>Un nouveau fichier Houdini est un livre non lu, bourré d'idées intéressantes. En utilisant un Desktop qui expose un onglet <em>Tree View</em>, vous pouvez rapidement voir ce que l'utilisateur a essayé de faire en quelques secondes. Encore une fois, utilisez le <em>Technical Desktop</em> dès le départ si vous utilisez le <em>Build Desktop</em> (si vous me connaissez, vous saurez que je vous forcerais à avoir une <em>Tree View</em> sous les yeux).
Vous pouvez rapidement traverser la scène et inspecter le graph.
Si ce n'est pas assez, vous pouvez ouvrir le Performance Monitor et voir quel node fait le plus gros travail.</p>


<p>Il n'y a pas vraiment besoin de vidéos, juste un fichier .hip. Bien entendu, c'est une vraie aide si la scène est commentée et les nodes nommés en fonction de leurs intentions.</p>


<h3>SOP</h3>


<blockquote><p>Les questions comme: Où les Attributs sont stockés, comment les récupérer (en VOP, Python, Expression), Différence entre les Primitives / Points / Vertex / Volume, les différents Contexts, tout spécialement les explications plus générales sur les contextes DOP / POP... Solver et Multisolver... comme un tutorial Houdini général mais de niveau intermédiaire vers avancé...</p></blockquote>

<p>Restons sur les SOPs.</p>


<p>Dans Houdini, les attributs sont une partie intrinsèque de la géométrie qui est cachée par chaque SOP et non une entité distincte qui doit être gérée indépendamment. C'est ce qui rend les SOPs si élégant. Ce fil entre deux SOP, c'est la géométrie qui passe d'un SOP à l'autre, ces attributs et tout le reste. Et non un lien par attribut (ce qui, dans d'autres logiciels, peut être un attribut géométrie, un attribut paramètre, etc...). Ceci permet à Houdini de manipuler une énorme quantité de géométrie avec beaucoup d'attributs très facilement. Tous les SOPs feront de leur mieux pour traiter les attributs en conséquence (certains mieux que d'autres et pour ces dernier, n'hésitez pas à envoyer un RFE ou un Bug à Side Effects pour voir si quelque chose peut être fait).</p>


<p>Vous pouvez créer des attributs géométriques supplémentaires dans Houdini en utilisant ces SOPs:</p>
<ul>
<li>Point SOP créé les attributs de point "standard".</li>
<li>Vertex SOP créé les attributs de vertex "standard".</li>
<li>Primitive SOP créé les attributs de primitive "standard".</li>
<li>Utilisez le SOP <em>Attribute Create</em> pour créer un attribut ponctuel de différentes classes (float, vector, etc...) de point, vertex, primitive ou Detail.</li>
<li>Utilisez les VEX/VOPs pour créer un attribut de point standard et ponctuel.</li>
<li>utilisez les SOPs Python pour créer un attribut de géométrie standard ou ponctuel.</li>
</ul>

<h4>Distinction entre point et vertex</h4>


<p>Dans Houdini, une clarification qui doit être faite est la distinction entre un attribut de type "point" et un attribut de type "vertex". Certains logiciels utilisent le terme vertex pour désigner soit les attributs de point ou les attributs de prim/vertex. Les jeux vidéos sont attaché à cette définition rendant la confusion encore plus grande, mais hélas, ce n'est pas correct. Dans Houdini, vous devez faire la distinction entre les attributs de point et les attributs de vertex très tôt. Un attribut de point est le niveau le plus bas qu'une information puisse avoir. Par exemple, vector4 P position (la quatrième information étant le poids dans le cas des NURBS) et un attribut de point qui définit un point dans l'espace. C'est tout ce dont vous avez besoin: des points. Pas de primitives ou autres. Vous pouvez ensuite instancier des choses sur ces points au moment du rendu.
Vous pouvez assigner n'importe quel attribut supplémentaire sur ce point.</p>


<p>Pour construire une Primitive, vous avez besoin d'un point (dans le cas d'une Primitive vextex) pour référencer une position et un poid. Dans le cas d'un polygone, ce sont les vertex du polygone qui indexent ces points. Vous pouvez visualiser ces informations dans la <em>Details View</em> en inspectant les attributs des vertex. Le numéro de vertex est présentés sous la forme &lt;primitive_number&gt;:&lt;vertex_number&gt; et la première colonne ("Point Num") affiche à quels points chaque vertex se réfère.</p>


<p><img src="media/313e0f71.houdini_sous_le_capot_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_001.png" alt="houdini_sous_le_capot_001.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_001.png, mai 2013"  height="382" width="726" /></p>


<p>Bien évidemment, vous pouvez avoir plusieurs vertex se référant au même point et c'est ce "partage" qui permet d'obtenir un shading doux par défaut, sans utiliser les normales des vertex (car les normales des points seront moyennées automatiquement par les vertex se partageant ce point).</p>


<p>Par exemple, dans le cas d'une Primitive Sphere, il y a un simple point dans l'espace, puis une primitive de type sphere avec un seul vertex qui référence la position du point pour placer la sphère. Puis il y a les données intrinsèques de la sphère (qui seront disponible dans la prochaine version majeur (ndt: Houdini 12)) ou vous pourrez voir les propriétés de cette sphère tel que ces bornes (ou vous pouvez augmenter le diamètre), son volume, etc...</p>


<p><img src="media/3d7f3500.houdini_sous_le_capot_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_002.png" alt="houdini_sous_le_capot_002.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_002.png, mai 2013"  height="438" width="725" /></p>


<p>Les autres types de primitives composés d'un seul point et d'un seul vertex sont les primitives de type volume, metaball, grille VDB, archive Alembic, etc...</p>


<p>Comment, par exemple, un SOP de type <em>Transform</em> sait faire la différence entre transformer une primitive de type sphère une primitive de type sphère polygonale? La réponse est qu'il a été programmé pour gérer les primitives de type sphères d'une manière compatible avec n'importe quelle géométrie polygonale. Il en est de même avec les Volumes. Il a été programmé pour gérer les volumes de manière à donner à l'utilisateur final le résultat souhaité.</p>


<p>Cela signifie que tout SOP correctement codés se chargera tout type de primitives de manière cohérente. Certains SOPs sont uniquement destinés aux surfaces paramétriques (<em>Basis</em>, <em>Refine</em>, <em>Carve</em>, etc) et d'autres pour les polygones (PolySplit, etc), mais pour la plupart, la majorité des SOPs peuvent fonctionner avec tous les types de primitives.</p>


<h4>Les Attributs</h4>


<p>Qu'en est-il des attributs? Le SOP <em>Carve</em>, par exemple, peut découper n'importe quelle géométrie polygonale à un point donné. Il interpolera probablement bilinéairement tous les attributs présents sur la géométrie entrante puis cachera le résultat. C'est ce comportement automatique pour n'importe quel point, vertex, primitive et attributs particuliers qui fluidifie le travail avec le s SOP.</p>


<p>Comment Houdini sait quoi faire avec les vertex attributs quand la position P, la vélocité V et la normale de la surface N doivent être traités différemment?
Si par exemple, vous exécuter une rotation via un SOP <em>Transform</em> et que la géométrie a des normales N, des vecteurs de vélocité V, et un cache de position "rest", chaque attribut sera traité correctement (en fait, N car c'est un attribut par défaut connu mais pour les attributs customs, vous pouvez spécifier une "intention" sur le vecteur qui lui dira si il doit être considéré comme un type vecteur, une position en 3 float, ou de type normal de surface). C'est ce comportement automatique avec les attributs combiné au fait que vous n'ayez pas à gérer les attributs à la main qui rend l'utilisation des SOPs facile et puissant, sans avoir à recourir au code.</p>


<p>Rappelez-vous que chaque SOP est un petit programme en lui-même. Il aura ses propres comportements, ces propres variables locales s'il supporte plusieurs attributs dans son code, ses propres paramètres, sa propre manière de gérer les différents types de primitive (polygones, NURBS, Beziers, Volumes, grilles VDB, Metaballs, etc...). Si vous traitez chaque SOP comme un plugin autonome, vous êtes sur la bonne voie. Chaque SOP a sa propre page d'aide rédigée correctement qui vous expliquera ce que ce plugin fait, ce que font les paramètres, les variables locales disponibles s'il y en a, les nodes liés à ce node, et finalement, des fichiers d'exemple que vous pouvez loader dans la scène courante ou une scène externe.</p>


<p>Beaucoup de hardcores users d'Houdini amassent de l’expérience uniquement en trainant dans les fichiers d'exemples de l'aide et c'est une très bonne façon d’apprendre Houdini car tout y est fait de node. Pour vous dire, si nous avions locké la géométrie dans les fichiers d'aides, le téléchargement de Houdini prendrait des gigas. Il n'y a donc que des nodes dans l'aide et ce sont les seules choses que vous ayez besoin de connaitre.</p>


<p>Je ne vais pas parler des DOPs pour l'instant car c'est un type différent pensé pour la simulation. Invariablement, un graph de DOPs finit par être référencé par un SOP pour aller chercher de la géométrie. Donc au final, c'est juste de la géométrie, et donc, des SOPs.</p>


<h3>Shelf Tools et scripts</h3>


<blockquote><p>Je grince des dents quand je vois quelqu'un utiliser un <em>Shelf Tools</em> dans un tutoriel... (Je veux savoir exactement ce qui se passe)</p></blockquote>

<p>Les <em>Shelf Tools</em> où ils sont, mais je comprends ce que vous voulez dire. Oui, il n'y a rien qui puisse connecter un tas de node dans différents graphs puis vous référencer le tout. Faites cela pour en partant de zéro pour une simulation une ou deux fois, super! Faites cela des dizaines de fois par semaine, et bien c'est là que les <em>Shelf Tools</em> et les HDAs vous rendent la vie plus simple.</p>


<p>Mais ne soyez pas effrayés par les <em>Shelf Tools</em>. Tout ces outils sont de simples scripts qui placent les opérateurs ensembles et set les valeurs des paramètres pour vous. Il n'y a aucune quand au fichier .hip que vous sauvez. Si vous êtes du genre ultra-hardcore, vous ne sauvez même pas le fichier .hip et que vous refaites toutes les connections de zéro, tout le temps, chaque fois d'une manière un peu différente, en évoluant, en apprenant. Donc si vous trouvez cette logique des <em>Shelf Tools</em> aussi détestable, sachez que chaque fois que vous ouvrez une scène .hip, vous trichez. :P
Ca me rappelle l'argument du menuisier quant à ce qui est construit à la main et ce qui ne l'est pas. Je veux dire, à partir du moment où vous utilisez n'importe quoi d'autres que vos ongles et vos dents pour travailler le bois, vous trichez, mais nous ne faisons pas la distinction pour autant. Les menuisiers utilisent du métal et du verre pour travailler le bois parce que les ongles mettent trop de temps à repousser et les dents endommagées ne repoussent pas. Mais je m'égare...</p>


<p>Racontez ça à des power users d'autres applications qui ont tapé un code propre et impec mais qui ont toujours peur que la prochaine release rende leurs routines favorites obsolètes. Avec des nodes, vous avez un type et des paramètres. S'ils ne changent pas de build en build, ils se chargeront correctement. Je peux ouvrir des fichiers d'avant qu'il soit de type .hip, quand ils portaient l'extension .mot (de Sage pour ceux qui se souviennent) de 1995. Ils s'ouvrent toujours, avec quelques petites erreurs tout de même mais ils s'ouvrent toujours. Un SOP <em>Point</em> est un SOP <em>Point</em> et un SOP <em>Copy</em> est un SOP <em>Copy</em>. Aucune crainte que des trucs deviennent obsolètes. Il suffit de taper la commande "ophide" dans le textport de Houdini et vous pourrez encore trouver les SOPs Limb et Arm (wtf?). LOL!</p>


<p>La première chose que je fais chaque matin? Téléchargez la dernière build. Lire le log des builds. S'il y a quelque chose d'intéressant dans cette build, je fais un test en partant de zéro.
Alors lisez forums si vous avez le temps et répondez à des questions à partir de zéro si vous le pouvez.
Tout ça au nom de la pratique.</p>


<p>Comme précisé plus haut, gardez à l'esprit qu'un fichier .hip est une simple collection de fichier de script dans un système de dossier sauvé sur le disque. Un HDA Houdini est de la même vaine. Idem pour un <em>Shelf Tool</em>: Un script qui ajoute et connecte des nodes et change leurs paramètres. Générer un amas de géométrie et le stocker dans un node de shape ne vous permettra jamais de savoir comment vous y êtes arrivés.</p>


<p>Afin d'aider l'utilisateur à suivre qui a créé quoi, vous pouvez utiliser le raccourcis clavier "N" dans n'importe quel graph pour basculer le nom du node entre:</p>


<p><img src="media/94edb22a.houdini_sous_le_capot_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_006.png" alt="houdini_sous_le_capot_006.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_006.png, mai 2013"  height="150" width="205" /></p>
<center>Label par défaut</center>



<p><img src="media/cd5b7dd7.houdini_sous_le_capot_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_007.png" alt="houdini_sous_le_capot_007.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_007.png, mai 2013"  height="161" width="264" /></p>
<center>Le nom de l'outil qui a créé ce node</center>



<p><img src="media/bfd41ba6.houdini_sous_le_capot_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_008.png" alt="houdini_sous_le_capot_008.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_008.png, mai 2013"  height="159" width="221" /></p>
<center>Rien</center>



<p>Ceci combiné aux options d'affichages des dépendances du graph (raccourci "d") devrait vous permettre de comprendre ce que chaque <em>Shelf Tool</em> fait dans votre scene.</p>


<h3>Naviger dans le File System Houdini</h3>


<p>Si vous voulez creuser encore plus profond, vous pouvez utiliser l'onglet textport et utiliser les commandes:</p>
<ul>
<li><code>opcf</code> (aliasé en <code>cd</code>)</li>
<li><code>opls</code> (aliasé en <code>ls</code>)</li>
<li><code>oppwd</code> (aliasé en <code>oppwd</code> et <code>pwd</code>)</li>
</ul>

<p>Et ce, pour naviguer dans la scène Houdini via le textport comme vous le feriez dans un shell unix.</p>


<p>Une commande que j'aime montrer à ceux qui s’intéressent plus particulièrement à comment Houdini fonctionne. Taper (par exemple):</p>
<pre class="bash bash"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>obj</pre>


<p>Puis de faire un:</p>
<pre class="bash bash">opls <span style="color: #660033;">-al</span></pre>


<p>Et voir leur liste de node:</p>
<pre class="bash bash"><span style="color: #000000; font-weight: bold;">/</span> -<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>obj
<span style="color: #000000; font-weight: bold;">/</span>obj -<span style="color: #000000; font-weight: bold;">&gt;</span> opls
grid_object1
<span style="color: #000000; font-weight: bold;">/</span>obj -<span style="color: #000000; font-weight: bold;">&gt;</span> opls <span style="color: #660033;">-al</span>
<span style="color: #660033;">----h---</span> ipr_camera <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                 May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">22</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>rwxrwxrwx<span style="color: #7a0874; font-weight: bold;">&#93;</span>
d---e--- grid_object1 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">5</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>               May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">31</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>rwxrwxrwx<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #660033;">----h---</span> ipr_camera1 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">26</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>rwxrwxrwx<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #660033;">----h---</span> ipr_camera2 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">26</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>rwxrwxrwx<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre>


<p>Vous aurez un retour très similaire à ceux qu'on peut avoir dans un shell unix listant les fichiers. Gardez à l'esprit que Houdini "EST" un file system avec des dépendances complexes supplémentaires toutes triées pour vous.
Il y a des permissions <code>user/group/other</code>. Oui, vous pouvez utiliser <code>opchmod</code> (non aliasé en <code>chmod</code> mais ça se fait facilement faite avec la commande <em>hscript</em> <code>alias</code>) pour changer la permission des nodes.</p>


<p>Par exemple:</p>


<p><code>opchmod 000 *</code> supprimera toutes les permissions read/write/execute de tous les nodes du répertoire courant.</p>
<pre class="bash bash"><span style="color: #000000; font-weight: bold;">/</span>obj -<span style="color: #000000; font-weight: bold;">&gt;</span> opchmod 000 <span style="color: #000000; font-weight: bold;">*</span>
<span style="color: #000000; font-weight: bold;">/</span>obj -<span style="color: #000000; font-weight: bold;">&gt;</span> opls <span style="color: #660033;">-al</span>
<span style="color: #660033;">----h---</span> ipr_camera <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                 May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>---------<span style="color: #7a0874; font-weight: bold;">&#93;</span>
d---e-cs grid_object1 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">5</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>               May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>---------<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #660033;">----h---</span> ipr_camera1 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>---------<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #660033;">----h---</span> ipr_camera2 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">3</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                May  <span style="color: #000000;">3</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> Narann <span style="color: #7a0874; font-weight: bold;">&#91;</span>---------<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre>


<p>Et devinez quoi? Les paramètres ne sont plus disponibles à la modification.</p>


<p><img src="media/692e6490.houdini_sous_le_capot_009_opchmod.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_04_24_Houdini_sous_le_capot/houdini_sous_le_capot_009_opchmod.png" alt="houdini_sous_le_capot_009_opchmod.png" style="display:block; margin:0 auto;" title="houdini_sous_le_capot_009_opchmod.png, mai 2013"  height="438" width="646" /></p>


<p>N'oubliez pas de le dire à vos victimes ou de leur régler leur souci sinon vous pourriez bien perdre votre job tout seul. <code>opchmod 777 *</code> rend les permissions. Un <code>opls -al</code> vous permettra de le vérifier.</p>


<p>Maintenant, vous savez ce que notre système de licence fait aux états des nodes. Vous pouvez modifier les permissions <code>read</code> et <code>execute</code> de tous les nodes, mais la permission <code>write</code> d'un node DOP ou SOP n'est modifiable que si vous possedez la licence Houdini FX.</p>


<p>Tout en sachant ça, le fichier .hip est vraiment un livre d'histoire avec beaucoup de façon de savoir qui a créé quel node et quand, quel tool il a utilisé pour le créer, quelles dépendances possèdent ce node, est ce qu'il est time dépendant, et plus... Tout ça en inspectant rapidement.</p>


<h3>Conclusion</h3>


<p>Après tout ça, apprendre Houdini se résume simplement à apprendre chaque node et pratiquer, pratiquer, pratiquer. Oh! Et si vous ne le savez pas encore, beaucoup de nodes ont une histoire riche (certains sont plus vieux de 30 ans) et peuvent faire beaucoup de choses. Donc inspirez-vous de tout ça, lisez la documentation des nodes, étudiez les fichiers d'exemples et avancez. Plus vous maitriserez de nodes, plus vous aurez de manière de résoudre un problème, plus vite vous travaillerez et meilleurs vous serez. Plus vous ferez ça et plus pertinents seront vos choix. La courbe d'apprentissage est sans fin, visuel et WYSIWYG. B)</p>


feed_id: urn:md5:828a40028de3c667de154ff671f3686b
title: Présentation d'une publication: Sorted Deferred Shading for Production Path Tracing
uri: Présentation-d-une-publication-Sorted-Deferred-Shading-for-Productio
url:
http://www.fevrierdorian.com/blog/post/2013/07/06/Presentation-d-une-publication-Sorted-Deferred-Shading-for-Production-Path-Tracing

content:
<p><img src="media/79f1e26f.Sorted_Deferred_Shading_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/Sorted_Deferred_Shading_tn.png" alt="Sorted_Deferred_Shading_tn.png" style="float:left; margin: 0 1em 1em 0;" title="Sorted_Deferred_Shading_tn.png, juil. 2013"  height="150" width="150" />Ce billet est une présentation très succincte d'une publication de <em>Walt Disney Animation Studios</em> datant de 2013 visant à expliquer les tenants et aboutissants du "tri" des rayons et shading points avant leur calcul: <a href="media/a7d01d5c.Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf" data-original-source="https://disney-animation.s3.amazonaws.com/uploads/production/publication_asset/70/asset/Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf" hreflang="en">Sorted Deferred Shading for Production Path Tracing</a>.</p>


<p>Je ne rentrerais pas dans les détails et un développeur un peu à l'aise avec le raytracing tirera surement beaucoup plus d'informations du papier original. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>    <h3>Introduction</h3>

<p>Tout d'abord pourquoi parler de ça sur ce blog? <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>


<p>Comme vous avez surement pu le constater, je ne suis plus très actif. Sachez que ce n'est pas uniquement un manque de temps mais surtout de sujets à aborder.</p>


<p>En effet, au fils des années j'ai commencé à travailler sur des problématiques de plus en plus complexes et de moins en moins génériques. Il y avait donc très peu d’intérêt d'aborder les sujets ici.</p>


<p>J'ai un certain nombre de billets que j'ai commencé sans jamais les finir car les sujets abordés n'étaient soit pas intéressants (mon point du vue sur la vague des "logiciels de rendu") sois trop spécifiques (il n'est pas évident d'aborder les technologies maisons des studios <img src="media/974288c3.cayMal.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/cayMal.gif" alt=":cayMal:" class="smiley" /> ).</p>


<p>Bref, ce n'est pas pour autant que j'ai chaumé et j'ai emmagasiné un bon paquet d'infos, de connaissances que je commence à maitriser, en tous cas, suffisamment pour en parler. <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>


<p>L'idée m'est donc venue de vous parler de différentes publications (<em>papers</em> en anglais) dont vous avez surement déjà dû voir ou entendre parler, leur sortie étant très florissante pendant la période du Siggraph. <img src="media/990690f6.whistle2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /></p>


<p>Maintenant, pourquoi cette publication là en particulier?</p>


<p>Et bien parce que depuis quelques années l'idée que le full raytracing "va tout simplifier" s'est généralisée. Le maitre incontesté de cette philosophie est sans conteste Arnold à qui on pourrait presque reprocher son approche quasi religieuse, mais le virage abrupt de Renderman vers du full raytrace tend à lui donner raison. <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /></p>


<p>Et pourtant. Non, tout n'est pas rose au pays du full raytrace. Car si de nouvelles choses sont possibles, de nouvelles problématiques apparaissent et oui, il faut "tricher". Le <em>rayswitch</em> devient la norme et tout moyen visant à gagner du temps est mis à profit, car c'est bien le rapport temps/qualité qui détermine l'efficacité d'un moteur, et la course à la puissance a aussi ses limites. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></p>


<p>Cette publication est intéressante car elle permet, de par la problématique qu'elle aborde (GI raytrace) de comprendre les défis et limites que peuvent/vont rencontrer les moteurs de rendu modernes.</p>


<h3>Avant propos</h3>

<p>Avant de commencer je voudrais préciser quelques points techniques importants. Ces notions ne sont pas forcément très connu des graphistes, pourtant je pense qu'elle ont beaucoup de sens, même à notre échelle.</p>


<h4>Rayon cohérent/incohérent</h4>

<p>Un terme fréquemment utilisé quand on parle d'optimisation du raytracing est <em>cohérent</em>/<em>incohérent</em> mais doit se comprendre comme <em>qui varie peu</em>/<em>qui varie beaucoup/presque aléatoire</em>.</p>


<p><img src="media/92242c4b.coherent_incoherent_rays.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/coherent_incoherent_rays.jpg" alt="coherent_incoherent_rays.jpg" style="display:block; margin:0 auto;" title="coherent_incoherent_rays.jpg, juil. 2013"  height="271" width="584" /></p>


<p>Ces images sont tirées du très instructif article de <em>Intel</em> expliquant le fonctionnement de <em>Embree</em>: <a href="http://software.intel.com/en-us/articles/embree-highly-optimized-visibility-algorithms-for-monte-carlo-ray-tracing" hreflang="en">Embree: Photo-Realistic Ray Tracing Kernels</a>. Pdf <a href="media/c1d366b1.Embree_June2011.pdf" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/Embree_June2011.pdf">ici</a>.</p>

<ul>
<li>A gauche: Ce sont des rayons cohérents. Ils partent d'un même point et vont dans une direction particulière (même si cette direction est plus ou moins "ouverte"). Le nombre d'objets que vont toucher ces rayons est faible.</li>
<li>A droite: Ce sont des rayons incohérents. Ils vont et viennent de toutes les directions. Bien entendu, le nombre d'objets que vont toucher ces rayons est important.</li>
</ul>

<p>Vous allez très vite comprendre le pourquoi du comment. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<h4>Rays et Shading Points</h4>

<p>En raytracing on fait souvent la distinction entre le lancer de rayons en lui même (savoir quelle géométrie le rayon va toucher dans la scène) et le shading du point (le fait de calculer la couleur, la reflection, tout ce qui est lié au matérial sur ladite géométrie).</p>


<p>Ce sont deux étapes très différentes:</p>


<p><img src="media/a205a19f.schema_shading_point.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/schema_shading_point.png" alt="schema_shading_point.png" style="display:block; margin:0 auto;" title="schema_shading_point.png, juil. 2013"  height="207" width="326" /></p>


<h4>Out-of-core</h4>

<p>Le terme <em>out-of-core</em> est un terme que l'on rencontre souvent dans les calculs massivement distribués. <a href="http://en.wikipedia.org/wiki/Out-of-core_algorithm" hreflang="en">La page Wikipedia</a> explique bien le principe mais en gros, <em>core</em> est un ancien terme pour désigner la mémoire vive. <em>Out-of-core</em> fait donc référence à des calculs sur des données qui ne sont pas stockées dans la mémoire vive mais directement sur le disque.</p>


<p>Pour être efficace, un calcul <em>out-of-core</em> doit lire le minimum d'information sur le disque, et donc, les informations les plus pertinentes.</p>


<p>Si vous comprenez ces notions, la suite va vous sembler évidente. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<h3>Traduction</h3>

<p>Toute bonne publication commence par la partie la plus courte et la plus simple à comprendre: <em>Abstract</em>. Même si ce genre de lecture ne vous fait pas rêver, je vous encourage à la lire si vous vous intéressez un temps soit peu à la technique.</p>


<p>Le principe est de résumer, aussi simplement que possible, en quelques phrases, ce que présente la publication.</p>


<h4>Abstract</h4>

<p>L'illumination globale (GI) en lancé de rayon se généralise dans le rendu de production mais l'incohérence des rayons secondaires limite son utilisation à des scènes qui peuvent être placées intégralement en mémoire.</p>


<p>L'incohérence du shading entraine également d'importants soucis de performance lors de l'utilisation de nombreuses (et lourdes) textures qui oblige le moteur de rendu à recourir aux caches d'irradiance, de radiosité, et autres moyens pour diminuer le cout du shading.</p>


<p>Malheureusement, cette mise en cache:</p>
<ul>
<li>Complique le travail du graphiste</li>
<li>Est difficile à paralléliser efficacement</li>
<li>Occupe une précieuse mémoire.</li>
<li>Et pire, ces caches impliquent une approximations qui altère la qualité.</li>
</ul>

<p>Dans cette publication, nous présentons une nouvelle structure de path tracing qui évite ces compromis. Nous organisons les rayons en gros paquets, potentiellement <em>hors du core</em>, pour assurer la cohérence des rayon lancés.</p>


<p>Nous retardons le shading des points touchés par les rayons jusqu'à ce que nous les ayons trié, ce qui permet un shading cohérent et évite d'avoir recours à des caches.</p>


<p>Et voilà pour <em>Abstract</em>!</p>


<p>Avouez que ce n'est pas non plus la misère à comprendre. <img src="media/fb7f2cd8.seSentCon.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/seSentCon.gif" alt=":seSentCon:" class="smiley" /></p>


<p>On enchaine avec l'introduction qui résume grosso modo ce que présente <em>Abstract</em>.</p>


<h4>Introduction</h4>

<p>La GI en path-tracing offre de nombreux avantage en rendu de production: Un éclairage plus riche, plus plausible avec moins de lights et évite la lourde gestion des données liées aux point clouds (PTC) et aux deep map shadows.</p>


<p>Bien que cette approche offre une meilleure image et une productivité accrue, les performances se dégrade de manière importante à mesure que la géométrie et les textures dépassent la capacité mémoire disponible.</p>


<p>Ainsi, les moteurs de rendu de production existants s'évertuent à lancer le moins de rayons possible et à calculer le moins de points de shading possible, privilégiant l'utilisation de caches d'éclairage/de shading et de géométrie instanciées. Mais ces mesures gênent le travail des graphistes.</p>


<p>A mesure que la recherche améliore l'intersection rayon/géométrie, le calcul de shading points incohérent devient un problème de plus en plus conséquent.</p>


<p>En particulier, l'accès incohérent à d'énormes textures de production entraine de fréquents <em>cache-misses</em> (à traduire: "Pas dispo dans le cache de texture? S'pas grave, on reload!") provoquant des <em>pauses</em> importantes due à la latence d'accès mémoire/disque/réseaux durant le calcul.</p>


<p>Les caches d'irradiance et de radiosité tentent de minimiser cela, bien que leur non-directionalité inhérente ne les rendent efficace que pour des surfaces parfaitement diffuses. (ndt: Par "non-directionnalité", comprenez qu'on ne peut stocker l'irradiance d'une surface réfléchissante, qui "varie en fonction de la direction", miroir etc... Le chercheur semble toutefois oublier qu'une irradiance est tout à fait "stockable" sous la forme d'une spherical harmonique, ce qui permet de palier à ce problème).</p>


<p>Par conséquent, il est d'usage de séparer les techniques en fonction du type de rayon à calculer (diffus, spéculaires et caustiques) ce qui complique encore le travail des graphistes.</p>


<p>Pire encore, ces approches sont difficiles à adapter à des architectures multi-core à cause de la synchronisation, l'<a href="http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access" hreflang="en">effet NUMA</a> (le fait d'aller chercher des informations un peu partout dans la mémoire diminue drastiquement ces performances) et l'équilibrage de la charge (load-balancing).</p>


<p>De fait, il est préférable d'éviter les caches et privilégier un shading cohérent.</p>


<p>Dans cette publication, nous présentons un ray-tracer continu capable d'effectuer plusieurs rebonds de GI dans une scène de production sans recourir à des caches de shading ou des instances.</p>


<p>Pour y parvenir, nous introduisons une nouvelle approche de tri de rayon en deux étapes.</p>


<p>Dans un premier temps, nous organisons les rayons en gros paquets, potentiellement <em>hors du core</em> (stocké sur disque donc), pour s'assurer de  leur cohérence.</p>


<p>Travailler avec de gros paquets est essentiel pour extraire les groupes de rayons cohérent d'une scène complexe.</p>


<p>Dans un second temps, nous trions les rayons ayants touchés (les fameux <em>ray hits</em>) pour calculer les shading des points en utilisant les textures <em>hors du core</em>.</p>


<p>Pour chaque lot, nous réalisons un shading parfaitement cohérent avec des lectures de textures séquentielles, ce qui élimine la nécessité d'un cache de texture.</p>


<p>Notre approche est simple à implémenter et compatible avec la plupart des techniques de casting de scène.</p>


<p>Nous démontrons l'efficacité de notre tri en deux étapes combiné au paquets de rayons <em>hors du core</em> et comparons nos résultats avec les deux principaux ray-tracers de production: PhotoRealistic RenderMan (hum... <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /> ) de Pixar et Arnold de Solid Angle.</p>


<p>Je m’arrête là, pour plus d'explications, il faut <a href="media/a7d01d5c.Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf" data-original-source="https://disney-animation.s3.amazonaws.com/uploads/production/publication_asset/70/asset/Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf" hreflang="en">lire la publication</a>! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>


<h3>Explications</h3>

<p>Ce qu'explique cette publication c'est que le fait d'avoir beaucoup de rayons incohérents va nécessiter un load de quasiment toute la scène pour calculer les intersections des rayons, puis, en parallèle, va nécessiter de loader un grand nombre de textures différentes pour calculer le shading de ces rayons. Tout ça juste pour calculer l'illumination d'un seul point.</p>


<p><img src="media/368f2936.schema_ray_coherent_incoherent.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/schema_ray_coherent_incoherent.png" alt="schema_ray_coherent_incoherent.png" style="display:block; margin:0 auto;" title="schema_ray_coherent_incoherent.png, juil. 2013"  height="313" width="506" /></p>


<p>Et sur une scène plus dense:</p>


<p><img src="media/9fc257e3.schema_big.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/schema_big.png" alt="schema_big.png" style="display:block; margin:0 auto;" title="schema_big.png, juil. 2013"  height="355" width="495" />
Imaginez chaque <em>zone</em> comme un énorme asset avec beaucoup de géométrie et beaucoup de textures. On ne peut pas tout loader en RAM. Du-coup, pour calculer l'illumination global d'un point ça risque de faire tourner le cache inutilement.</p>


<p>La solution proposée consiste à rassembler les rayons allants dans des directions similaires et de les calculer en même temps, d'un seul bloc. La quantité de données à charger sera donc moins disparate/plus pertinente et permettra d'éviter de charger et décharger le cache, opération couteuse en temps.</p>


<p>Grossièrement cela donne ça:</p>


<p><img src="media/085e9d81.schema_big002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_13_09_Presentation_Sorted_Deferred_Shading/schema_big002.png" alt="schema_big002.png" style="display:block; margin:0 auto;" title="schema_big002.png, juil. 2013"  height="317" width="494" /></p>


<p>Partant de là on peut imaginer pas mal d'approches:</p>
<ul>
<li>Calculer quelques samples "à l'ancienne", pour sortir une "map" d'environnement, récupérer son importance et générer plus de rayons à lancer dans certaines directions plutôt que d'autres (si une direction renvoit majoritairement du noir, il n'y a pas de raison d'envoyer autant de rayons qu'une direction plus clair qui va avoir une influence plus importante sur la solution finale).</li>
<li>Comme on a une utilisation plus optimisé du cache, on pourrait imaginer que le calcul des intersections soit fait sur le GPU, après y avoir chargé un paquet de rayon. Les échanges RAM/VRAM étant le goulet d'étranglement traditionnel de cette approche, on peux espérer repousser ces limites. L'avantage en cas de multi GPU c'est de pouvoir lancer un paquet d'une direction sur un des GPU et un autre sur le second GPU. Une fois qu'un GPU a fini son calcul, on pourrait en tirer une importance et générer des paquets plus "intéressants" (importance driven).</li>
<li>Après une première "passe", on stocke les résultats des shading points par object (on doit pouvoir les "compresser" si ils ont la même couleur, en leur donnant un "facteur de présence"). Lors de la seconde "passe" le calcul d'intersection des objets éloigné/peu "importants" se fait sur une version allégé de la géométrie (plus rapide à intersecté) et le résultat du shading point est récupéré directement, de manière aléatoire, dans le tableau des valeurs de shading points stocké précédemment sur l'object. De cette façon, plus aucune raison de calculer les shading points lors de la seconde/troisième passe, faisant des économies de ressource indirect conséquent (cache de texture notamment). Même si cette approche est biased, dans le cas de rayons incohérents, elle pourrait se révéler très efficace.</li>
<li>On combine toutes ces approches en même temps! <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></li>
</ul>

<h3>Conclusion</h3>

<p>J'espère que ce petit billet vous aura intéressé et vous aura permis de comprendre un peu ce qui se passe dans un raytracer quand il doit parcourir une scène et tout particulièrement les limites qu'il peut y avoir durant cette étape.</p>


<p>A bientôt!</p>


<p>Dorian</p>

<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:6e1993769c1741aa9a0e7135c7951be6
title: Mental ray for Maya: Diminuer le flicking du Final Gather
uri: Mental-ray-for-Maya-Diminuer-le-flicking-du-final-gather
url:
http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Diminuer-le-flicking-du-final-gather

content:
<p><img src="media/cf3f6048.fg_diminuer_flicking_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_tn.png" alt="fg_diminuer_flicking_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fg_diminuer_flicking_tn.png, juil. 2013"  height="150" width="150" />Dans ce billet je vous propose d'utiliser <del>une méthode simple</del> un bricolage (on parle de mental ray for Maya là <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> ) visant à diminuer le flicking du Final Gather.</p>


<p>Vous allez voir que l'approche est un peu particulière mais elle vise tout bêtement à reproduire le comportement de l'option <a href="http://www.spot3d.com/vray/help/maya/150R1/render_params_advancedimap.htm#basic" hreflang="en">Interp. samples</a> de Vray.</p>    <h3>Avant propos</h3>


<p>Avant de commencez sachez que c'est vraiment Vray qui m'a poussé à remettre mon nez dans mental ray, en particulier le merge des maps de Final Gather. Alors que tout est très simple dans Vray, dans mental ray, c'est la douleur (comme d'hab <img src="media/27323fb5.mad0001.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mad0001.gif" alt=":septic:" class="smiley" /> ).</p>


<p>En gros on va devoir injecter du script dans les <em>Pre render frame MEL</em> et <em>Post render frame MEL</em> pour recréer le comportement de Vray.</p>


<p>Mental ray permet déjà de "merger" des maps de Final Gather, mais l’intégration dans Maya ne permet pas de faire ça de manière temporelle simplement.</p>


<h3>La scène</h3>

<p>J'ai pris le genre typique de scène qui met à genou le Final Gather (et la plupart des méthodes de chaching de GI de manière générale):</p>
<ul>
<li>Aucune light (<em>Default Light</em> désactivées).</li>
<li>Un couloir blanc.</li>
<li>Du coté non visible de la caméra: Une plaque avec un material émissive blanc.</li>
<li>A l'intersection: Des sphère et des cubes colorés animés.</li>
<li>Et de l'autre coté, notre camera.</li>
</ul>

<p><a href="media/65f58a38.fg_diminuer_flicking_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_001.png" title="fg_diminuer_flicking_001.png"><img src="media/b1ddc688..fg_diminuer_flicking_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/.fg_diminuer_flicking_001_m.jpg" alt="fg_diminuer_flicking_001.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_001.png, juil. 2013"  height="470" width="560" /></a></p>


<p><a href="media/3d50d1bf.fg_diminuer_flicking_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_003.png" title="fg_diminuer_flicking_003.png"><img src="media/a73f4559..fg_diminuer_flicking_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/.fg_diminuer_flicking_003_m.jpg" alt="fg_diminuer_flicking_003.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_003.png, juil. 2013"  height="420" width="560" /></a></p>
<center>C'est un cas extrême, ne l’oublions pas. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></center>



<p><img src="media/f9ed10fa.fg_diminuer_flicking_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_002.png" alt="fg_diminuer_flicking_002.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_002.png, juil. 2013"  height="408" width="405" /></p>


<p>Le nombre de rebonds diffus du Final Gather est volontairement élevés pour gonfler les artefacts. Tout est présent pour avoir quelque chose de bien dégueulasse. <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<h3>Final Gather sans interpolation</h3>

<p>Voici un rendu de la scène avec un Final Gather calculé à chaque frame, sans interpolation (Mode <em>Automatic</em>):</p>


<p><img src="media/97fce1ff.fg_anim_001.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_001.gif" alt="fg_anim_001.gif" style="display:block; margin:0 auto;" title="fg_anim_001.gif, juil. 2013"  height="240" width="320" /></p>


<p>Comme vous pouvez le voir, ça flick pas mal. <img src="media/ef3897e4.ideenoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/ideenoire.gif" alt=":ideenoire:" class="smiley" /></p>


<p>Comment résoudre ça? <a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/fg_copy.html" hreflang="en">fg_copy</a> est ton amis! <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> (Plus spécifiquement, l'option <em>-f</em>).</p>


<p>Bon, en fait il est déjà possible de donner des maps de Final Gather à Maya pour qu'il les merges avant rendu. C'est d’ailleurs cette approche qui va servir de base à notre "interpolation temporelle".</p>


<h3>Interpoler les frames?</h3>


<p>En gros, le principe consiste simplement à "mélanger" plusieurs maps de Final Gather entre elles pour atténuer l'effet de flicking.</p>


<p>Pour une frame <em>n</em>, on merge les maps de Final Gather <em>n</em>-2, <em>n</em>-1, <em>n</em>, <em>n</em>+1, et <em>n</em>+2 (deux avants, deux après).</p>


<p>Dans la pratique, mental ray va mélanger les points de Final Gather ayant des normales similaires en utilisant le <em>Min Radius</em> de la scène. Deux points de Final Gather ayant une normale similaire (Je suppose que c'est le paramètre <em>Normal Tolerance</em> de la section <em>Final Gather Quality</em> qui est utilisé) et dont la distance n’excède pas le <em>Min Radius</em> de la scène (qui, si il est à zéro, correspond à 10% du diamètre de la scène) voient leur couleur et leur position mélangées.</p>


<p>Vous pouvez voir la taille de la scène que mental ray utilise dans le log:</p>
<pre>
RC   0.2     41 MB info : scene extent: (-12.34,-0.45,-17.07) : (15.83,10.96,12.07)
</pre>


<p>Cette approche est loin d'être parfaite et vous verrez qu'elle ne résout pas tous les problèmes. En effet, l'effet de <em>ghosting</em> <a name="ghosting"></a> qu'elle génère, bien que plus acceptable qu'un flicking par frame, reste particulièrement disgracieux, en particulier sur les rendus avec peu de textures/variations de couleurs (surfaces "douces"). Cela dit, cet effet peut passer totalement inaperçu sur certaines séquences (notamment les mouvements de caméra), c'est donc au cas par cas.</p>


<h3>Baker le Final Gather</h3>

<p>Pour pouvoir merger les maps de Final Gather avant rendu (5 maps dans notre cas) il faut, dans un premier temps, toutes les générer. Et c'est ce qu'on va faire. <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /></p>


<p>Comme il va s'agir de deux fg maps avant et deux fg maps après, pour un frame range de 101 à 110, on a donc les maps de Final Gather de l'image 99 à l'image 112.</p>


<p>Personnellement, je procède par <em>RenderLayers</em> en overridant les scripts <em>Pre render frame MEL</em> et <em>Post render frame MEL</em> pour entrer le nom de la fg maps à la valeur de la frame courante (<em>fgmap.0012.fgmap</em> par exemple) juste avant que le rendu ne se lance.</p>


<p><img src="media/54feb391.fg_diminuer_flicking_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_004.png" alt="fg_diminuer_flicking_004.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_004.png, juil. 2013"  height="200" width="374" /></p>


<p>Par exemple, pour le <em>RenderLayer</em> qui va générer les fg maps, j'override avec ça:</p>

<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.updateFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>Bon, c'est pas super sexy mais comme vous le savez, les <em>Pre render frame MEL</em> et <em>Post render frame MEL</em> ne supporte que... Le MEL... On demande donc à du MEL d’exécuter du Python! <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


<p>En mode "lisible", les deux appels sont les suivants:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> preframe
<span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>preframe<span style="color: black;">&#41;</span>
preframe.<span style="color: black;">updateFgFiles</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Et:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> preframe
<span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>preframe<span style="color: black;">&#41;</span>
preframe.<span style="color: black;">cleanFgParams</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Et bien entendu, il y a un petit fichier <em>preframe.py</em> à placer dans votre: <em>maya\scripts</em>.</p>


<h4>Le script</h4>

<p>Voici le contenu du <em>preframe.py</em>, contenu que je vais détailler, fonction après fonction.</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> updateFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	fgmapFile = <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># &quot;fgmap.0012.fgmap&quot;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Set fgmap file for frame %s -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>frame, fgmapFile<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Rebuild On</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, fgmapFile, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> prepareFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Freeze</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>Vous pouvez vous copier ça dans un <em>maya/scripts/preframe.py</em>.</p>


<h5>cleanFgParams()</h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[4]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[5]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>Cette fonction vide les entrées des attributs de <em>file</em> du Final Gather (met une chaine de caractère vide). Elle est utilisée juste avant de setter les noms des maps de Final Gather à sauver, et juste après (en <em>Post render frame</em>), pour être sur de vider les champs de texte.</p>


<h5>updateFgFiles()</h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> updateFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	fgmapFile = <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># &quot;fgmap.0012.fgmap&quot;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Set fgmap file for frame %s -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>frame, fgmapFile<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Rebuild On</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, fgmapFile, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>Cette fonction est utilisé en <em>Pre render frame</em> du <em>RenderLayer</em> et sert à donner un nom correct de map de Final Gather à sauver. Elle récupère le numéro de la frame courante et génère un nom de fg map à la frame.</p>


<p>Le petit "bricolage":</p>
<pre class="python python"><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span></pre>

<p>Sert à transformer le numéro de la frame en chaine de caractère (string) puis de lui appliquer un <em>zero fill</em> de 4, pour transformer "10" en "0010" par exemple.</p>


<h5>prepareFgFiles() <a name="prepareFgFiles"></a></h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> prepareFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Freeze</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>Et dernière fonction, en <em>Pre render frame</em> du <em>RenderLayer</em>, qui sert à remplir tous les champs de maps à merger lors du rendu finale. C'est le même mécanisme de génération des numéros de frame mais on en génère deux avant et deux après.</p>


<p>A ce moment là, vous avez un Final Gather en mode <em>Freeze</em>, qui va merger vos fichiers avant de les utiliser tel quel.</p>


<h3>Les render layers</h3>

<p>Voici une petite description de mes <em>RenderLayers</em>. :)</p>


<p><img src="media/ed9af1c5.fg_diminuer_flicking_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_005.png" alt="fg_diminuer_flicking_005.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_005.png, juil. 2013"  height="183" width="419" /></p>


<p>Oubliez FG_RAW qui ne servait qu'à rendre en mode <em>Automatic</em>.</p>


<h4>masterLayer</h4>

<p>Le <em>RenderLayer</em> de base est préparé de manière à recevoir les <em>Secondary FinalGather Maps</em>.</p>


<p><img src="media/ba9a0a03.fg_diminuer_flicking_009.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_009.png" alt="fg_diminuer_flicking_009.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_009.png, juil. 2013"  height="289" width="456" /></p>


<p>Notez que, comme tous les multiattributs de Maya, si ces valeurs sont vides, les blocs sont supprimés à l'ouverture de la scène. C'est la raison pour laquelle je met le mot <em>temp</em> dedans. Dans tous les cas, je supprime ces valeurs juste avant le rendu de la frame (via la fonction <em>cleanFgParams()</em> si vous avez suivi). C'est uniquement pour empêcher Maya de supprimer les entrées (Workaroundman! <img src="media/82beb7c8.diable.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/diable.gif" alt=":nousfesonslemal:" class="smiley" /> ).</p>


<blockquote><p>Note: Chaque entrée à un <em>temp</em> avec un numéro différent juste pour que je puisse rendre le <em>RenderLayer</em> FG_RAW sans que mental ray tente de merger une fg map qu'il est en train de générer.</p></blockquote>


<p>Mais en principe, jamais une map de Final Gather nommé "temp" ne devrait être créé durant notre process. Si c'est le cas c'est que quelque chose ne marche pas. <img src="media/af8fdcdb.zinzin.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/zinzin.gif" alt=":zinzin:" class="smiley" /></p>


<h4>FGMAPONLY</h4>

<p>Ce <em>RenderLayer</em> sera le premier lancé. C'est celui qui générera les maps de Final Gather (avec deux frames avant et deux frames après).</p>


<p>Les <em>Pre render frame MEL</em> et <em>Post render frame MEL</em> à overrider (via <a href="http://download.autodesk.com/global/docs/maya2014/en_us/index.html?url=files/Vari_Work_with_attribute_overrides.htm,topicNumber=d30e650035" hreflang="en">Create Layer Override</a>) sont les suivants:</p>
<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.updateFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>Il ne faut pas oublier de passer ce <em>RenderLayer</em> en <em>Multiframe</em> (<em>Optimize for Animation</em> dans Maya). Mais l'attribut n'est pas overrideable depuis l'interface. <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></p>


<p><img src="media/338ab0f8.fg_diminuer_flicking_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_006.png" alt="fg_diminuer_flicking_006.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_006.png, juil. 2013"  height="201" width="450" /></p>


<p>Il faut passer par le node <em>miDefaultOptions</em> que vous pouvez sélectionnez en tapant la commande MEL suivante:</p>
<pre class="mel mel">select miDefaultOptions</pre>

<p>Et en allant chercher le <em>Final Gather Mode</em> dans les <em>Extra Attributes</em>:</p>


<p><img src="media/56ec3924.fg_diminuer_flicking_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_007.png" alt="fg_diminuer_flicking_007.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_007.png, juil. 2013"  height="116" width="306" /></p>


<p>Simple comme bonjours... <img src="media/f44dab51.mayaProf.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mayaProf.gif" alt=":mayaProf:" class="smiley" /></p>


<p>Comme l'image rendue à ce moment là ne nous sert pas, vous pouvez overrider le <em>Render Mode</em> pour ne rendre que l'étape de Final Gather:</p>


<p><img src="media/73bc43c8.fg_diminuer_flicking_005a.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_005a.png" alt="fg_diminuer_flicking_005a.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_005a.png, juil. 2013"  height="83" width="420" /></p>


<h4>RENDERONLY</h4>

<p>C'est dans ce <em>RenderLayer</em> que sera fait le "vrai" rendu. L'idée étant de setter les différentes fg maps (<em>n</em>-2, <em>n</em>-1, <em>n</em>, <em>n</em>+1 et <em>n</em>+2) pour que mental ray les merges en <em>Freeze</em> (pas de rebuild), et nous calcule le résultat final.</p>

<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.prepareFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>Je vous invite à relire la fonction <a href="http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Diminuer-le-flicking-du-final-gather#prepareFgFiles">prepareFgFiles()</a> pour bien comprendre ce qu'on fait.</p>


<h3>La ligne de commande</h3>


<p>Et vient le moment de lancer le rendu! <img src="media/94b95129.popcorn.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/popcorn.gif" alt=":popcorn:" class="smiley" /></p>


<p>Je vous donne les deux lignes de batch pour que vous puissiez vous en inspirer:</p>
<pre>
&quot;C:\Program Files\Autodesk\Maya2013\bin\render.exe&quot; -mr:v 4 -mr:rt 4 -cam camera1 -rl FGMAPONLY -s 99 -e 126 -preFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.updateFgFiles()\&quot;)&quot; -postFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.cleanFgParams()\&quot;)&quot; -proj &quot;D:\3D\VracProject&quot; &quot;D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma&quot;
&quot;C:\Program Files\Autodesk\Maya2013\bin\render.exe&quot; -mr:v 4 -mr:rt 4 -cam camera1 -rl RENDERONLY -preFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.prepareFgFilesNoAnim()\&quot;)&quot; -postFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.cleanFgParams()\&quot;)&quot; -proj &quot;D:\3D\VracProject&quot; &quot;D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma&quot;
</pre>


<blockquote><p>Note: J'ai personnellement rencontré quelques soucis avec les overrides des <em>Pre render frame MEL</em> et <em>Post render frame MEL</em>. C'est la raison pour laquelle je les écris "en dur" dans la ligne de commande.</p></blockquote>


<h4>La génération des maps de Final Gather (première ligne)</h4>

<p>A la fin de l’exécution de la première ligne, vous deviez avoir quelque chose dans le dossier <em>renderData/mentalray/finalgMap</em> qui ressemble à ça:</p>


<p><img src="media/6b086dc3.fg_diminuer_flicking_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_008.png" alt="fg_diminuer_flicking_008.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_008.png, juil. 2013"  height="418" width="351" /></p>


<h4>Seconde ligne, le rendu!</h4>

<p>Ne tergiversons pas.</p>


<p>Avant:
<img src="media/97fce1ff.fg_anim_001.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_001.gif" alt="fg_anim_001.gif" style="display:block; margin:0 auto;" title="fg_anim_001.gif, juil. 2013"  height="240" width="320" /></p>


<p>Après:
<img src="media/89f6e8ba.fg_anim_002.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_002.gif" alt="fg_anim_002.gif" style="display:block; margin:0 auto;" title="fg_anim_002.gif, juil. 2013"  height="240" width="320" /></p>
<center>FG Merge. Parce que je le vaux bien. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></center>



<p>Bon, j’admets que le gif n'est pas ce qu'il y a de mieux pour juger de la qualité d'une image mais vous remarquerez que c'est beaucoup plus stable. Vous remarquerez aussi sur le mur droit, l'effet de ghosting <a href="http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Diminuer-le-flicking-du-final-gather#ghosting">dont je parlais</a> précédemment.</p>


<p>Encore une fois, on est dans un cas extrême:</p>
<ul>
<li>Une surface émissive, aucune source de lumière direct.</li>
<li>Un couloir.</li>
<li>Des paramètres de rebonds élevés.</li>
<li>Des paramètres de qualité de Final Gather bas.</li>
</ul>

<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/tuto_flick_mr_maponly.7z">Voici la scène</a> pour que vous puissiez voir un peu les paramètres.</p>


<p>Important: Suivez bien vos logs car (et je ne trouve pas ça super <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> ) le mode <em>Freeze</em> n'est pas aussi bête qu'il en a l'air (<a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/options.html#finalgathering" hreflang="en">voir doc</a>). Si une map de Final Gather n'existe pas pas, il la créé quand même. Vous aurez donc l'impression qu'à la fin de ces deux lignes tout c'est bien passé (les map de Final Gather sont là ainsi que les images) mais tout flickera...</p>


<p>Quelques infos à vérifier (exemple pour le calcule de la frame 123):</p>
<pre>
RC   0.2     26 MB info : option:   rebuild         freeze
RC   0.2     26 MB info : option:   files           D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0121.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0122.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0123.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0124.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0125.fgmap
</pre>
<pre>
RCFG 0.2     27 MB info : finalgather map is frozen, using loaded from file(s)
</pre>


<p>Je vous invite donc, dans un premier temps, à lancer ces deux lignes séparéments et à vous assurer du résultat entre chacune.</p>


<p>J'insiste sur le fait que vous n'y arriverez pas forcément du premier coup. Il y a pas mal de choses à faire mine de rien. Donc persévérez et sachez que c'est possible. <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<h3>Variante</h3>

<p>Comme vous pouvez le constater, le flicking des objets animés (sphères et cube) ne change pas des masses. On peut donc envisager plusieurs variantes pour résoudre le soucis.</p>


<p>La première approche consiste à générer deux séquence de fg map distinctes:</p>
<ul>
<li>L'une uniquement pour les objets animé (on passe les objets statiques en <em>primary rays</em> off) avec des paramètres de Final Gather plus élevés. Nommé <em>fg_anim.####.fgmap</em>.</li>
<li>L'autre uniquement pour les objets statiques (on passe les objets animés en <em>primary rays</em> off de manière à conserver leurs rebonds diffus sur la fg map des objets statiques). Nommé <em>fg_static.####.fgmap</em>.</li>
<li>Et on merge l'ensemble après.</li>
</ul>

<p>On peut aussi aller un cran au dessus dans la complexité (au point ou on en est <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> ) et utiliser la commande <a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/fg_copy.html" hreflang="en">fg_copy</a> pour merger les fg maps d'anim avec un radius plus élevé pour aller chercher les points de Final Gather plus loins dans l'espace. Cela dit, je ne suis pas sur que cette méthode offre de meilleurs résultats mais c'est à tester.</p>


<p>Et enfin, vous pouvez <a href="http://www.fevrierdorian.com/blog/post/2013/02/10/Combiner-les-importons-avec-le-Final-Gather">combiner ça avec les importons</a> pour avoir de meilleur points de Final Gather. :)</p>


<h3>Conclusion</h3>

<p>Je pensais que c'était impossible mais finalement, on peut bien "faker" l'option <a href="http://www.spot3d.com/vray/help/maya/150R1/render_params_advancedimap.htm#basic" hreflang="en">Interp. samples</a> de Vray dans mental ray. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>Bien sur, faire ça de cette manière n'est pas forcément super évident, et il est une fois de plus regrettable de devoir se battre à ce point pour profiter d'un feature accessible via un simple slider dans Vray... <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>Toutefois, j'espère que ce billet vous aura intéressé et que vous y avez appris des choses. Je pense que si on arrive à mettre ce genre de système en place, on diminue pas mal l'un des principaux soucis du Final Gather (ou techniques similaires) dans les animations.</p>


<p>N'hésitez pas à me faire des retours dans les commentaires si il manque des éléments. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>A bientôt!</p>


<p>Dorian</p>
<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


feed_id: urn:md5:0a9ec9489fde5e36a8bae4182f717d0d
title: Mental ray for Maya: Decrease Final Gather flicking
uri: Mental-ray-for-Maya-Decrease-Final-Gather-flicking
url:
http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Decrease-Final-Gather-flicking

content:
<p><img src="media/cf3f6048.fg_diminuer_flicking_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_tn.png" alt="fg_diminuer_flicking_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fg_diminuer_flicking_tn.png, juil. 2013"  height="150" width="150" />In this ticket, I present a <del>simple way</del> hack (keep in mind we are talking about mental ray for Maya <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> ) to drastically decrease Final Gather flicking.</p>


<p>You will see this method is a little tricky but it simply aims to reproduce the <a href="http://www.spot3d.com/vray/help/maya/150R1/render_params_advancedimap.htm#basic" hreflang="en">Interp. samples</a> Vray's option behavior.</p>    <h3>Foreword</h3>


<p>Before start, know that it's truly Vray which prompted me to put my nose in mental ray, especially Final Gather map merging. While everything is very simple in Vray, in mental ray, it's a pain (as usual <img src="media/27323fb5.mad0001.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mad0001.gif" alt=":septic:" class="smiley" /> ).</p>


<p>Basically you will have to inject scripts in the <em>Pre render frame MEL</em> and <em>Post render frame MEL</em> ​​to recreate the behavior of Vray.</p>


<p>Mental ray actually provide a way to merge Final Gather maps, but Maya integration doesn't do it temporally (no Final Gather map with frame number name).</p>


<h3>The scene</h3>

<p>I took the typical kind of scene that brings Final Gather to its knees (and most GI caching methods in general):</p>
<ul>
<li>No lights (<em>Default Light</em> disabled).</li>
<li>A white corridor.</li>
<li>From the invisible-to-the-camera side: A plane with a white emissive material.</li>
<li>At the crossroads: Animated colorful spheres and cubes.</li>
<li>And from the other side, our camera.</li>
</ul>

<p><a href="media/65f58a38.fg_diminuer_flicking_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_001.png" title="fg_diminuer_flicking_001.png"><img src="media/b1ddc688..fg_diminuer_flicking_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/.fg_diminuer_flicking_001_m.jpg" alt="fg_diminuer_flicking_001.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_001.png, juil. 2013"  height="470" width="560" /></a></p>


<p><a href="media/3d50d1bf.fg_diminuer_flicking_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_003.png" title="fg_diminuer_flicking_003.png"><img src="media/a73f4559..fg_diminuer_flicking_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/.fg_diminuer_flicking_003_m.jpg" alt="fg_diminuer_flicking_003.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_003.png, juil. 2013"  height="420" width="560" /></a></p>
<center>Keep in mind: This is an extreme case. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></center>



<p><img src="media/f9ed10fa.fg_diminuer_flicking_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_002.png" alt="fg_diminuer_flicking_002.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_002.png, juil. 2013"  height="408" width="405" /></p>


<p>The Final Gather diffuse bounces number is high to increase visual artectacts. Everything is here to have something awful. <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></p>


<h3>Final Gather without interpolation</h3>

<p>There is a render of the scene with Final Gather generated for each frame, without interpolation (Mode <em>Automatic</em>):</p>


<p><img src="media/97fce1ff.fg_anim_001.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_001.gif" alt="fg_anim_001.gif" style="display:block; margin:0 auto;" title="fg_anim_001.gif, juil. 2013"  height="240" width="320" /></p>


<p>As you can see, there is a lot of flicking. <img src="media/ef3897e4.ideenoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/ideenoire.gif" alt=":ideenoire:" class="smiley" /></p>


<p>How to solve this? <a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/fg_copy.html" hreflang="en">fg_copy</a> is your friend! <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> (Specially the <em>-f</em> flag).</p>


<p>Well, acutally, there is already a way to give Final Gather maps to Maya to make them merged before render. This way will be the foundation to our "temporal interpolation".</p>


<h3>Interpolate frames?</h3>


<p>Basically, the idea is simply to "mix" several Final Gather maps together to mitigate the effect of flicking.</p>


<p>For a frame <em>n</em>, we merge Final Gather maps <em>n</em>-2, <em>n</em>-1, <em>n</em>, <em>n</em>+1, and <em>n</em>+2 (two before, two after).</p>


<p>In practice, mental ray will merge Final Gather points with similar normal using <em>Min Radius</em> of the scene. Two Final Gather points having a similar normal (I suppose the <em>Normal Tolerance</em> of the <em>Final Gather Quality</em> section is used to control that) and where the distance doesn't execeed the <em>Min Radius</em> of the scene (if set to zero is 10% of the whole scene bouding box) have their color and position merged.</p>



<p>You can see the scene size mental ray is rendering using the log:</p>
<pre>
RC   0.2     41 MB info : scene extent: (-12.34,-0.45,-17.07) : (15.83,10.96,12.07)
</pre>


<p>This approach is far from perfect and you will see it doesn't solve all problems. The <em>ghosting</em> <a name="ghosting"></a> you can have, better than a by frame flicking though, is still unsightly, particularly on renders with few texture/color variations (diffuse surfaces). That said, this effect may go unnoticed on some sequences (especially camera movements), it really depends on what you've got.</p>


<h3>Bake Final Gather</h3>

<p>To be able to merge Final Gather maps before render (5 maps in our case) you must, as a first step, generate all of them. And this is what we will do. <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /></p>


<p>As we have a range of 101-110 and we will generate two frame before and two frame after, the final Final Gather maps sequence will be 99-112.</p>


<p>Personnally, I use <em>RenderLayers</em> overriding <em>Pre render frame MEL</em> and <em>Post render frame MEL</em> scripts to generate fg map names using the current frame (eg: <em>fgmap.0012.fgmap</em>) just before render start.</p>


<p><img src="media/54feb391.fg_diminuer_flicking_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_004.png" alt="fg_diminuer_flicking_004.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_004.png, juil. 2013"  height="200" width="374" /></p>


<p>For example, I override the <em>RenderLayer</em> that will be used to generate fg maps with this:</p>

<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.updateFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>Ok, that's not really sexy but as you know, <em>Pre render frame MEL</em> and <em>Post render frame MEL</em> only execute... MEL... So we ask MEL to execute Python! <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>


<p>In a "readeable" mode, the two calls are followings:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> preframe
<span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>preframe<span style="color: black;">&#41;</span>
preframe.<span style="color: black;">updateFgFiles</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>And:</p>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> preframe
<span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>preframe<span style="color: black;">&#41;</span>
preframe.<span style="color: black;">cleanFgParams</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Of course, there is a little <em>preframe.py</em> in your: <em>maya\scripts</em>.</p>


<h4>The script</h4>

<p>Here is the contents of <em>preframe.py</em>, contents that I will explain, function by function.</p>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> maya.<span style="color: #dc143c;">cmds</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">cmds</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> updateFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	fgmapFile = <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># &quot;fgmap.0012.fgmap&quot;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Set fgmap file for frame %s -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>frame, fgmapFile<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Rebuild On</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, fgmapFile, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> prepareFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Freeze</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>You can copy this in a file in <em>maya/scripts/preframe.py</em>.</p>


<h5>cleanFgParams()</h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[4]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[5]&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>This function clears the Final Gather <em>file</em> attributes (put an empty string). It's called just before setting the name of the Final Gather maps to save, and just after render, in <em>Post render frame</em>, to be sure to clear text fields.</p>


<h5>updateFgFiles()</h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> updateFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	fgmapFile = <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># &quot;fgmap.0012.fgmap&quot;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Set fgmap file for frame %s -&gt; %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>frame, fgmapFile<span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Rebuild On</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, fgmapFile, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>This function is set in the <em>Pre render frame</em> attribute of the <em>RenderLayer</em> and is used to give a correct name to the Final Gather map to save. It gets the current frame and generates a fg map name with the frame number.</p>


<p>The little "hack":</p>
<pre class="python python"><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span></pre>

<p>Used to generate the frame number with padding. Converting it to string first then apply a <em>zero fill</em> of 4, to make "10" to "0010" for example.</p>


<h5>prepareFgFiles() <a name="prepareFgFiles"></a></h5>
<pre class="python python"><span style="color: #ff7700;font-weight:bold;">def</span> prepareFgFiles<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
	cleanFgParams<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	frame = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmds</span>.<span style="color: black;">currentTime</span><span style="color: black;">&#40;</span> query=<span style="color: #008000;">True</span> <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherRebuild&quot;</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># Freeze</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherFilename&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[0]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[1]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame<span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[2]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">cmds</span>.<span style="color: black;">setAttr</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;miDefaultOptions.finalGatherMergeFiles[3]&quot;</span>, <span style="color: #483d8b;">&quot;fgmap.%s.fgmap&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>frame+<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">zfill</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#41;</span></pre>

<p>And the last function, in <em>Pre render frame</em> of the <em>RenderLayer</em>, used to fill every text fields with Final Gather maps to merge during final render. This is the same method we used to generate Final Gather map name but we generate two before and two after.</p>


<p>This is where you put Final Gather mode to <em>Freeze</em> to ensure you will merge your files before using them as such.</p>


<h3>Render layers</h3>

<p>There is a little description of my <em>RenderLayers</em>. :)</p>


<p><img src="media/ed9af1c5.fg_diminuer_flicking_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_005.png" alt="fg_diminuer_flicking_005.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_005.png, juil. 2013"  height="183" width="419" /></p>


<p>Don't worry about FG_RAW, it's only used to render in <em>Automatic</em> mode.</p>


<h4>masterLayer</h4>

<p>The main <em>RenderLayer</em> is prepared in order to get <em>Secondary FinalGather Maps</em>.</p>


<p><img src="media/ba9a0a03.fg_diminuer_flicking_009.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_009.png" alt="fg_diminuer_flicking_009.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_009.png, juil. 2013"  height="289" width="456" /></p>


<p>Note that, as all Maya's multi-attributes, if this values are empty, blocks are removed while reopening the scene. That's why I put the <em>temp</em> words in it. In any case, I remove this values just before frame render start (using the <em>cleanFgParams()</em> function). That's only to prevent Maya to remove entries (Workaround time!).</p>


<blockquote><p>Important: Each entry has a <em>temp</em> with a different number just so I can render the FG_RAW <em>RenderLayer</em> avoiding mental ray to try to merge a fg map it is actually generating.</p></blockquote>


<p>But there shouldn't ever be any Final Gather map named "temp" in your fg map folder. If there is, something has gone wrong during our process. <img src="media/af8fdcdb.zinzin.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/zinzin.gif" alt=":zinzin:" class="smiley" /></p>


<h4>FGMAPONLY</h4>

<p>This <em>RenderLayer</em> will be the first started. It's the one that will generate Final Gather maps (with two frames before and two frames after).</p>


<p><em>Pre render frame MEL</em> and <em>Post render frame MEL</em> to override (using <a href="http://download.autodesk.com/global/docs/maya2014/en_us/index.html?url=files/Vari_Work_with_attribute_overrides.htm,topicNumber=d30e650035" hreflang="en">Create Layer Override</a>) are followings:</p>
<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.updateFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>Don't forget to put this <em>RenderLayer</em> in <em>Multiframe</em> (<em>Optimize for Animation</em> in Maya). But the attribute can't be override from the <em>Render Settings</em>. <img src="media/d0c5449f.trollface_smiley.png" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/trollface_smiley.png" alt=":trollface:" class="smiley" /></p>


<p><img src="media/338ab0f8.fg_diminuer_flicking_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_006.png" alt="fg_diminuer_flicking_006.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_006.png, juil. 2013"  height="201" width="450" /></p>


<p>You must go through the <em>miDefaultOptions</em> node you can select typing this MEL command:</p>
<pre class="mel mel">select miDefaultOptions</pre>

<p>And looking for <em>Final Gather Mode</em> in <em>Extra Attributes</em>:</p>


<p><img src="media/56ec3924.fg_diminuer_flicking_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_007.png" alt="fg_diminuer_flicking_007.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_007.png, juil. 2013"  height="116" width="306" /></p>


<p>Easy as 1-2-3... <img src="media/f44dab51.mayaProf.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mayaProf.gif" alt=":mayaProf:" class="smiley" /></p>


<p>As there is no interest to keep the image rendered during this process, you can override <em>Render Mode</em> to make mental ray compute only Final Gather:</p>


<p><img src="media/73bc43c8.fg_diminuer_flicking_005a.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_005a.png" alt="fg_diminuer_flicking_005a.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_005a.png, juil. 2013"  height="83" width="420" /></p>


<h4>RENDERONLY</h4>

<p>It's in this <em>RenderLayer</em> the "real" render will be done. The idea is to set the differents fg maps (<em>n</em>-2, <em>n</em>-1, <em>n</em>, <em>n</em>+1 et <em>n</em>+2) to make mental ray merging them in <em>Freeze</em> (no rebuild), and compute the final render.</p>

<pre class="mel mel">python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.prepareFgFiles()&quot;</span><span style="color: #009900;">&#41;</span>
python<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;import preframe<span style="color: #000099; font-weight: bold;">\n</span>reload(preframe)<span style="color: #000099; font-weight: bold;">\n</span>preframe.cleanFgParams()&quot;</span><span style="color: #009900;">&#41;</span></pre>


<p>I encourage you to read the <a href="http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Decrease-Final-Gather-flicking#prepareFgFiles">prepareFgFiles()</a> function to fully understand what we do.</p>


<h3>Command line</h3>


<p>And it's time to start rendering! <img src="media/94b95129.popcorn.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/popcorn.gif" alt=":popcorn:" class="smiley" /></p>


<p>I give you my two batch command line to help you:</p>
<pre>
&quot;C:\Program Files\Autodesk\Maya2013\bin\render.exe&quot; -mr:v 4 -mr:rt 4 -cam camera1 -rl FGMAPONLY -s 99 -e 126 -preFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.updateFgFiles()\&quot;)&quot; -postFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.cleanFgParams()\&quot;)&quot; -proj &quot;D:\3D\VracProject&quot; &quot;D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma&quot;
&quot;C:\Program Files\Autodesk\Maya2013\bin\render.exe&quot; -mr:v 4 -mr:rt 4 -cam camera1 -rl RENDERONLY -preFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.prepareFgFilesNoAnim()\&quot;)&quot; -postFrame &quot;python(\&quot;import preframe\nreload(preframe)\npreframe.cleanFgParams()\&quot;)&quot; -proj &quot;D:\3D\VracProject&quot; &quot;D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma&quot;
</pre>


<blockquote><p>Notice: I've personally encounter few problems with <em>Pre render frame MEL</em> and <em>Post render frame MEL</em> overrides. That's the reason why I "hard" write them in the commande line.</p></blockquote>


<h4>Generating Final Gather maps (first line)</h4>

<p>In the end of the first line execution, you should have the folder <em>renderData/mentalray/finalgMap</em> with something like:</p>


<p><img src="media/6b086dc3.fg_diminuer_flicking_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_diminuer_flicking_008.png" alt="fg_diminuer_flicking_008.png" style="display:block; margin:0 auto;" title="fg_diminuer_flicking_008.png, juil. 2013"  height="418" width="351" /></p>


<h4>Second line, render!</h4>

<p>Aaaaaaaand:</p>


<p>Before:
<img src="media/97fce1ff.fg_anim_001.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_001.gif" alt="fg_anim_001.gif" style="display:block; margin:0 auto;" title="fg_anim_001.gif, juil. 2013"  height="240" width="320" /></p>


<p>After:
<img src="media/89f6e8ba.fg_anim_002.gif" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/fg_anim_002.gif" alt="fg_anim_002.gif" style="display:block; margin:0 auto;" title="fg_anim_002.gif, juil. 2013"  height="240" width="320" /></p>
<center>FG Merge. Because I'm worth it. <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /></center>



<p>Ok, I admit gif is not the best thing to assess the image quality but you will notice it's a lot more stable. You will notice too, on the right wall, the ghosting effect <a href="http://www.fevrierdorian.com/blog/post/2013/07/20/Mental-ray-for-Maya-Decrease-Final-Gather-flicking#ghosting">I was talking about</a>.</p>


<p>Once again, it's an extreme case:</p>
<ul>
<li>No direct lighting.</li>
<li>An emissive surface.</li>
<li>A corridor.</li>
<li>High number of bouces.</li>
<li>Low Final Gather quality parameters.</li>
</ul>

<p><a href="http://www.fevrierdorian.com/blog/public/billets/2013_07_20_Mental_ray_final_gather_diminuer_flicking/tuto_flick_mr_maponly.7z">There is the scene</a> so you can see parameters and try all of this yourself.</p>


<p>Important: Keep an eye on you logs because (and I don't think it's "good" <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> ) <em>Freeze</em> mode is not as stupid it seems to be (<a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/options.html#finalgathering" hreflang="en">see the doc</a>). If a Final Gather map don't exists, it create it anyway. You will so have the impression, when the two batch lines will ends, that everything passed well (Final Gather maps are there and images so) but everything will flick...</p>


<p>Few informations you should keep an eye on (example for the frame 123):</p>
<pre>
RC   0.2     26 MB info : option:   rebuild         freeze
RC   0.2     26 MB info : option:   files           D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0121.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0122.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0123.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0124.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0125.fgmap
</pre>
<pre>
RCFG 0.2     27 MB info : finalgather map is frozen, using loaded from file(s)
</pre>


<p>I encourage you, as a first step, to start these two lines separately and check everything passed well between them.</p>


<p>I insist on the fact that you will not necessary succeed the first time. There is actually a lot of things to do. So persevere and keep in mind "this is possible". <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


<h3>Variant</h3>

<p>As you can see, flicking of animated objects (spheres and cube) don't change too much. We can consider many variant to solve this problem.</p>


<p>The first approach is to generate two distinct Final Gather maps sequence:</p>
<ul>
<li>One only with animated objects (putting static objects in <em>primary rays</em> off) with higher Final Gather quality. Named <em>fg_anim.####.fgmap</em>.</li>
<li>The other only with static objects (putting animated objects in <em>primary rays</em> off in order to keep their diffuse bounces on the fg map). Named <em>fg_static.####.fgmap</em>.</li>
<li>And we merge everything just before render.</li>
</ul>

<p>We can also go a step up in complexity (while we're there... <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> ) and use the <a href="http://docs.autodesk.com/MENTALRAY/2014/ENU/mental-ray-help/files/manual/fg_copy.html" hreflang="en">fg_copy</a> command to merge animated object Final Gather maps with a higher radius to to get farther Final Gather points. That said, I'm not sure this approach produces better results but it has to be tested.</p>


<p>And last but not least, you can <a href="http://www.fevrierdorian.com/blog/post/2013/02/10/Combine-importons-with-Final-Gather-English-Translation">combine this with importons</a> to have better Final Gather points. :)</p>


<h3>Conclusion</h3>

<p>I was thinking it was impossible but we can actually "immitate" the <a href="http://www.spot3d.com/vray/help/maya/150R1/render_params_advancedimap.htm#basic" hreflang="en">Interp. samples</a> Vray option in mental ray. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>


<p>Of course, doing it this way is not necessarily easy, and it's again unfortunate having to fight to benefit a feature available using a simple slider in Vray... <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>


<p>However, I hope this post have interest you and that you've learned things. I think if you can put this kind of system in place, you solve the main concerns about Final Gather (or similar techniques) in animations.</p>


<p>Don't hesitate to feedbacks in comments if I missed some points/explaination you would like to have. <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>


<p>See you guys!</p>


<p>Dorian</p>
<center><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></center>


