# articles

feed_id: urn:md5:048393b24ce8cf3463760190f3e43edc
title: Exporter des curves d'anim et nettoyez le fichier .ma
uri: Exporter-des-curves-d-anim-et-nettoyez-le-fichier-ma
url:
http://www.fevrierdorian.com/blog/post/2013/06/08/Exporter-des-curves-d-anim-et-nettoyez-le-fichier-ma

content:
<p><img src="media/743a58b2.Python_logo_150.png" data-original-source="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" />Je sais pas pour vous mais moi ça me fatigue un peu que, suite à l'export de courbes d'anim Maya, lors de l'import, Maya essaie de me charger tous les plugins qui étaient présents au moment de l'export... <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>Je vous propose une petite suite d'expression régulière que j'utilise de temps à autres visant à nettoyer un fichier .ma de ces "requires" et autres "select" quand tout ce qui nous intéresse au fond ce sont des nodes "simples".</p>


<p>Je poste ce code principalement comme un aide mémoire auquel je me réfèrerai et qui pourrait vous servir. <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>    <blockquote><p>Important: Un fichier nettoyé de cette façon détruit toute référence à des plugins externes. Les courbes d'anims ne nécessitant pas de plugin particulier ce n'est pas un problème, mais soyez vigilant si vous souhaitez exporter des nœuds qui nécessitent un/des plugins pour pouvoir s'ouvrir.</p></blockquote>

<pre class="python python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<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>
&nbsp;
<span style="color: #808080; font-style: italic;"># selectionnez vos curves d'anim puis:</span>
animCurveFilePath = <span style="color: #483d8b;">&quot;/home/toto/myAnimCurves.ma&quot;</span>
<span style="color: #dc143c;">cmds</span>.<span style="color: #008000;">file</span><span style="color: black;">&#40;</span> animCurveFilePath            ,
           force          = <span style="color: #008000;">True</span>        ,
           exportSelected = <span style="color: #008000;">True</span>        ,
           <span style="color: #008000;">type</span>           = <span style="color: #483d8b;">&quot;mayaAscii&quot;</span> ,
           options        = <span style="color: #483d8b;">&quot;v=0&quot;</span>       <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on lit et stock le contenu</span>
myFile  = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span> animCurveFilePath, <span style="color: #483d8b;">&quot;r&quot;</span> <span style="color: black;">&#41;</span>
rawRead = myFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
myFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># puis on reecrit le fichier</span>
myFile  = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span> animCurveFilePath, <span style="color: #483d8b;">&quot;w&quot;</span> <span style="color: black;">&#41;</span>
rawRead = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;requires <span style="color: #000099; font-weight: bold;">\&quot;</span>.*;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>          , <span style="color: #483d8b;">&quot;&quot;</span>    , rawRead <span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># on supprime tous les &quot;requires&quot; des plugins</span>
rawRead = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;select(.*<span style="color: #000099; font-weight: bold;">\n</span>)*(select)&quot;</span>     , <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>2&quot;</span> , rawRead <span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># on supprime tous les &quot;select&quot; qui vont notamment modifier le node &quot;time1&quot;</span>
rawRead = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;select(.*<span style="color: #000099; font-weight: bold;">\n</span>)*(// End of )&quot;</span> , <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>2&quot;</span> , rawRead <span style="color: black;">&#41;</span>	<span style="color: #808080; font-style: italic;"># et le dernier &quot;select&quot; de fin de ligne</span>
myFile.<span style="color: black;">write</span><span style="color: black;">&#40;</span> rawRead <span style="color: black;">&#41;</span>
myFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Et voilà le travail! <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>Encore une fois ce n'est pas un tutorial, juste un partage rapide d'un truc que j'ai eu à utiliser plusieurs fois.</p>


<p>En espérant que ça vous aide.</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:bfffa7c4e38ece8de4f0ef6fccb0caee
title: Multithreading for Visual Effects book review
uri: Multithreading-for-Visual-Effects-book-review
url: http://www.fevrierdorian.com/blog/post/2014/08/24/Multithreading-for-Visual-Effects-book-review
content:
<p><img src="media/bea5c843.multithreading_for_vfx_review_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/multithreading_for_vfx_review_tn.png" alt="multithreading_for_vfx_review_tn.png" style="float:left; margin: 0 1em 1em 0;" title="multithreading_for_vfx_review_tn.png, août 2014"  height="150" width="150" />In programming, nothing is better than a good book. You will often ear that from many experienced programmers.</p>


<p>Today I want to share my humble review of <a href="http://www.crcpress.com/product/isbn/9781482243567" hreflang="en">Multithreading for Visual Effects</a>.</p>


<p>This book has been created after the <a href="http://s2013.siggraph.org/attendees/courses/events/multithreading-and-vfx" hreflang="en">Multithreading and VFX courses session</a> at Siggraph 2013 where some companies were presenting how they used multithreading in their tools. The results where so interesting they decide to gather them and make a book.</p>


<p>As this kind of <em>niche</em> book is rare in the CGI, let's talk about it! <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><a href="media/0c005d30.multithreading_for_vfx_review_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/multithreading_for_vfx_review_001.jpg" title="multithreading_for_vfx_review_001.jpg"><img src="media/d416ba65..multithreading_for_vfx_review_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/.multithreading_for_vfx_review_001_m.jpg" alt="multithreading_for_vfx_review_001.jpg" style="display:block; margin:0 auto;" title="multithreading_for_vfx_review_001.jpg, août 2014"  height="560" width="420" /></a></p>

<h3>Chapter 1: Introduction and Overview (by James Reinders)</h3>


<p>The prologue is an ode to multithreading (What a surprise <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> ). James Reinders is an engineer from Intel and we can say he know his job!</p>


<p>What I'd really liked is that multiple faces of multithreading are presented (multi task vs multi thread, vectorization, etc...), explaining technically how they work and giving pros and cons for each of them.</p>


<p>I must talk about how <a href="https://en.wikipedia.org/wiki/Threading_Building_Blocks" hreflang="en">TBB</a> is presented. In general TBB is considered as a serious choice for multithreading programs (Almost every program in the book use it). And from what I've read from the documentation, it deserves it. To be honest, TBB make we want to master C++ templates and I totally understand you would choose TBB if you are familiar with them.</p>


<p>But I regret James didn't spend more time and love presenting alternatives. I know it's a Intel guy but clearly, TBB receive a lot of emphasis and it totally hides the others. I think it's quiet a shame because a lot of chapters talk about TBB too. Alternatives are "presented" but not as in depth than TBB.</p>


<p>Anyway, you get the message: TBB is good, eat some! <img src="media/48a6a7fc.banane-jaune.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>


<h3>Chapter 2: Houdini: Multithreading Existing Software (by Jeff Lait)</h3>


<p><img src="media/67ce2585..houdini_black_s.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/.houdini_black_s.png" alt="houdini_black.png" style="display:block; margin:0 auto;" title="houdini_black.png, sept. 2014"  height="56" width="240" /></p>


<p>A lot of multithreading informations you can find here and there, even on books (including this one), are very academic. They explain how you <em>should</em> write code.</p>


<p>This chapter is interesting because it take the invert approach: How convert old code to modern multithreading. Jeff present different concrete problems and how they choosed to solve them, what they lost doing so and how, if it was possible, they can still save what can be.</p>


<p>What I really love in this chapter is how unacademic it is. Some example's code solution make you realize: "Yeah! I could do that... It's weird but it works pretty well!". The best examples are how Houdini handles the thread creation time (because create a thread is long actually) where the datas to compute doesn't worth the threads creation time. Easy trade of: If data_count &lt; 5000 : compute in the main thread! <img src="media/6bf85d36.IFuckTheWorld.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/IFuckTheWorld.gif" alt=":IFuckTheWorld:" class="smiley" /></p>


<p>You will never see this kind of solution on an academic book but you will never have more efficient that this! :D</p>


<p>Each case is interesting. While not relevant for a general experience, read them all train your brain in <em>why</em> you should avoid to do things like this and how to react when you see them.</p>


<p>I must confess I'd read <a href="media/7b30663d.MultithreadingHoudini.pdf" data-original-source="http://www.multithreadingandvfx.org/course_notes/MultithreadingHoudini.pdf" hreflang="en">the original Side Effect paper</a> after the Siggraph 2013. This make me realize some work has been done to reorganize and better explain the examples. I remember I were pretty lost with some examples in the original paper but it was not a problem with the book so I guess this examples where better explained (or my general programming skills has increase from that time).</p>


<p>This chapter was frustrating for me because I wanted to know more! More examples, more tricky problems to solve, more "here boys is what you've got if you write code this way".</p>


<p>If you want to know more about how Houdini works under the hood you can find this <a href="http://forums.odforce.net/topic/17105-short-and-sweet-op-centric-lessons/#entry104263" hreflang="en">very interesting post</a></p>


<h3>Chapter 3: The Presto Execution System: Designing for Multithreading (by George ElKoura)</h3>


<p>Interactivity is the key of this chapter.</p>


<p>The first part is not very interesting. George explain the technical goals and constrains they had. This is good, but he spend too much time on things you often know without explain what where the specific implication in Presto ("vectorization is important because blah blah", "you should organized you data because blah blah"). Its kind of redundant with the first chapter. I would have put every general multithreading stuff explained in the first chapter and let the study case focus on implementation.</p>


<p>However, the second part is very interesting. Here are the smart choices they had to do. The way they handle threads in Presto (especially how graph computation is separate) is very different than an "academic" graph network. Indeed, Presto had to deal with "time" because time is the animator toy. He also talk about interactivity and the relation betweens "batch" threads (responsive of math computation) and UI threads and how they tried to avoid any kind of lag in interactivity (interrupt or not interrupt, that is the question). It's very well explained while not enough detailed for my taste. They finish with a small (2 pages) concrete code example of how a "naive" geometric deformer code can be multithreaded. It's an interesting code snippet because it present a general problem (but he give a "general" solution).</p>


<p>If you want to have an <em>overview</em> of how Presto work under the hood, you will like this chapter. The word <em>overview</em> is a good word here because George only focus on multithreading (it's what this book is supposed to do so...) but he often talk about things implicitly that (I guess) you could understand if you were familiar with Presto (what a rig look like in Presto?!). This "abstraction" of some technical details can be frustrating. <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /></p>


<p>I also felt a "everything were fine and rosy" like if there was no complications, no multithreading specific "problems", no "what a silly idea we had there". I mean, in development, there is always moments where the vision and abstracted concepts face reality and involve serious trade of, moments where the academic approach can't be applied <em>as it</em>. This is even more glaring when you compare to the following chapter.</p>


<h3>Chapter 4: LibEE: Parallel Evaluation of Character Rigs (by Martin Watt)</h3>


<p>This one surprise me a lot! It shine in many places!</p>


<p>From the first pages of the chapter I was not very excited. LibEE is presented as a multithreaded Dependency Graph... You could almost read "Maya DG is not relevant anymore so there was no alternative: We have to write our own". I'm not a big fan of the classic "Dependency" Graph pattern. I'm not sure it's a good approach for multithreading and more I was reading the chapter more it confirm my humble opinion (but you know, I'm not working at Dreamwork so there is maybe a lot of valid reasons...). While the Dreamwork team seems to have done a big job to bypass some of the limitations a Dependency Graph could have, many sections make me realize "why" DG is not straightforward for massive multithreading. I tend to prefer a compiled approach like <a href="http://www.sidefx.com/docs/houdini13.0/vex/" hreflang="en">VEX</a> or what Presto team choosed but reading the rest of the chapter, I'm not sure the Dreamwork RnD team has all the needed discretion (and resources?) to choose a such approach.</p>


<p>And this is one point where this chapter is amazing: You "feel" the production. I mean, the deadlines, riggers ranting over the new tools <em>because-it-was-better-to-use-the-old-shitty-Maya-DG-before</em>. I'm a big fan of various few line examples of discussions betweens various peoples involved (copy of rigger mails make me ROFL). It also explained how they have to <em>train</em> riggers to <em>think</em> multithreaded. The various bench tools they provided to riggers to find where the <em>critical paths</em> were and when "cut" them (yet another point to stay away from DG IMHO). LibEE follow the typical VFX situation where tools are  developed and used at the same time (unlike Presto team that seems to have worked far away the production before release even if this is not clearly stated). Handle such situation is an art from a development perspective as goals often change and this chapter explain (a little) how handle this.</p>


<p>The second impressive point is the experience they share with the tests they did in production. I was sad the Presto chapter where only mentioning few technical points to be aware of in general (NUMA, bandwith, Hyperthreading, etc...) without provide any graph or so, while the Dreamworks team not only explain, but show <em>where</em> this points are problematics, how they bench them and what they observed. And they became very far at this point. Once again, this is not academic, this is true use cases decorticates.</p>


<p>So a very cool and clear chapter! One of the most valuable of this book. I would have love the same level of in depth discussion with Presto.</p>


<h3>Chapter 5: Fluids: Simulation on the CPU (by Ronald D. Henderson)</h3>

<p>lol this one is massive. If you love code, maths and computer science, you would love 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>There is some interesting OpenMP/TBB comparison codes (with TBB C++11 lambdas, first time I read such! <img src="media/9346b45f.confused0028.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/confused0028.gif" alt=":gne2:" class="smiley" /> ). If you are not comfortable with C++, that's gonna be hard (and kind of disrupting).</p>


<p>About maths, I must admit I've smiled a lot each time I realize "I don't get anything! <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> " after read some lines.</p>


<p>In others chapters of the book, a lot of explanation is often presented with sentences like: "We measure the core efficiency by dividing the bench time by the number of core" (you know, something humanly readable). In this chapter, such sentence are actually presented by a tiny mathematical formulation following by: "Where <em>p</em> is the relational infrastructured derived of the inversed logarithm's result of the number of core and <em>n</em> is the time of the benchmark expressed in second (ISU-CIPM 1967)". Yeah, I exaggerate of course but as I'm not used to mathematical formulations this is exactly the feel I had reading this kind of sentences for the first time. And I laugh even more when, after some digging minutes, I realize all of this could be said with a simple sentence. Haha! <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>But I had the opportunity to work with mathematicians (or peoples loving maths in general) and they tend to use math equations to model anything (even such trivial things than the average time peoples spend at lunch or to be late at a meeting) so it reminded me all this funny moments. <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>I'd also really loved the quick <a href="http://www.openvdb.org/" hreflang="en">OpenVDB</a> presentation. I had often heard about OpenVDB and never know how it was working under the hood. This tiny presentation was perfect. There is a lot of widely open source libraries used in the CGI but they lack of easy-to-get presentations and there is a lot of CG artists, while not true developers, are very technical and would benefit of advanced presentations of such libraries in their day to day work. So VFX artists, this presentation is for you!</p>


<p>For the rest, it was too <em>mathematics</em> for me. If you find it hard to read mathematics equation you would be lost in this chapter. I did so I can't really comment how valuable it is. Actually, I think you could be right with it if you are familiar with all "fluid/liquid" simulation maths.</p>


<h3>Chapter 6: Bullet Physics: Simulation with OpenCL (by Erwin Coumans).</h3>


<p><img src="media/727fb2f5..Bullet_Physics_Logo.svg_s.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/.Bullet_Physics_Logo.svg_s.png" alt="Bullet_Physics_Logo.svg.png" style="display:block; margin:0 auto;" title="Bullet_Physics_Logo.svg.png, sept. 2014"  height="90" width="240" /></p>


<p>What a cool chapter I was not expecting. <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'm not so much interested by physics in general but I must admit Erwin did a great work to decorticate his nice library. It's also the only chapter talking about <a href="http://en.wikipedia.org/wiki/OpenCL" hreflang="en">OpenCL</a> and GPU low level computation. While it's a very fast overview, it's well described and every steps of the various collision detection/repulsion computation of the Bullet libs that have been parallelized are well highlighted. This give a very interesting overview of how a physic engine can work which is something pleasant to know in VFX.</p>


<p>There is also a lot of tiny and very clear schema. I tend to prefer a lot of tiny, one problem focused, schema than bigger ones, you can see in the Presto eating places where some other schemas could have been interesting.</p>


<p>It finished on more advanced principles.</p>


<p>One of the clearest and pleasant chapter to read. <img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


<h3>Chapter 7: OpenSubdiv: Interoperating GPU Compute and Drawing (by Manuel Kraemer)</h3>


<p>I was waiting for this one impatiently and I've not been disappointed, very cool chapter. It's composed of two parts.</p>


<p>The first part talk about the iterative Catmull Clark subdivision, its history, why a "universal-matching" subdivision is needed, how it was working and how they multithread it. If you are not familiar with geometry <a href="http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml" hreflang="en">hard edge data structure</a> you will certainly be lost. They also give some shy benchmarks and conclude iterative subdivision design, while a need for off-line rendering, does not fit well to realtime constraints. I've been surprised they didn't talk about how they organize the memory to improve cache and benefit vectorization. I'm not an expert but after have read the previous chapters, I wonder if there was not other things to do to improve performances. I guess they are just not presented because the benefit where not such interesting who know... But to have distantly followed OpenSubdiv development I have the impression they quickly jump to the GPU side as it was maybe a more important step for the studio (Presto seems to rely on it), leaving the CPU code as "good enough".</p>


<p>The second part talk about how OpenSubdiv use GPU (and OpenGL) to offer realtime subdivision using realtime tessellation shaders available with OpenGL. Once again, I enjoyed the GPU presentation and how you are supposed to organize your batchs to benefit from it (and deal with strong GPU limitation). Edge Crease (a pivotal point of OpenSubdiv) seems to have been a problem (so does the triangle/quad/polygon) but I really like how they handle it: They separate each set of the geometry to apply different algorithms. The separation process is done once as the topology doesn't change, and the GPU simply recompute the tessellation shader according to the face set. Interesting and pragmatic approach to apply the most efficient algorithm to various part of a single geometry (while I guess it should complicate the code).</p>


<p>Off topic, I wonder if creases were a good idea for an open subdiv library. It fit very well with the <em>surface limit</em> concept dear to Renderman but:</p>
<ul>
<li>This concept doesn't seems to fit well with raytracers that need true geometry to raycast.</li>
<li>It seems that you need high subdivision levels to benefits of strong (but still smooth) crease edges were a simple bevel or double edge could do the job (it certainly make the geometry more complex indeed).</li>
<li>It seems to complicate and fragment the subdivision code.</li>
<li>Fragmented code? Fragmented data structure? What impact it could have on memory (efficient access and size)?</li>
</ul>


<p>If you can't subdivide for hell, a last option could be to represent creases modifying the normal but you would have to deal with shading stuff and this is not what OpenSubdiv is supposed to do (beside all the troubles you could have to "merge" the other shading normals).</p>


<p>So I wonder if creases where not something Pixar (and mainly Pixar) absolutely needs and this would explain while a such "exotic" concept fall in OpenSubdiv.</p>


<p>Notice the <a href="http://www.fxguide.com/quicktakes/opensubdiv-3-0-coming/" hreflang="en">next OpenSubdiv is coming</a> and seems to have some other studios contributions. It's a good thing as it seems to became a strong part of Maya. :)</p>


<h3>Conclusion</h3>


<p>Well... Good book! :D</p>


<p>There is inconsistencies between chapters. Some are very deep (LibEE, Fluids, Bullets), and others just touch the surface and finish too soon (Houdini, Presto).</p>


<p>So this book is exactly what it states: Multithreading for Visual Effects. And it focus on how multithreading can be/is used in VFX. But as the chosen softwares are very interesting (Seriously, Side Effect, Pixar, Dreamworks!) it can be sometime frustrating!</p>


<p>The book is very nice (hard cover!) while a bit pricey (hard cover?). But it's about a specific domain so it's ok (is there any book that talk about such softwares?). Most of the time it will be your studio that will buy it so... :P</p>


<p>Does it worth it? If you have to code on VFX softwares, don't hesitate. You will not find massive "ready to use" resources but it's like if you had talks with this guys sharing their experience, they explain how their babies works, what is important and what is a mess. Not sure you can find such infos everywhere.</p>


<p>If you are an artists enjoying technical stuff, I wouldn't recommend this book. It's very focus on development, you will not find multithreading tricks that will enhance your work. Anyway, I encourage to prick it to your RnD and see by yourself! :P</p>


<p>After reading this book, I'm sure I could pay for books (even with soft cover!) that focus on in depth architecture of a specific VFX software from a dev point of view (Houdini, Presto, Maya, Nuke). How datas are managed, what data structures look like, how a specific kind of operations are done etc... And not just an overview!</p>


<p>From the time I've been on the artistic side, I've tried to understood how softwares where technically working (because most of the time they were working bad/not as expected/I DIDN'T SAVE MY WORK!!!! etc...). I'm now able to understand the "logic" part of them so I want to read such high end code more!</p>


<p>Unfortunately, I missed a lot of valuable informations because of my lack of mathematic skills. I'm more familliar with computer science in general. I mean, I know what 4x4 matrices are, what they are used to, I know what a dot/cross product is and how it can be used to achieve various stuff but thats pretty much all. I was angry against myself to not be able to read and understand some advanced part of the code (I skip a lot of the Fluids chapter. :( ).</p>


<p>What is also interesting is to gather interesting Siggraph courses to make a book. I really like the idea while I would suggest to favor courses that go more in depth or with a lot of implementation studies (Once again, Presto is very frustrating). I also tend to prefer books than pdf.</p>


<p>I don't know about the success of this book but I've heard many peoples interested in it so we could hope for... Let say... "Alembic/OpenVDB/OpenEXR code review and use cases" with a lot of in depth explanation of the foundation and infrastructure of each of this libs. :D</p>


<p>Hope you enjoyed this humble review! I would be very interesting to ear your opinion if you also read this book so feel free to comment. :)</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:2f9c1853ac39265f4efdfd1782d0fbd0
title: Le livre Multithreading for Visual Effects
uri: Le-livre-Multithreading-for-Visual-Effects
url: http://www.fevrierdorian.com/blog/post/2014/08/24/Le-livre-Multithreading-for-Visual-Effects
content:
<p><img src="media/bea5c843.multithreading_for_vfx_review_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/multithreading_for_vfx_review_tn.png" alt="multithreading_for_vfx_review_tn.png" style="float:left; margin: 0 1em 1em 0;" title="multithreading_for_vfx_review_tn.png, août 2014"  height="150" width="150" />En code, rien ne vaut un bon bouquin. Vous entendrez souvent ce conseil de la part de développeurs expérimentés.</p>


<p>Aujourd'hui je vous propose un billet sur le livre <a href="http://www.crcpress.com/product/isbn/9781482243567" hreflang="en">Multithreading for Visual Effects</a>.</p>


<p>Ce livre a été publié après <a href="http://s2013.siggraph.org/attendees/courses/events/multithreading-and-vfx" hreflang="en">la session de cours Multithreading and VFX</a> au Siggraph 2013 où un certain nombre de studios présentaient comment ils avaient utilisés le multithreading dans leur outils. Les papers étaient suffisamment intéressant pour qu'ils décident de les rassembler en un livre.</p>


<p>Dans la mesure ou ce type de livre fait parti du marche de <em>niche</em> que sont les VFX, parlons en! <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><a href="media/0c005d30.multithreading_for_vfx_review_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/multithreading_for_vfx_review_001.jpg" title="multithreading_for_vfx_review_001.jpg"><img src="media/d416ba65..multithreading_for_vfx_review_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_04_24_multithreading_for_vfx_review/.multithreading_for_vfx_review_001_m.jpg" alt="multithreading_for_vfx_review_001.jpg" style="display:block; margin:0 auto;" title="multithreading_for_vfx_review_001.jpg, août 2014"  height="560" width="420" /></a></p>

<h3>Chapitre 1: Introduction et vue d'ensemble (par James Reinders)</h3>


<p>Le prologue est une ode au multithreading (Sans blagues <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> ). James Reinders est ingénieur pour Intel et on peut dire qu'il connait son boulot!</p>


<p>J'ai pas mal apprécié comment les multiples facettes du multithreading sont présentées (multi tache vs multi thread, vectorisation, etc...) ainsi que les explications techniques sur comment chacune d'elle fonctionne, avec leurs avantages et inconvénients.</p>


<p>Je me dois de parler de la manière dont <a href="https://en.wikipedia.org/wiki/Threading_Building_Blocks" hreflang="en">TBB</a> est présenté. TBB est généralement considéré comme une (la?) librairie de choix pour des logiciels multithreadés (Presque tous les logiciels du livre l'utilisent). Et de ce que j'ai pu lire de la documentation, c'est mérité. Pour être tout à fait honnête, TBB me donne réellement envie de maitriser les templates C++ et je comprends parfaitement qu'on puisse se tourner vers TBB rien que pour ça.</p>


<p>Mais je trouve dommage que James n'ai pas passé autant de temps et d'amour à présenter les alternatives. Je sais bien, c'est un bonhomme d'Intel mais clairement, TBB reçoit tellement d'éloge dans ce chapitre (et tout au long du livre) qu'il en occulte complètement les autres librairies (qui sont "présentées" mais pas de manière aussi clair que TBB).</p>


<p>Bref, vous comprenez assez vite le message: <em>TBB cay bon, mangez-en!</em> <img src="media/48a6a7fc.banane-jaune.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>


<h3>Chapitre 2: Houdini: Multithreader un logiciel existant (par Jeff Lait)</h3>

<p><img src="media/67ce2585..houdini_black_s.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/.houdini_black_s.png" alt="houdini_black.png" style="display:block; margin:0 auto;" title="houdini_black.png, sept. 2014"  height="56" width="240" /></p>


<p>Bon nombre des informations qu'on peut trouver ici et la, y compris dans les livres (celui ci inclus), sont très académiques. Elles expliquent comment vous <em>devriez</em> écrire du code.</p>


<p>Ce chapitre est très intéressant car il prend l'approche inverse: Comment convertir du vieux code en un code <em>scalable</em> (qui se parallélise efficacement). Jeff présente différents problèmes concrets, la ou les les méthodes qu'ils ont choisis pour les résoudre, ce qu'ils ont perdus au passage et ce qu'il ont pu sauver.</p>


<p>Ce que j'adore dans ce chapitre est à quel point il est anti-académique. Certains code d’exemples m'ont vraiment fait réagir: "Je pourrais faire ça... Ça serait bizarre mais ça marcherait plutôt pas mal!". Le meilleur exemple est la façon dont Houdini gère la latence de création des threads (car créer un thread est assez long) quand la quantité de données a calculer ne vaux pas le temps de création des threads. Accrochez vous: If data_count &lt; 5000&nbsp;: compute in the main thread! <img src="media/6bf85d36.IFuckTheWorld.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/IFuckTheWorld.gif" alt=":IFuckTheWorld:" class="smiley" /></p>


<p>Vous ne trouverez jamais ce genre de "solutions" dans un livre académique mais vous ne trouverez jamais plus efficace que ça sans avoir à modifier le code à milles endroits! :D</p>


<p>Chaque exemple est intéressant (bien que souvent très spécifique). Les lires entraine votre cerveaux sur <em>pourquoi</em> vous devriez faire les choses de tel ou tel façon et comment réagir quand vous voyez un truc qui semble louche.</p>


<p>Je dois avouer que j'avais lu <a href="media/7b30663d.MultithreadingHoudini.pdf" data-original-source="http://www.multithreadingandvfx.org/course_notes/MultithreadingHoudini.pdf" hreflang="en">le paper original de Side Effect</a> après le Siggraph 2013. J'ai d'ailleurs remarqué qu'un petit travail de réorganisation a été fait et certains exemples m'ont paru mieux expliqué. Je me rappel avoir été un peu perdu avec certains des exemples du paper original mais je n'ai eu aucun soucis à comprendre ceux du livre. J'en conclu donc qu'une bonne relecture a été faite (ou que je suis plus capable de lire du code qu'avant ce qui est fort probable).</p>


<p>J'ai été super frustré par la fin du chapitre qui arrive trop vite... On en veut encore! <img src="media/00461682.1420.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /> Plus d'exemples, plus de problèmes tordu (mais concrets) à résoudre!</p>


<p>Si vous souhaitez en savoir plus sur comment Houdini fonctionne sous le capot, <a href="http://www.fevrierdorian.com/blog/post/2013/04/24/Houdini-sous-le-capot">j'avais traduis</a> <a href="http://forums.odforce.net/topic/17105-short-and-sweet-op-centric-lessons/#entry104263" hreflang="en">un post très intéressant</a> que je vous invite à lire.</p>


<h3>Chapitre 3: Le système d’exécution de Presto: Architecturer pour le Multithreading (par George ElKoura)</h3>


<p>L'interactivité est le mot clef de ce chapitre.</p>


<p>La première partie n'est pas particulièrement intéressante. George explique les ambitions et les contraintes techniques. C'est chouette pour la partie animation (temps de latence, interactivité, etc...), mais il passe définitivement trop de temps sur des choses que tu connais souvent déjà sans vraiment expliquer les implications spécifiques à Presto ("La vectorisation du code est importante car blabla", "Il faut organiser ces données comme ça sinon blabla"). Le coté très général des conseils fait presque redondance avec le premier chapitre. Il aurait peut être été préférable de développer tout ces points dans le premier chapitre (plutôt que de brosser TBB dans tous les sens <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" /> ) et laisser chacun des autres chapitre se focaliser sur l’implémentation.</p>


<p>Cela dit, la second partie est vraiment superbe! Vous y trouverez pleins de petites choses qu'il faut avoir en tête si vous souhaitez développer pour des logiciel d'animation. La gestion des threads dans Presto (tout particulièrement la manière dont le graph d'evaluation est compilé puis exécuté) m'a semblé vraiment moderne, bien pensé et concret. Par concret j'entends qu'on est pas dans des choses génériques mais vraiment spécifiques. La gestion du temps (cache des géométries), la gestion de l'interface utilisateur avec une anticipation des valeurs modifié pour mieux préparer les "batchs" de thread (si un utilisateur modifie les contrôleurs d'un personnage, on peut vraisemblablement penser qu'il ne modifiera pas le cache des autres, inutile d’arrêter leurs threads car un thread coute cher à lancer rappelez vous). Chaque détail permettant d'éviter des ralentissements et d'augmenter le "rendement" des graphs est présenté.</p>


<p>Tout ceci est très clairement expliqué même si ça manque un peu de détails à mon gout (j'aime bien avoir des explications de cas un peu tordu).</p>


<p>Ils finissent avec un petit exemple de code (2 pages) sur comment multithreader un déformer géométrique simple. C'est un exemple intéressant car il présente un cas assez général mais qu'on peu rencontrer souvent en prod quand on est rigger. Vous vous en doutez, la solution est tout aussi "général".</p>


<p>Si vous souhaitez avoir un survole de comment Presto fonctionne sous le capot il y a de fortes chances que vous appreciez ce chapitre. Le mot "survol" est le bon terme car George ne se focalise que sur l'aspect multithreading (c'est le titre du livre donc difficile de le lui reprocher...) mais il parle souvent de choses implicites qu'il est difficile de cerner si on n'est pas habitué a Presto (j'imagine). A la fin du chapitre, on ne sais pas vraiment a quoi ressemble un rig dans Presto (relation entre les nodes et la UI, les nodes les plus bizarres/spéciaux/gros, etc...). Cette "abstraction" de certains détails techniques est souvent frustrante. <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /></p>


<p>J'ai également ressenti une sorte de "tout va pour le mieux dans le meilleur des mondes". Comme si il n'y avait jamais eu de complication, aucun souci spécifique au multithreading (qui est pourtant un techno assez jeune en terme de paradigme), aucun "on a pensé faire ça car blabla mais on c'est rabattu sur ça car blabla". Sincèrement, en développement il y a toujours des moments ou la vision "abstraite" des concepts (vision nécessaire à l’architecture général d'un logiciel, surtout dans les premières années) se mange les cas non prévus de la réalité dans les dents. Des moments ou un juste milieu, un moindre mal est nécessaire. C'est d'autant plus flagrant quand on compare avec le chapitre suivant.</p>


<h3>Chapitre 4: LibEE: Évaluation en Parallèle des Rigs des Personnages (par Martin Watt)</h3>


<p>Celui là m'a littéralement surpris! Il se lit comme une histoire!</p>


<p>J’avoue que les premières page ne m'ont pas particulièrement fait sauté au plafond . LibEE est présenté comme un graph de dépendance (Dependency Graph ou DG) multithreadé... On pourrais presque lire entre les lignes "Le DG de Maya est totalement à l'Ouest alors on l'a réécrit". Le problème c'est qu'un graph de dépendance "a la Maya" ne rime pas forcément avec performance, surtout dans le cas d'un rig. Le fait que chaque node soit exécuté indépendamment puis passe son résultat au node suivant via des attributs, le tout badigeonné d'une dépendance inter-attributs (ou certains attributs d'entrés peuvent modifier certains des attributs de sortie mais pas tous) et vous obtenez un graph qui passe plus de temps a évaluer les dépendances pour savoir quel node exécuter qu’exécuter réellement les calculs des nodes (avouez que c'est con quand le node ne fait au final qu'une simple addition <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> ).  Et c'est vrai pour Maya comme pour n'importe quel autre implémentation qui suit cette approche. La vitesse d’exécution d'un graph dépend souvent énormément de son "allure" et il n'est pas rare qu'un graph un peu tordu plombe drastiquement les performances. J'ai tendance à préférer l'approche compilé d'un <a href="http://www.sidefx.com/docs/houdini13.0/vex/" hreflang="en">VEX</a> ou d'un Presto mais en lisant le reste du chapitre, je ne suis pas sur que la RnD de Dreamworks ait pu disposer de toute la latitude (et des ressources?) nécessaires.</p>


<p>Après, je ne suis pas dev a Dreamworks et il y a peut être un autre paquet de bonnes raisons... <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>Mais bien que l'équipe de Dreamworks semble avoir fait un travail colossale pour contourner les limitations qu'implique ce type de DG, plusieurs sections tendrons a confirmer mes (humbles) hypothèses.</p>


<p>Et quand je parle de travail colossale je ne suis pas en dessous de la vérité. C'est la raison principal pour laquelle ce chapitre est exceptionnel: Vous "sentez" la production. Vous savez, les deadlines, les riggers qui râle sur les nouveaux outils "car-le-vieu-DG-de-Maya-il-aytay-mieu". Je suis un gros fan des quelques exemples de discussions entre les différentes personnes impliquées dans le projet (avec une petite copie d'un mail bien senti lol). Il explique aussi comment ils on eu à <em>apprendre</em> à leurs riggers à <em>penser</em> multithreadé (chose qui n'était pas prévu au départ). La présentation des différents outils de bench fourni au riggers pour qu'ils puissent trouver eu même les <em>critical paths</em> de leur code et qu'ils les "coupe" ou "blend" la logique en un seul node (un autre argument pour se tenir loin d'un DG IMHO). LibEE semble avoir suivi la situation typique d'une prod de VFX/anim ou les outils sont développé et utilisé en même temps (à l'inverse de Presto ou l'équipe semble avoir travaillé loin de la production, même si ce n'est pas clairement dit, avant de relâcher leurs outils). D'un point de vu développement, gérer une tel situation est un art en soit dans la mesure ou les objectifs/contraintes changent au fil du temps et ce chapitre explique (un petit peu) comment gérer ça.</p>


<p>Si vous êtes développeur et que vous pensez que les studios de VFX échouent car ils ne sont pas assez carré, passez ce chapitre, vous allez détester car c'est vraiment des situations de terrain, du vécu. Les autres, si vous voulez bosser en VFX il y a vraiment de quoi vous inspirer (ou vous faire fuir, au choix!). Et les derniers, ceux qui bossent déjà en VFX habitué des <em>patchs-en-prod-parce-que-cay-super-plus-urgent-que-les-autres-urgences</em>, vous allez vous sentir moins seul! <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 second point concerne les expériences et tests qu'ils ont effectués en prod ou de manière plus formel. J’étais déçu que le chapitre Presto ne mentionne que quelques points techniques souvent assez connus (effet <a href="https://fr.wikipedia.org/wiki/Non_Uniform_Memory_Access" hreflang="fr">NUMA</a>, bande passante de la RAM, Hyperthreading, etc...) sans fournir aucun graph ou expliquer en quoi ces problèmes impactaient directement Presto. Ici, non seulement les gars de Dreamworks expliquent ce qui les amènes à faire tel ou tel test mais ils fournissent une quantité de détails impressionnant qui explique, de manière très clair, <em>comment</em> et <em>pourquoi</em> tel ou tel effet apparait. Et on peut dire qu'ils ont poussé le bouchon très loin. Une fois encore, tout ces exemples ne sont pas académiques, ce sont de vrais <em>use cases</em> décortiqués et analysés très clairement. Certains tests expliquent même pourquoi un effet attendu n'est, en pratique, pas un problème.</p>


<p>C'est donc un chapitre super chouette! Un des plus intéressant du livre. J'aurais aimé que le chapitre de Presto sois aussi poussé.</p>


<h3>Chapitre 5: Fluides: Simulation sur le CPU (par Ronald D. Henderson)</h3>

<p>lol celui la est massif. Si vous aimez le code et les maths vous allez être servi! <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>Il y a quelques codes de comparaison entre OpenMP et TBB (avec du lamdbas C++11, première fois que j'en vois! <img src="media/9346b45f.confused0028.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/confused0028.gif" alt=":gne2:" class="smiley" /> ). Si vous n'êtes pas à l'aise avec le C++, ça risque d'être assez dure (et un peu déroutant).</p>


<p>Pour ce qui est des maths, je dois admettre que j'ai pas mal rigolé chaque fois que je me disais "tin mais je capte rien! <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /> " après quelques équations (et leur magistrales explications).</p>


<p>Dans les autres chapitres du livre, beaucoup d'explications se font sous la forme de phrases assez basiques tel que: "Nous mesurons l’efficacité des cores en divisant le temps de calcul par le nombre de core" (enfin un truc compréhensible quoi...). Dans ce chapitre, de tel phrases serait plutôt présenté sous la forme d'une petite équation de math bien senti suivi d'un: "Ou <em>p</em> est la dérivé relationnel d'infrastructure de la logarithme du nombre de core et <em>n</em> est le temps de calcul exprimé en second (ISU-CIPM 1967)". Bien sûr j'exagère mais dans la mesure ou je ne suis pas habitué aux équations mathématiques c'est exactement l'effet que ça m'a fait à la première équation. Et j'ai d'autant plus rie quand, après m’être bien trituré pour déchiffrer et comprendre tout ça j'ai réalisé qu'on pouvait résumer ça en une phrase... Haha! <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>Mais j'ai eu l’opportunité de travailler avec des matheux (ou des gens qui apprécient les maths d'une manière général) et ils ont cette tendance à jouer avec les équations mathématiques partout, y compris pour des trucs anodins (comme le temps moyen que passe les gens à la cantines en fonction des menus proposé, ou bien le temps de retards moyen des réunions suivant les dates de livraison) et ça m'a rappelé tout ces moments assez drôles. <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>J'ai également apprécié la petite présentation de <a href="http://www.openvdb.org/" hreflang="en">OpenVDB</a>. J'ai souvent entendu parlé de OpenVDB mais je n'ai jamais compris comment il marchait sous le capot. Cette petite présentation est parfaite! Il y a un bon nombre de librairies open source utilisé dans en CGI mais elles manques souvent de présentations faciles à comprendre alors qu'il y a beaucoup de graphistes qui, bien qu'il ne soit pas développeurs, sont assez techniques et pourrais bénéficier d'une meilleur compréhension de ces librairies dans leur travail au quotidien. Donc les VFX boys, cette présentation est pour vous!</p>


<p>Pour le reste, c'était malheureusement trop <em>mathématiques</em> pour moi. Si vous trouvez difficile de lire des équations mathématiques, vous serez perdu dans ce chapitre. Ça été le cas en ce qui me concerne et je ne peut pas vraiment dire si ce qui est présenté dans le reste du chapitre est intéressant ou classique. En fait, je pense que vous pourriez vous en tirer si vous êtes un temps soit peu habitué au solver de fluides/liquides.</p>


<h3>Chapitre 6: Bullet Physics: Simulation avec OpenCL (par Erwin Coumans).</h3>


<p><img src="media/727fb2f5..Bullet_Physics_Logo.svg_s.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/.Bullet_Physics_Logo.svg_s.png" alt="Bullet_Physics_Logo.svg.png" style="display:block; margin:0 auto;" title="Bullet_Physics_Logo.svg.png, sept. 2014"  height="90" width="240" /></p>


<p>Un chapitre bien sympa auquel je ne m'attendais pas vraiment. <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>Je ne suis pas spécialement intéressé par la physique (au sens mécanique) mais je dois admettre qu'Erwin a fait un gros travail pour décortiquer et présenter sa librairie. C'est un des deux chapitre à aborder <a href="http://en.wikipedia.org/wiki/OpenCL" hreflang="en">OpenCL</a> et le calcul GPU (le second étant le chapitre sur OpenSubdiv) mais c'est surement celui qui le fait le mieux. Bien que l'aperçu soit assez rapide, il décrit très bien les différentes étapes de créations des batchs de calcul pour le GPU et revient dessus à chacune des (très) nombreuses étape de détection de collision/calcul de répulsion. C'est d’ailleurs un très bon aperçu de comment fonctionne un moteur physique ce qui est quelque chose de très intéressant à savoir quand bon bosse en VFX.</p>


<p>Il y a aussi beaucoup de petits schémas qui sont tous très clair, chacun ne se focalisant que sur un seul problème. J'ai tendance à préférer cette approche plutôt que peu de gros schémas qui essaient d’expliquer milles choses.</p>


<p>Il fini sur des choses plus avancés.</p>


<p>Surement le chapitre le plus clair et plaisant à lire. <img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


<h3>Chapitre 7: OpenSubdiv: Interoperating GPU Compute and Drawing (par Manuel Kraemer)</h3>


<p>J'attendais ce chapitre avec impatience et je n'ai pas été décu. Très chouette, il est composé de deux parties.</p>


<p>La première partie explique succinctement comment la subdivision itérative Catmull Clark fonctionne, sont histoire, pourquoi une "subdivision universelle" était nécessaire, et comment ils ont choisi de la multithreader. Si vous n'êtes pas familier avec la structure de donnée géométrique en arc dur (dite <a href="http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml" hreflang="en">hard edge data structure</a>) vous allez surement être un peu paumé. Manuel donne quelques benchs timides et conclu que le design itératif de la subdivision Catmull Clark, bien que nécessaire pour le rendu non temps réelle (<em>off-line rendering</em>), ne s'adapte pas très bien au contraintes du temps réel. J'ai été assez surpris qu'il n'aborde pas du tout comment ils organisent leur données dans la mémoire pour améliorer le cache et bénéficier d'une meilleur vectorisation. Je ne suis pas un expert, mais après avoir lu les chapitres précédents, je me demande sérieusement si il n'y avait pas d'autres axes de recherche pour améliorer les performances. Je suppose que Manuel n'en parle pas car les gains n'était pas substantiels. Qui sait... Mais pour avoir suivi le développement d'OpenSubdiv de loin, j'ai l'impression qu'ils ont rapidement sauté sur le GPU. Comme si c'était quelque chose de plus important pour le studio (Presto semble s'appuyer dessus) et que le code CPU serait "suffisant". Les nouvelles versions de Renderman s'appuyant massivement sur du raytracing (et donc, une subdivision CPU), j'en viens à me demander si Renderman s'appuie réellement sur OpenSubdiv.</p>


<p>La seconde partie présente comment OpenSubdiv utilise le GPU (et OpenGL) pour permettre un rendu d'une subdivision temps réelle en utilisant les shaders de tesselation. Une fois encore, j'ai bien apprécié la présentation du fonctionnement d'un GPU, leurs différences (contraintes surtout) par rapport à un CPU et comment organiser et préparer ces batchs pour en bénéficier. Les Edges Creases (un "truc" très présent dans OpenSubdiv) semble avoir été un problème (tous comme la gestion des triangles/quads/polys le sont dans une algo de subdivision) mais je trouve qu'ils ont été assez ingénieux dans la façon de le gérer: Ils ont séparé chaque set de géométrie pour lui appliquer différents algorithmes. Dans la mesure ou la topologie ne change pas, le processus de séparation est fait une seul fois et le GPU ne fait que recalculer les position des points avec le shader de tesselation associé à son "set de topologie". Une approche intéressante et pragmatique pour appliquer différents algorithmes de subdivision à une seule géométrie (bien que ça semble pas mal compliquer le code).</p>


<p>Je dérive un peu pour étaler mon point de vu: Je me demande vraiment si il était pertinent de garder les Creases dans OpenSubdiv. Le concept s’accommode parfaitement avec le principe de <em>surface limite</em> cher aux rendu REYES. Mais:</p>
<ul>
<li>Cette approche ne semble pas particulièrement adapté au ray tracer qui nécessite une vrai géométrie à raycaster.</li>
<li>Des Creases un peu fort nécessite d'augmenter pas mal le niveau de subdivision pour avoir un rendu correct là où un simple bevel ou une double edge aurait fait la blague (mais complexifié la géométrie c'est vrai). Encore une fois, quand on cherche à diminuer la taille des géométrie pour les faire rentrer dans la mémoire, augmenter drastiquement la subdivision pour récupérer l'équivalent d'un bevel me semble un peu dommage.</li>
<li>Il semble complexifier et fragmenter pas mal de partie du code.</li>
<li>Code fragmenté? Structure de donnée fragmenté? Quel impact sur la mémoire (accès et taille)?</li>
</ul>


<p>Une des dernière alternative que je vois au coté gourmand (en géométrie) du Creases si on ne peut pas subdiviser à tout va c'est de modifier la normale au niveau de l'edge (pouah! Le temps de calcul du truc). Mais cela faisant, vous devez prendre l'information en compte au niveau du shading et ce n'est pas ce que OpenSubdiv est supposé faire (sans compter les petits soucis qu'on pourrait avoir pour "blender" les normales). Mais il faut avouer que ça marcherait pas mal!</p>


<p>Bref, je me demande si les Creases n'était pas un truc dont Pixar (et seulement Pixar) a besoin. Ça pourrait expliquer pourquoi un concept aussi "exotique" se retrouve dans OpenSubdiv.</p>


<p>Notez que <a href="http://www.fxguide.com/quicktakes/opensubdiv-3-0-coming/" hreflang="en">la prochaine version de OpenSubdiv arrive</a> et semble avoir bénéficier des contributions et feedbacks d'autres studios (Dreamworks?). On dirait qu'ils ont isolés la partie algorithme de la partie structure de donnée ce qui est clairement une bonne chose car devoir passer sa géométrie dans une structure de donnée externe pour la récupérer ensuite est vraiment contre productif. Je suis content de voir qu'OpenSubdiv semble aller dans la bonne direction. C'est d'autant plus important qu'il devient une partie intégrante de Maya. :)</p>


<h3>Conclusion</h3>


<p>Et bien... Un très bon livre! :D</p>


<p>Il y a une inconsistance entre les chapitres. Certains vont vraiment au bout des choses (LibEE, Fluids, Bullets), et d'autres ne font qu'effleurer la surface (Houdini, mais surtout Presto).</p>


<p>Donc ce livre est exactement ce qu'il prétend être: Multithreading for Visual Effects. Et il ne se focalise que là dessus, laissant certains points, qui mériteraient aussi d’être abordé, de coté. Mais les logiciels choisis son tellement intéressants (Sérieusement: Side Effect, Pixar, Dreamworks!) que ça en est frustrant!</p>


<p>Le livre est super classe (hard cover! <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /> ) bien que le prix me semble un chouilla élevé (hard cover? <img src="media/ef3897e4.ideenoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/ideenoire.gif" alt=":ideenoire:" class="smiley" /> ). Mais il s'agit d'un domaine de niche donc on va pas cracher dans la soupe (vous en connaissez vous des livres à lire dans votre canap' qui parle des logiciels les plus cools du monde? <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /> ). Et puis faut bien l'avouer, la plupart du temps c'est votre studio qui va l'acheter... :P</p>


<p>Est ce qu'il vaut le coup? Si vous avez à coder des softwares lié au VFX, n'hésitez pas une seconde! Vous n'y trouverez pas de ressources "clef en main" mais c'est un peu comme si vous aviez une discussion avec des gars brillants qui partage leur expériences autour de leur logiciel. Pas sur que vous puissiez trouver de tels infos ailleurs.</p>


<p>Si vous êtes un graphiste un peu technique, je ne vous recommanderais pas forcément de le prendre. Il est vraiment tourné autour du développement, vous n'y trouverez pas de trucs et astuces en multithreading pour améliorer votre travail. Cela dit, je vous encourage à le piquer à votre RnD ( <img src="media/6bf85d36.IFuckTheWorld.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/IFuckTheWorld.gif" alt=":IFuckTheWorld:" class="smiley" /> ) et à le feuilleter. Le début de chacun des chapitre est souvent assez clair.</p>


<p>Après avoir lu ce livre, je me dis que je pourrais bien payer pour d'autres du même genre qui passe en revu et en profondeur (un truc advanced j'entends) l'architecture des logiciels de VFX (Houdini, Presto, Maya, Nuke). Comment les données transitent, a quoi ressemble les structures de données utilisées, comment un type spécifique d'opération s’exécute, etc... Et pas juste un aperçu. Les docs des logiciels sont souvent trop timide sur le sujet.</p>


<p>Avant, j'étais incapable de lire et comprendre de tels codes. Je tentais de déduire le fonctionnement et la logique sous-jacente des logiciels que j'utilisais par dichotomie. Maintenant que je sais lire du code, autant y aller et voir directement le code des dis logiciels! :D</p>


<p>Malheureusement, je suis passé à coté de pas mal d'informations intéressantes à cause de mon incapacité à lire des équations de mathématiques. Je veux dire, je sais ce qu'est une matrice 4x4, les raisons pour lesquelles ont pourrait les utiliser, je sais ce qu'est un dot product, un produit en croix et comment je peut les utiliser pour obtenir un effet souhaité mais c'est à peut près tout... Je m’énervais contre moi même de n'être pas capable de déchiffrer les équations (qui au final ne semblaient pas super compliqué <img src="media/53728ad7.nervous.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nervous.gif" alt=":nervous:" class="smiley" /> ). Idem pour certains morceaux de code que j'ai eu du mal a comprendre <img src="media/edc4ddb7.gne.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/gne.gif" alt=":gne:" class="smiley" /> . Je suis passé à coté de pas mal de choses dans le chapitre des Fluids.... <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>Ce qui est très intéressant c'est d'avoir rassemblé des cours d'une session Siggraph sur un sujet donnée et d'en faire un livre. J'adore l'idée car je passe des heures derrière un ordi et j'apprécie de pouvoir lire ce genre de chose sur du papier plutôt que mon écran de PC (lire un PDF me fatigue assez vite).</p>


<p>Je n'ai aucune idée du succès du livre mais j'ai entendu pas mal de gens intéressé donc on pourrait imaginé... Je ne sais pas... "Alembic/OpenVDB/OpenEXR under the hood and use cases" avec un maximum d'explications sur les fondations et l'infrastructure, jusqu'aux points clefs du code. <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>J'espère que vous avez apprécié cette humble review! N'hésitez pas à commentez si vous avez vous aussi lu ce livre. Je serais curieux de savoir ce que vous en pensez. <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>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:3433f9212ad011cdeab73d46fa9aa7a8
title: fxguide and deep data
uri: fxguide-and-deep-data
url: http://www.fevrierdorian.com/blog/post/2014/10/15/fxguide-and-deep-data
content:
<p><img src="media/2583c2ab.fxguide_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/fxguide_tn.png" alt="fxguide_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fxguide_tn.png, oct. 2014"  height="150" width="150" />As you might know, I work mainly on animated features. I am often involved with productions and RnD departments to talk about incoming challenges, in particular on the lighting side.</p>


<p>There are many situations where peoples argue how deep comp is canonical now and how it will change the face of the CGI... I'm often arguing it's not a "tiny" feature and, while it can be useful "sometime", it creates more troubles than it solve in practice, specially if its use is generalized (and on a animated feature you often need to "over-generalize" uses). Doing so, I'm facing to a lot of "What? But fxguide state a lot of animation studios use it! Dreamworks, Disney, etc...". <img src="media/61b0b317.tuComprendRien.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/tuComprendRien.gif" alt=":tuComprendRien:" class="smiley" /></p>


<p>I will not argue on the fact the projects I have to deal with are not running in such studios. I will not even argue about the actual budget compared to big production ones. I will simply quote something fxguide report and pray the various supervisors I have the opportunity to worked with will take this in consideration.</p>    <blockquote><p>This article is not a shout against fxguide (I read it often and enjoy it a lot, their work is massive!) but mainly against peoples taking fxguide's articles as gospel while having no idea of technical implications using such high end techs fxguide talks about in real world production, specially on (sometime "low cost") animated features.</p></blockquote>


<p>fxguide is one of the most popular CGI news website. It's one of the few (the only one?) providing a lot of articles/interviews of well known personality and high end techs used in CG.</p>


<p>Few days ago, I read <a href="http://www.fxguide.com/featured/disneys-new-production-renderer-hyperion-yes-disney/" hreflang="en">this</a>.</p>


<p>I tends to take lightly what fxguide states because it often obfuscate a lot of details which are very important in a productions situations (all the "what if" questions actually). It's the "everything goes smooth and rosy in the best world ever 'cause the flexibility of our internal tools allow us to deliver high end shots in deadlines with lower cost ever" syndrome (not surprising in the CGI) while the reality of the day to day job is more like:</p>


<p><a href="media/ea27ea65.PicassoGuernica_800.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/PicassoGuernica_800.jpg" title="PicassoGuernica_800.jpg"><img src="media/0632ae5a..PicassoGuernica_800_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/.PicassoGuernica_800_m.jpg" alt="PicassoGuernica_800.jpg" style="display:block; margin:0 auto;" title="PicassoGuernica_800.jpg, oct. 2014"  height="250" width="560" /></a></p>
<center><i><a href="https://en.wikipedia.org/wiki/Guernica_%28painting%29" hreflang="en">Guernica</a> from <a href="https://en.wikipedia.org/wiki/Pablo_Picasso" hreflang="en">Pablo Picasso</a></i></center>



<p>(Joke <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>So for the first time fxguide seems to report wise words about deep data in animated feature and it came from Hank Driskill, Technical Supervisor on Big Hero 6 (next Disney animated feature). If you are an animated feature supervisor, please consider this:</p>


<blockquote><p>The renderer and pipeline can render with deep data. It was not used on all shots, however. “We use it sparingly just because of the data management concerns,” says Driskill, referring to the huge data sets complex deep data rendering can produce.</p></blockquote>


<p>No kidding... Only Weta would have created a such heavy, massive and crazy stuff that deep data file format is. But the reality is you are often not at Weta  (are they really rendering beauties with it?) and you are not working with the same budgets.</p>


<p>Notice the fxguide's "It was not used on all shots" following by contrasted Driskill's quote: "We use it sparingly". They both mean the same thing, just taking the problem by two different angle.</p>


<p>There is a huge gap between what fxguide reports and the artists work, RnD/production relation and the hard time you can have to deliver on time. There is a reason behind this: CGI is very shy when time to talk came. You can't blame that, that's the way things work in any big company. But you have to be aware of that when you read such informations: fxguide, and implicitly, you, don't have the whole story.</p>


<p>This brings fxguide to often have a big abstraction of how things actually run in a studio and how nuanced the stated reality can be (but which supervisor would tell: "This was a mess!" and rant over their in house tools?). This have to be kept in mind when you choose a technical solution based on what fxguide states, specially if you have limited experience on animated features that involve a huge data consistency management.</p>


<p>This might be obvious for a lot of peoples but as I've seen many supervisors taking fxguide as a reference to choose a technology based on <em>according to the industry</em>, I'm taking this opportunity to call for vigilance: You are artists, take the tool you known and move on!</p>


<p>For fun:</p>


<p><img src="media/14be1a91.fxguide_batman_robin.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/fxguide_batman_robin.jpg" alt="fxguide_batman_robin.jpg" style="display:block; margin:0 auto;" title="fxguide_batman_robin.jpg, oct. 2014"  height="310" width="320" /></p>


<p>You will get more chances to deliver a show using a shitty tech you known than a high end tech you have no idea how to use and what it would imply. This has to be considered when you work with limited resources. <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>Hope this help. You're welcome to comment, specially if you don't agree with me! :)</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>



<p>If any fxguide staff member read this post: Don't take any offense, I'm just trying to show that some people can be very strongly influenced and make mistakes because your articles won't always covers the downside. :)</p>


feed_id: urn:md5:3b0e4ff66d6eb67a11f88395351cb98d
title: fxguide et le deep compo
uri: fxguide-et-le-deep-compo
url: http://www.fevrierdorian.com/blog/post/2014/10/15/fxguide-et-le-deep-compo
content:
<p><img src="media/2583c2ab.fxguide_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/fxguide_tn.png" alt="fxguide_tn.png" style="float:left; margin: 0 1em 1em 0;" title="fxguide_tn.png, oct. 2014"  height="150" width="150" />Comme vous le savez peut être, je travaille principalement sur des longs métrages d'animation. Il m'arrive de participer à des discussions (formelles ou informelles) entre la RnD et la production concernant les difficultés techniques (principalement coté lighting) des projets en cours et/ou qui pourraient arriver.</p>


<p>Je dois admettre que j'entends souvent que le deep compositing c'est super, utilisé partout etc... J’avoue avoir une vision plus nuancé de la chose que je ne considère pas comme une "petite" feature et que, bien qu'il puisse se révéler utile dans des cas bien particuliers, il entraine plus de complications qu'il ne résout de problèmes, tout particulièrement si son usage est généralisé (et sur un long métrage d'animation il est souvent nécessaire de "sur-généraliser" les usages pour garder une consistance dans les données générées).</p>


<p>Mais cela faisant, je me retrouve face à pas mal de "Hein? Mais fxguide dit que c'est utilisé dans tous les studios d'animation! Dreamworks, Disney, toussa..." <img src="media/61b0b317.tuComprendRien.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/tuComprendRien.gif" alt=":tuComprendRien:" class="smiley" /></p>


<p>Je ne m'étalerais pas sur le fait que les projets sur lesquels je travaille ne sont pas fait dans de tels studios. Je ne parlerais même pas de la différence de budget. Je vais simplement citer un propos rapporté par fxguide et prier pour que tout superviseur, actuel et futur, ait l'occasion de prendre ça en considération.</p>    <blockquote><p>Cet article ne vise pas a cracher sur fxguide (J'y vais souvent et je trouve qu'ils font un travail de titan!) mais à attirer l’attention de ceux qui prennent ses articles comme parole d'évangile sans prendre la mesure des implications techniques que peut avoir l'utilisation d'outils aussi complexes et évolués dans une production et en particulier sur un long métrage d'animation.</p></blockquote>


<p>fxguide est un des sites de news CGI le plus connu. C'est un des quelques sites (le seul?) a fournir autant d'articles et d'interviews de personnes et des logiciels utilisé dans la CGI.</p>


<p>Il y a quelques jours, je lisais <a href="http://www.fxguide.com/featured/disneys-new-production-renderer-hyperion-yes-disney/" hreflang="en">cet article</a>.</p>


<p>J'ai tendance à prendre ce que rapporte fxguide avec des pincettes car il offusque souvent des détails qui sont importants dans le cas d'une production (toute les questions qui pourraient commencer par "Ok, mais qu'est ce qui ce passe si..."). Il y a une sorte de syndrome: "tout est allé pour le mieux dans le meilleur des mondes car la flexibilité ainsi que la polyvalence de nos outils internes, nous a permis de livrer dans les temps limité et à cout très faible, des plans d'une qualité sans commune mesure dans l'histoire de notre industrie". Ce type de discours n'est pas surprenant ni vraiment choquant dans notre milieu, même si la réalité du terrain ressemble souvent plus à ça qu'autre chose:</p>


<p><a href="media/ea27ea65.PicassoGuernica_800.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/PicassoGuernica_800.jpg" title="PicassoGuernica_800.jpg"><img src="media/0632ae5a..PicassoGuernica_800_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/.PicassoGuernica_800_m.jpg" alt="PicassoGuernica_800.jpg" style="display:block; margin:0 auto;" title="PicassoGuernica_800.jpg, oct. 2014"  height="250" width="560" /></a></p>
<center><i><a href="https://en.wikipedia.org/wiki/Guernica_%28painting%29" hreflang="en">Guernica</a> from <a href="https://en.wikipedia.org/wiki/Pablo_Picasso" hreflang="en">Pablo Picasso</a></i></center>



<p>C'était une blague (Vous pouvez rigoler <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>Mais pour la première fois, fxguide semble rapporter des propos autour du deep compositing dans le cadre d'un long métrage d'animation. Et ces mots viennent de Hank Driskill, Superviseur Technique sur Big Hero 6 (le prochain Disney). Si vous êtes un superviseur, veuillez prendre note de ces sages paroles:</p>


<blockquote><p>The renderer and pipeline can render with deep data. It was not used on all shots, however. “We use it sparingly just because of the data management concerns,” says Driskill, referring to the huge data sets complex deep data rendering can produce.</p></blockquote>


<p>Sans déconner... Il n'y a que Weta pour faire un format de fichier aussi massif a stocker, lourd a l'usage et fou que le deep data. Mais la vérité c'est qu'on est pas souvent à Weta et qu'on ne travail pas avec les même budgets.</p>


<p>Notez les propos de fxguide "It was not used on all shots" suivis de ceux de Dirskill, beaucoup plus contrastés: "We use it sparingly". Les deux phrases veulent dires la même chose, mais chacun aborde le problème d'une manière différente (verre a moitié vide VS verre à moitié plein).</p>


<p>Il y a un fossé énorme entre ce que fxguide rapporte et le quotidien des graphistes, les vas et viens incessants entre la RnD et la production avec les deadlines qui approchent quand un outil ne fonctionne pas. Il y a une bonne raison à ça: La CGI est très timide quand vient le temps de communiquer. Il n'y a rien de mal à ça. La plupart des grosses compagnies qui travaillent pour de gros client adopte une approche similaire. Rien n'est calculé et personne n'est réellement briefé mais ce qui est dit sera souvent "doux" vis-avis du studio, de la prod et des collègues. Il faut en être conscient quand de tels informations sont rapportées: fxguide, et par extension, vous, n'avez jamais toute l'histoire.</p>


<p>Ceci amène fxguide à faire une grosse abstraction de comment les choses tournent réellement dans un studio et à quel point la réalité peut être plus nuancé. Mais quel superviseur digne de ce nom pourrait dire publiquement: "Ça été une bordel monstre cette prod! Les outils internes sont tous à foutre à la poubelle, il n'y a rien a en tirer!". Pourtant de tels propos peuvent arriver en off sur une prod un peu difficile. C'est quelque chose que vous devez garder à l'esprit quand vous vous appuyez sur des articles de fxguide pour choisir vos outils et la manière dont vous voulez travailler. Vous devez être tout particulièrement vigilant si vous avez pas/peu d’expérience en long métrage qui implique un management de la consistance des données colossale.</p>


<p>Tout ceci peut sembler évident pour beaucoup de monde mais dans la mesure ou j'ai entendu pas mal de superviseurs prendre fxguide comme référence <em>de ce qui ce fait dans l'industrie</em>, je me dis qu'un brin de retenue vis-à-vis de la vision de l'industrie renvoyée par de tels sites ne serait pas fortuite: Vous êtes des artistes. Prenez les outils que vous connaissez et foncez! (D’où l’intérêt de connaitre les outils à l'avance et de ne pas attendre d'avoir un long sur les bras pour faire un saut qui pourrait être fatal)</p>


<p>Et pour le fun:</p>


<p><img src="media/14be1a91.fxguide_batman_robin.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_10_18_fx_guide/fxguide_batman_robin.jpg" alt="fxguide_batman_robin.jpg" style="display:block; margin:0 auto;" title="fxguide_batman_robin.jpg, oct. 2014"  height="310" width="320" /></p>


<p>Vous avez plus de chances de sortir un film, avec des mauvais outils que vous maitrisez qu'avec les outils super évolués auxquels vous ne pipez rien. C'est quelque chose à prendre en compte quand on dispose de ressources limitées. <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>J'espère que cet humble billet vous sera utile. N'hésitez pas à commentez, surtout si vous n'êtes pas d'accord! :)</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:8656195ac281915dc1a9d811598b2c50
title: Ocarina Baby DragonTooth de Songbird
uri: Ocarina-Baby-DragonTooth-de-Songbird
url: http://www.fevrierdorian.com/blog/post/2014/12/05/Ocarina-Baby-DragonTooth-de-Songbird
content:
<p><img src="media/06611ae2.baby_dragontooth_songbird_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_tn.png" alt="baby_dragontooth_songbird_tn.png" style="float:left; margin: 0 1em 1em 0;" title="baby_dragontooth_songbird_tn.png, fév. 2015"  height="150" width="150" />Cela fait un moment que j'ai cet ocarina mais du fait du peu d’intérêt pour ce type d'instrument sur la scène francophone je ne voyais pas de raisons d'en parler.</p>


<p>J'ai cependant l'impression que ça change et que certains artisans francophones s'y mettent tout comme certains musiciens, eux aussi français, sortent de l'ombre pour échanger. <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>Comme il s'agit de musique, il est assez normal qu'il soit difficile, sur internet, de savoir en quelles quantités les gens s’intéressent à cet instrument millénaire, mais la quantité de personnes semblant chercher des conseils pour leur premier ocarina est bien visible et force est de constater qu'elle n'est pas négligeable (en gardant à l'esprit qu'on est sur un marché de niche).</p>


<p>C'est un peu pour tous ces anonymes que je partage mon avis sur l'ocarina <a href="http://www.songbirdocarina.com/products/baby-dragontooth-ocarina-in-metallic-lustre" hreflang="en">Baby DragonTooth</a> de <a href="http://www.songbirdocarina.com/" hreflang="en">Songbird</a> que j'ai depuis presque un an.</p>


<h3>Ocarina, l'inception</h3>


<p>Comme la plupart des clampins qui ont découvert l'ocarina, ça s'est fait avec <a href="http://fr.wikipedia.org/wiki/The_Legend_of_Zelda:_Ocarina_of_Time" hreflang="fr">The Legend of Zelda: Ocarina Of Time</a> (OOT pour les intimes). Je soupçonne que la version 3DS ressortie en 2012 (combiné à l'ouverture du magasin <a href="http://www.buyocarina.com/fr/" hreflang="fr">Buy Ocarina</a> au marché français) n'est pas étranger aux "regain" que j'observe. Oui, cet épisode de Zelda est un monument du jeu vidéo pour milles raisons que je n’évoquerais pas. Mais évoquez ce jeu à la plupart des gens qui l'ont parcouru lors de sa sortie original en 1995 et vous pourrez sûrement lire les traits de <a href="https://imgur.com/gallery/qtfK183" hreflang="en">la nostalgie</a> sur le visage du preu joueur qui vous contera ces déambulations dans l'univers si particulier (entre drôle et macabre) de cet épisode.</p>


<p>Mais OOT c’était il y a vingt ans, pourquoi s'y intéresser maintenant? Et bien simplement parce que je fais parti de ses artistes ratés qui aimeraient jouer un instrument <a href="http://www.bouletcorp.com/2010/03/09/pas-de-repos-pour-les-guerriers-2/" hreflang="fr">sans avoir le moindre don pour la musique</a> et encore moins le temps d'apprendre...</p>


<p>Je ne me souvient plus ou j'ai pu tomber sur une info me montrant que les ocarinas existaient vraiment mais après avoir vaguement hésité (le mot <em>vaguement</em> fait ici référence au temps d’hésitation de l'occidental moyen devant un objet désiré soit de l'ordre de quelques millisecondes), je décidais d'en acquérir un. J'ai suivi les conseils de la vidéo de David Erick Ramos <a href="https://www.youtube.com/watch?v=9DbSBYlMsr8" hreflang="en">Choosing Your First Ocarina (Octalk!)</a> et opté pour un ocarina six trous qu'il juge plus facile à apprendre/maîtriser, un moyen pour moi de tester sans sauter sur un modèle jugé plus traditionnel à douze trous ( La question existentielle qui porta immédiatement préjudice dans mon esprit de primate fut: "Douze trous, dix doigts. Embrouille? Esbroufe? Que veut on me cacher?").</p>


<p>J'ai également pu compter sur la bienveillance de mes proches:</p>


<blockquote><p>Lol, j'ai tapé "Ocarina" sur google, je connaissais pas mais j'étais sur que c'était une merde de ce genre :P.
Le truc inutile, geek et ou faut apprendre des trucs.</p></blockquote>



<blockquote><p>mdr! Et tu va aussi foutre les collants blancs et la tunique verte pourri? XD</p></blockquote>



<blockquote><p>J'crois qu'j'préfère encore quand tu code...</p></blockquote>


<p>C'est donc sous ce tonnerre d'encouragements que je partais à la recherche d'un ocarina six trous sympathique. <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>Un ocarina, oui mais lequel?</h3>


<p>Première chose: Je ne voulais pas (mais alors pas du tout) un ocarina estampillé Zelda (je n'ai jamais été un grand fan de l'extension à profusion des jeux vidéos dans le monde réel). Je me demandais souvent pourquoi ce magnifique ocarina que je voyais s'afficher sur mon écran avait ce ridicule symbole de la triforce que je ne me voyais pas avoir sous le pif à chaque utilisation tel un <a href="http://www.bouletcorp.com/2010/08/20/la-bete-en-moi/" hreflang="fr">jinggle de pub pour enfant</a>: "Joue de l'ocarina pour avoir de la triforce en toi". <em>Orh yeah...</em> Si les ocarinas jouaient sur des fréquences plus basse, ça aurait presque pu marcher. Mais la <a href="https://fr.wikipedia.org/wiki/Tessiture" hreflang="fr">tessiture</a> particulière de ce type d'instrument rappelant plus le cri d'un oisillon puceau en détresse que le raclement de gorge d'un Arnold sous testostérone rends caduque toute tentative d'assimilation à une quelconque forme de virilité, aussi relative soit elle (L'univers Hylien est plus proche du transgenre japonnais que l'univers de prépubère en rûte d'un quelconque GTA...).</p>


<p>Les modèles six trous ne courant pas les rues et comme l’idée de souffler dans une <a href="media/841212bd.baby_dragontooth_songbird_015.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_015.jpg">testicule de taureau</a> m’était également désagréable, mes choix s'en retrouvaient implicitement réduits.</p>


<p>Je me tournai finalement vers Songbird et plus précisément le Baby DragonTooth qui était à la fois original tout en ayant une forme un peu classe.</p>


<p>Pas grand chose à dire sur l’envoi. Acheté le 20 février 2014 et reçu trois semaines plus tard. Faut pas être pressé (adepte de l'achat compulsif, te voila prévenu). C'est bien protégé et il est arrivé <del>sans se presseeeeer</del> nickel.</p>


<p>L'emballage est.. <em>(on s'en fout)</em>. Un petit feuillet est inclus avec d'un coté la gamme ainsi qu'une liste de tablatures de différents airs. Mon premier fut Joyeux Anniversaire, sûrement le plus simple de tous et le plus facile à caler quelque part (on commence toujours par sa famille, les seuls capable de supporter nos âneries, le sourire de compassion faisant foi...).</p>


<p>Puis vient la bête, ou plutôt, sa dent (oui parce que <em>tooth</em>, c'est de l'anglais... Et ça veut dire dent... Donc <em>dragontooth</em> ça veut dire... Enfin vous avez l’idée <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 href="media/52489146.baby_dragontooth_songbird_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_001.jpg" title="baby_dragontooth_songbird_001.jpg"><img src="media/a8bf8a10..baby_dragontooth_songbird_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_001_m.jpg" alt="baby_dragontooth_songbird_001.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_001.jpg, fév. 2015"  height="419" width="560" /></a></p>


<p><a href="media/f4943deb.baby_dragontooth_songbird_002.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_002.jpg" title="baby_dragontooth_songbird_002.jpg"><img src="media/2ad0c3de..baby_dragontooth_songbird_002_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_002_m.jpg" alt="baby_dragontooth_songbird_002.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_002.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/8753c430.baby_dragontooth_songbird_003.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_003.jpg" title="baby_dragontooth_songbird_003.jpg"><img src="media/9a0c2139..baby_dragontooth_songbird_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_003_m.jpg" alt="baby_dragontooth_songbird_003.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_003.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/a1bdc51b.baby_dragontooth_songbird_004.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_004.jpg" title="baby_dragontooth_songbird_004.jpg"><img src="media/93211344..baby_dragontooth_songbird_004_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_004_m.jpg" alt="baby_dragontooth_songbird_004.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_004.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/8cf23a98.baby_dragontooth_songbird_005.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_005.jpg" title="baby_dragontooth_songbird_005.jpg"><img src="media/f6fdfcd2..baby_dragontooth_songbird_005_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_005_m.jpg" alt="baby_dragontooth_songbird_005.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_005.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/a7a300dc.baby_dragontooth_songbird_006.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_006.jpg" title="baby_dragontooth_songbird_006.jpg"><img src="media/9e4979b0..baby_dragontooth_songbird_006_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_006_m.jpg" alt="baby_dragontooth_songbird_006.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_006.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/903563c3.baby_dragontooth_songbird_007.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_007.jpg" title="baby_dragontooth_songbird_007.jpg"><img src="media/d4503314..baby_dragontooth_songbird_007_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_007_m.jpg" alt="baby_dragontooth_songbird_007.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_007.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/87f11a65.baby_dragontooth_songbird_008.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_008.jpg" title="baby_dragontooth_songbird_008.jpg"><img src="media/c663f4e5..baby_dragontooth_songbird_008_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_008_m.jpg" alt="baby_dragontooth_songbird_008.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_008.jpg, fév. 2015"  height="560" width="420" /></a></p>


<p><a href="media/b796bfac.baby_dragontooth_songbird_009.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_009.jpg" title="baby_dragontooth_songbird_009.jpg"><img src="media/de43bcfc..baby_dragontooth_songbird_009_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_009_m.jpg" alt="baby_dragontooth_songbird_009.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_009.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/156cfcc9.baby_dragontooth_songbird_010.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_010.jpg" title="baby_dragontooth_songbird_010.jpg"><img src="media/dfaddeff..baby_dragontooth_songbird_010_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_010_m.jpg" alt="baby_dragontooth_songbird_010.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_010.jpg, fév. 2015"  height="419" width="560" /></a></p>


<p><a href="media/4a630b77.baby_dragontooth_songbird_011.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_011.jpg" title="baby_dragontooth_songbird_011.jpg"><img src="media/1e6fa3d1..baby_dragontooth_songbird_011_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_011_m.jpg" alt="baby_dragontooth_songbird_011.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_011.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/fed37c33.baby_dragontooth_songbird_012.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_012.jpg" title="baby_dragontooth_songbird_012.jpg"><img src="media/b70f6f89..baby_dragontooth_songbird_012_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_012_m.jpg" alt="baby_dragontooth_songbird_012.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_012.jpg, fév. 2015"  height="560" width="420" /></a></p>


<p><a href="media/e3ec5d71.baby_dragontooth_songbird_013.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_013.jpg" title="baby_dragontooth_songbird_013.jpg"><img src="media/aaab88ba..baby_dragontooth_songbird_013_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_013_m.jpg" alt="baby_dragontooth_songbird_013.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_013.jpg, fév. 2015"  height="420" width="560" /></a></p>


<p><a href="media/886799ef.baby_dragontooth_songbird_014.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_014.jpg" title="baby_dragontooth_songbird_014.jpg"><img src="media/56fdbefc..baby_dragontooth_songbird_014_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_014_m.jpg" alt="baby_dragontooth_songbird_014.jpg" style="display:block; margin:0 auto;" title="baby_dragontooth_songbird_014.jpg, fév. 2015"  height="420" width="560" /></a></p>


<blockquote><p>Note: Les photos ne dates pas du premier jours.</p></blockquote>


<p>Premier constat: Ilaybôôôôh! :3 #kawaiiface</p>


<p>Sérieusement, ça été le coup de foudre! J'adore le reflet bleu pétrole ainsi que la forme général de l'objet. Il dispose d'un coté légèrement aplati bien classe.</p>


<p>Les trous sont très bien placé, pas de crampes possibles. J'aurais apprécié un très léger creux aux niveaux des doigts pour bien les sentir quand on joue.</p>


<h3>Sensation de fragilité</h3>


<p>Les ocarinas ont la réputation d’être aussi solides qu'un cours de bourse (je ne parle plus du taureau). Comme il est assez difficile de "tester" la solidité d'un objet sans avoir à le casser je vais plutôt parler de <em>sensation de fragilité</em>. Force est de constater que, sûrement due à sa petitesse, ce modèle semble assez robuste et devrait résister à la plupart des chocs (un peu comme un mug).</p>


<h3>Le son</h3>


<p>Avant de commencer:</p>
<ol>
<li>Je ne suis pas musicien.</li>
<li>Je n'ai aucun autre ocarina pour comparer.</li>
<li>Je suis un <del>autodidacte</del> boulet pour ce qui est des instruments à vent (mes cours de flûte y sont sûrement pour beaucoup...).</li>
</ol>


<p>Bref, avant de prendre cette review pour argent comptant sachez que vous marchez sur un terrain miné par le noobisme et le haut niveau d’incompétence qui le caractérise. Si vous êtes de ceux là, vous compatirez sûrement. Les autres, vous noterez le ton humoriste bancale visant à ne point faire perdre son temps au lecteur quand bien même il ne trouverait moindre valeur au sujet présent dans cette colonne.</p>


<p>D'un point de vue purement acoustique j'ai été agréablement surpris. Le son est super jolie :3 #kawaiifaceagain. La différence de souffle nécessaire entre le Do grave (tous les trous bouchés) et le Mi aigu n'est pas énorme et viens naturellement. Un soprano est par définition aigu et celui ci ne déloge pas à la règle. Il est tout à fait possible d'y jouer pendant plusieurs heures mais n’hésitez pas à utiliser des boules Quies si vous jouez longtemps une partition aigu.</p>


<p>Il n'y a pas des masses de vidéos sur Youtube l'utilisant mais j'ai réussi à en trouver <a href="https://www.youtube.com/watch?v=EIFULXnc6R8" hreflang="en">quelques</a> <a href="https://www.youtube.com/watch?v=LEZ7CSpJkts" hreflang="en">unes</a>.</p>


<p>J'ai l'impression que l'ocarina produit un son différent (plus strident) lors des premières secondes d'utilisation si ce dernier a été stocké dans un endroit froid. C'est peut être mes oreilles qui déconnent (ou que le mot <em>froid</em> est à prendre au sens montréalais mais ça s'est produit plus d'une fois. Dans ces cas la je bouche le trou principal avec mon pouce, ouvre tous les autres et souffle fort quelques secondes pour "vider" l'air froid et chauffer l'ocarina (ne retirez pas votre pouce à ce moment là ou vos tympan vous lâcheront pour de bon). Si quelqu'un pouvait me confirmer que la chaleur sert a quelque chose dans le son généré qu'il n’hésite pas. :)</p>


<h3>Tessiture</h3>

<blockquote><p>Pour les boulets qui ont ratés mon lien plus tôt <a href="https://fr.wikipedia.org/wiki/Tessiture" hreflang="fr">le revoici</a>.</p></blockquote>


<p>Le Baby DragonTooth est donc un Soprano et produit un son très clair sans nécessairement être extrêmement fort. J'avais très peur de ne pas pouvoir jouer en intérieur mais cela ne pose finalement aucun problème. Je n'ai malheureusement pas d'appareil pour mesurer les décibels et vous donner une idée.</p>


<p>La page du produit stipule qu'il dispose d'une étendue de Sol4 à Si5 (G5-B6) soit de la touche 59 à 75 d'un piano classique (783,991Hz à 1975,53Hz d'<a href="https://fr.wikipedia.org/wiki/Fr%C3%A9quences_des_touches_du_piano" hreflang="fr">après Wikipedia</a>). En pratique, la première note sonne plutôt comme un Fa# (demi ton avant le Sol). Quand on souffle un peu plus fort on obtient en effet un Sol. C'est suivant la force du souffle (les premières notes y étant beaucoup plus sensible que les dernières).</p>


<p>Gardez bien à l'esprit que la première note n'est donc pas un Do (comme le petit papier livré avec vous le fait croire). Quand vous jouez seul ce n'est pas très important, vous transposez naturellement. Mais si vous voulez profiter de cet ocarina pour apprendre les bases du solfège il faut le savoir. En effet, si vous voulez vous caler sur une mélodie existante (groupe ou vidéo) commençant par un Do, vous aurez l'impression de jouer cinq tons au dessus.</p>


<p>Pas de quoi paniquer cela dit, mais si vous avez un esprit ultra cartésien vous serez sûrement tenté d'aller, comme un michu, acheter un accordeur... Juste pour tester... (J'ai acheté un accordeur ok?... Juste pour tester...).</p>


<h3>Accordage</h3>

<blockquote><p>Je me demandais: Quelle est le mot qui défini qu'un instrument à vents est accordé ou non? Le mot anglais est <em>tuning</em> mais je n’ai pas trouve l’équivalent français et j'ai comme l'impression que parler d'accordage dans le cas d'un instrument dénudé de toute forme de corde est un non sens. Si vous avez la réponse, un grand merci d'avance pour me laisser un commentaire. :)</p></blockquote>


<p>Voila.</p>


<p>Donc, maintenant que les blaireaux du solfège ont sautés sur la rubrique commentaires en vue d'aller étaler leur science ça laisse du temps aux membres de la catégorie suivante que sont les blaireaux ignares de parler de l'accordage. <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>Vous l'aurez compris, un ocarina ne s'accorde qu'une fois: A la fabrication. Si vous le l'avez pas compris, sachez qu'un ocarina est fait en argile cuit (et si vous ne voyez pas le rapport, vous pouvez vous jeter d'un pont). Une tentative de sauvetage est peut être possible (limer certains trous) mais il vaut mieux demander de l'aide sur <a href="http://theocarinanetwork.com/" hreflang="en">The Ocarina Network</a> (TON pour les intimes), le seul forum fureté par des spécialistes...</p>


<p>Il est important de constater que la force du souffle joue sur le timbre de la note. Ainsi, j'ai remarqué que, tous les trous bouchés et en fonction du souffle, on peut faire varier de presque une note. Jouer en face d'un accordeur et vous le verrez sûrement jouer au yoyo sur les notes basses. Sur certaines partitions, ça peut vous <del>sauver</del> (on parlerais plus de cache misère).</p>


<p>Je sais que certains artisans utilisent des <a href="http://www.sixthstreetocarina.com/blogs/frequently-asked-questions/1243212-how-are-sixth-street-ocarinas-tuned" hreflang="en">souffleurs electroniques</a> en vue d'accorder leurs ocarinas. C'est sûrement la meilleur façons de faire. Je ne sais pas si Songbird utilise ça mais si quelqu'un a l'info vous pouvez allez rejoindre les blaireaux du solfège plus bas qui ne vont pas tarder à revenir.</p>


<h3>Truc aux possesseurs</h3>

<p>Chris Gale a pris l'habitude de nous gratifier d'une ou plusieurs astuces suivant le modèle d'ocarina qu'elle test, chose que je trouve tout à fait appréciable et je vais donc faire de même ici (même si je ne prétend pas avoir son niveau d'expertise):</p>

<ul>
<li>N'englobez pas le bec de l'ocarina avec vos lèvres, pressez simplement (et doucement) le bout de vos lèvres dessus. D'une, ça évite (un peu) de dégueulasser votre ocarina avec votre salive (il vous en remercie) et de deux, ça vous permet de vous servir subtilement de votre bouche (mâchoire/langue) pour contrôler le flux d'air que vous lui envoyez (un peu comme quand vous sifflez). Vous ressentirez aussi beaucoup plus ce flux d'air si il touche vos lèvres là ou, en englobant le bec, vous ne sentirez rien. Notez aussi que plus vous gober le bec de l'ocarina, plus vous aurez du mal à fabriquer le fameux "tseuh!" entre chaque note. Sur un morceau lent, on peut s'appuyer sur le contrôle de sa respiration pour couper une note mais sur morceau rapide l’échec est radicale. La pose des lèvres est importante ne soyez pas timide, tentez des trucs différents. Ça permet de <em>sentir</em> votre instrument. Essayez de souffler à un rythme constant en déplaçant votre ocarina, vous verrez que le son qui sort varie de même.</li>
</ul>

<ul>
<li>Les notes aiguës menacent parfois de "souffler" au lieu de sonner. D'une manière générale, augmentez légèrement le flux d'air sur les notes aiguës. Plus subtilement, ramener (très) légèrement l'ocarina proche de votre poitrine ou tournez le (l'ocarina, pas vous!) très légèrement sur le cote (ramenez la pointe vers vous). En faisant cela, vous ne devriez pas avoir à faire varier votre souffle pour sortir les notes aiguës (ce qui est appréciable sur des morceaux rapides).</li>
</ul>

<ul>
<li>Si vous êtes amené à jouer des partitions aiguës longtemps en intérieur, mettez des boules Quies afin d’éviter de finir sourd rapidement. Pour peu que la pièce dans laquelle vous jouez résonne un peu, les sons aiguës mettront beaucoup de temps à se <em>dégrader</em> et ce n'est vraiment pas agréable.</li>
</ul>

<ul>
<li>Commencez toujours par jouer un nouveau morceau en vitesse réduite. On est souvent tenté de suivre la mélodie originale mais, tel un Schumacher junior qui veut sentir l'ivresse de l'asphalte, il y a plus de chances que vous sentiez le sable des sacs de protections du premier virage (et ça c'est si vous avez de la chance...). Je vous assure que vous apprenez plus vite en jouant lentement (paradoxal hein? <img src="media/af8fdcdb.zinzin.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/zinzin.gif" alt=":zinzin:" class="smiley" /> ) un doigté parfait plutôt qu'en ratant toutes les notes. Comme c'est un ocarina six trous, certains doigtés s’enchaînent d'une manière peu naturel (c'est d’ailleurs une remarque que j'entends souvent contre les ocarinas six trous).</li>
</ul>

<ul>
<li>Quand vous commencez à connaître le doigté d'une mélodie (pas avant sinon ça ne marche pas des masses), essayez d'avoir une approche plus instinctive. Chacun a sa méthode. Fermez les yeux et bougez doucement votre corps au fil de votre souffle. Ça ne doit pas être un effort vraiment conscient mais juste un moyen de se laisser porter par la musique que vous jouez. Comme si vous vous berciez dans votre propre musique. Vous serez surpris de voir que parfois vous jouerez un morceau entier sans la moindre fausse note et sans que vous ayez pour autant réfléchi à ou vous placiez vos doigts. C'est la gratification suprême du débutant, celui de <em>jouer</em> un instrument.</li>
</ul>

<ul>
<li>Jouez ce qui vous fait plaisir! Vous n’êtes plus un petit enfant incrédule, vous avez bouffé de la musique comme n'importe quel ado frustré. Bien que piteux musicien, votre oreille est affûté. Vous savez reconnaître une fausse note. L'adulte de la droiture droite qui est en vous saura vous le faire remarquer, vous rappeler que vous êtes une bouse fini, que vous perdez votre temps et n'irez nul part. Il rira de vous comme ce pauvre gars qui vous prenait toujours votre dessert au collège. Mais rassurez vous, c'est tout a fait normal: Le monde qui nous entoure nous flatte constamment. Nous ne supportons pas la difficulté car elle nous rappel qu'on est sacrément con. Nous estimons que nos divertissements doivent être simples (ce qui ne nous élève pas). Réapprendre à apprendre, c'est accepter de se mentir et faire disparaître son incompétence derrière un regards d'enfant: Celui qui jubile à chaque mètre parcouru et franchit des montagnes sans vraiment s'en rendre compte. Quand les premiers morceaux sortiront, vous prendrez conscience que cette incompétence sciemment nié disparaît progressivement au profit d'un plaisir bien réel.</li>
</ul>


<h3>Prix</h3>


<p>Moi ça été $29.95 + $12.00 (FDP vers Canada) = $41.95</p>


<h3>Conclusion</h3>

<p>Petit coucou aux gros flemmards qui sautent ici sans lire la moindre ligne des sections précédentes, tu te reconnaîtra (On le fait tous!  <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>Et bien très satisfait de mon achat. Je l'utilise souvent. J’essaie d'en faire quelques minutes par jour et ça vient doucement.</p>


<p>Ne vous laissez pas rebuter par le discours New Age propre à Songbird (si tu est à l’écoute des sons de ton <em>coaaarh</em> ton <em>aaaame</em> va s’élever au huitième ciel grâce aux vibrations acoustiques naturelles utilisées depuis des millénaires par les civilisations <em>ancestraaaaales</em> pour soigner les maladies rares et raffermir l'esprit... <a href="https://www.youtube.com/watch?v=t7xG7uVOfVs&amp;t=10s" hreflang="fr">Ouaih ouaih...</a>).</p>


<p>J'invite les artisans français (et européen) à se faire connaître ainsi qu'a <a href="http://www.partition-ocarina.fr/" hreflang="fr">partition ocarina</a> (site horrible mais communauté adorable) à les mettre en avant car comme tout secteur de niche, il ne se développe que par le bouche à oreille. <img src="media/98711e7e.france.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/france.gif" alt=":franceHappy:" 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:83c50f748c8c8e9e4136ec3d3f2aec95
title: Ocarina Baby DragonTooth de Songbird
uri: 2015-09-06-Ocarina-Baby-DragonTooth-de-Songbird
url: http://www.fevrierdorian.com/blog/post/2014/12/05/Ocarina-Baby-DragonTooth-de-Songbird
content:
<figure style="float: left; margin: 0 1em 1em 0;"><img style="float: left; width: 150px; height: 150px;" class="media" alt="baby_dragontooth_songbird_tn.png" src="media/06611ae2.baby_dragontooth_songbird_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_tn.png" /></figure><p>Cela fait un moment que j'ai cet ocarina mais du fait du peu d’intérêt pour ce type d'instrument sur la scène francophone je ne voyais pas de raisons d'en parler.</p><p>J'ai cependant l'impression que ça change et que certains artisans francophones s'y mettent tout comme certains musiciens, eux aussi français, sortent de l'ombre pour échanger. <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>Comme il s'agit de musique, il est assez normal qu'il soit difficile, sur internet, de savoir en quelles quantités les gens s’intéressent à cet instrument millénaire, mais la quantité de personnes semblant chercher des conseils pour leur premier ocarina est bien visible et force est de constater qu'elle n'est pas négligeable (en gardant à l'esprit qu'on est sur un marché de niche).</p><p>C'est un peu pour tous ces anonymes que je partage mon avis sur l'ocarina <a hreflang="en" href="http://www.songbirdocarina.com/products/baby-dragontooth-ocarina-in-metallic-lustre">Baby DragonTooth</a> de <a hreflang="en" href="http://www.songbirdocarina.com/">Songbird</a> que j'ai depuis presque un an.</p><h3>Ocarina, l'inception</h3><p>Comme la plupart des clampins qui ont découvert l'ocarina, ça s'est fait avec <a hreflang="fr" href="http://fr.wikipedia.org/wiki/The_Legend_of_Zelda:_Ocarina_of_Time">The Legend of Zelda: Ocarina Of Time</a> (OOT pour les intimes). Je soupçonne que la version 3DS ressortie en 2012 (combiné à l'ouverture du magasin <a hreflang="fr" href="http://www.buyocarina.com/fr/">Buy Ocarina</a> au marché français) n'est pas étranger aux "regain" que j'observe. Oui, cet épisode de Zelda est un monument du jeu vidéo pour milles raisons que je n’évoquerais pas. Mais évoquez ce jeu à la plupart des gens qui l'ont parcouru lors de sa sortie original en 1995 et vous pourrez sûrement lire les traits de <a hreflang="en" href="https://imgur.com/gallery/qtfK183">la nostalgie</a> sur le visage du preu joueur qui vous contera ces déambulations dans l'univers si particulier (entre drôle et macabre) de cet épisode.</p><p>Mais OOT c’était il y a vingt ans, pourquoi s'y intéresser maintenant? Et bien simplement parce que je fais parti de ses artistes ratés qui aimeraient jouer un instrument <a hreflang="fr" href="http://www.bouletcorp.com/2010/03/09/pas-de-repos-pour-les-guerriers-2/">sans avoir le moindre don pour la musique</a> et encore moins le temps d'apprendre...</p><p>Je ne me souvient plus ou j'ai pu tomber sur une info me montrant que les ocarinas existaient vraiment mais après avoir vaguement hésité (le mot <em>vaguement</em> fait ici référence au temps d’hésitation de l'occidental moyen devant un objet désiré soit de l'ordre de quelques millisecondes), je décidais d'en acquérir un. J'ai suivi les conseils de la vidéo de David Erick Ramos <a hreflang="en" href="https://www.youtube.com/watch?v=9DbSBYlMsr8">Choosing Your First Ocarina (Octalk!)</a> et opté pour un ocarina six trous qu'il juge plus facile à apprendre/maîtriser, un moyen pour moi de tester sans sauter sur un modèle jugé plus traditionnel à douze trous (La question existentielle qui porta immédiatement préjudice dans mon esprit de primate fut: "Douze trous, dix doigts. Embrouille? Esbroufe? Que veut on me cacher?").</p><p>J'ai également pu compter sur la bienveillance de mes proches:</p><blockquote><p>Lol, j'ai tapé "Ocarina" sur google, je connaissais pas mais j'étais sur que c'était une merde de ce genre :P. Le truc inutile, geek et ou faut apprendre des trucs.</p></blockquote><blockquote><p>mdr! Et tu va aussi foutre les collants blancs et la tunique verte pourri? XD</p></blockquote><blockquote><p>J'crois qu'j'préfère encore quand tu code...</p></blockquote><p>C'est donc sous ce tonnerre d'encouragements que je partais à la recherche d'un ocarina six trous sympathique. <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>Un ocarina, oui mais lequel?</h3><p>Première chose: Je ne voulais pas (mais alors pas du tout) un ocarina estampillé Zelda (je n'ai jamais été un grand fan de l'extension à profusion des jeux vidéos dans le monde réel). Je me demandais souvent pourquoi ce magnifique ocarina que je voyais s'afficher sur mon écran avait ce ridicule symbole de la triforce que je ne me voyais pas avoir sous le pif à chaque utilisation tel un <a hreflang="fr" href="http://www.bouletcorp.com/2010/08/20/la-bete-en-moi/">jinggle de pub pour enfant</a>: "Joue de l'ocarina pour avoir de la triforce en toi". <em>Orh yeah...</em> Si les ocarinas jouaient sur des fréquences plus basse, ça aurait presque pu marcher. Mais la <a hreflang="fr" href="https://fr.wikipedia.org/wiki/Tessiture">tessiture</a> particulière de ce type d'instrument rappelant plus le cri d'un oisillon puceau en détresse que le raclement de gorge d'un Arnold sous testostérone rends caduque toute tentative d'assimilation à une quelconque forme de virilité, aussi relative soit elle (L'univers Hylien est plus proche du transgenre japonnais que l'univers de prépubère en rûte d'un quelconque GTA...).</p><p>Les modèles six trous ne courant pas les rues et comme l’idée de souffler dans une <a href="media/841212bd.baby_dragontooth_songbird_015.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_015.jpg">testicule de taureau</a> m’était également désagréable, mes choix s'en retrouvaient implicitement réduits.</p><p>Je me tournai finalement vers Songbird et plus précisément le Baby DragonTooth qui était à la fois original tout en ayant une forme un peu classe.</p><p>Pas grand chose à dire sur l’envoi. Acheté le 20 février 2014 et reçu trois semaines plus tard. Faut pas être pressé (adepte de l'achat compulsif, te voila prévenu). C'est bien protégé et il est arrivé <s>sans se presseeeeer</s> nickel.</p><p>L'emballage est.. <em>(on s'en fout)</em>. Un petit feuillet est inclus avec d'un coté la gamme ainsi qu'une liste de tablatures de différents airs. Mon premier fut Joyeux Anniversaire, sûrement le plus simple de tous et le plus facile à caler quelque part (on commence toujours par sa famille, les seuls capable de supporter nos âneries, le sourire de compassion faisant foi...).</p><p>Puis vient la bête, ou plutôt, sa dent (oui parce que <em>tooth</em>, c'est de l'anglais... Et ça veut dire dent... Donc <em>dragontooth</em> ça veut dire... Enfin vous avez l’idée <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> ):</p><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/52489146.baby_dragontooth_songbird_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_001.jpg"><img style="width: 560px; height: 419px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_001.jpg" src="media/a8bf8a10..baby_dragontooth_songbird_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_001_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/f4943deb.baby_dragontooth_songbird_002.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_002.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_002.jpg" src="media/2ad0c3de..baby_dragontooth_songbird_002_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_002_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/8753c430.baby_dragontooth_songbird_003.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_003.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_003.jpg" src="media/9a0c2139..baby_dragontooth_songbird_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_003_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/a1bdc51b.baby_dragontooth_songbird_004.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_004.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_004.jpg" src="media/93211344..baby_dragontooth_songbird_004_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_004_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/8cf23a98.baby_dragontooth_songbird_005.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_005.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_005.jpg" src="media/f6fdfcd2..baby_dragontooth_songbird_005_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_005_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/a7a300dc.baby_dragontooth_songbird_006.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_006.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_006.jpg" src="media/9e4979b0..baby_dragontooth_songbird_006_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_006_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/903563c3.baby_dragontooth_songbird_007.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_007.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_007.jpg" src="media/d4503314..baby_dragontooth_songbird_007_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_007_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/87f11a65.baby_dragontooth_songbird_008.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_008.jpg"><img style="width: 420px; height: 560px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_008.jpg" src="media/c663f4e5..baby_dragontooth_songbird_008_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_008_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/b796bfac.baby_dragontooth_songbird_009.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_009.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_009.jpg" src="media/de43bcfc..baby_dragontooth_songbird_009_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_009_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/156cfcc9.baby_dragontooth_songbird_010.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_010.jpg"><img style="width: 560px; height: 419px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_010.jpg" src="media/dfaddeff..baby_dragontooth_songbird_010_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_010_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/4a630b77.baby_dragontooth_songbird_011.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_011.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_011.jpg" src="media/1e6fa3d1..baby_dragontooth_songbird_011_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_011_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/fed37c33.baby_dragontooth_songbird_012.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_012.jpg"><img style="width: 420px; height: 560px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_012.jpg" src="media/b70f6f89..baby_dragontooth_songbird_012_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_012_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/e3ec5d71.baby_dragontooth_songbird_013.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_013.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_013.jpg" src="media/aaab88ba..baby_dragontooth_songbird_013_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_013_m.jpg" /></a></p></figure><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/886799ef.baby_dragontooth_songbird_014.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/baby_dragontooth_songbird_014.jpg"><img style="width: 560px; height: 420px; display: block; margin: 0px auto;" class="media" alt="baby_dragontooth_songbird_014.jpg" src="media/56fdbefc..baby_dragontooth_songbird_014_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2014_12_05_baby_dragontooth_songbird/.baby_dragontooth_songbird_014_m.jpg" /></a></p></figure><blockquote><p>Note: Les photos ne dates pas du premier jours.</p></blockquote><p>Premier constat: Ilaybôôôôh! :3 #kawaiiface</p><p>Sérieusement, ça été le coup de foudre! J'adore le reflet bleu pétrole ainsi que la forme général de l'objet. Il dispose d'un coté légèrement aplati bien classe.</p><p>Les trous sont très bien placé, pas de crampes possibles. J'aurais apprécié un très léger creux aux niveaux des doigts pour bien les sentir quand on joue.</p><h3>Sensation de fragilité</h3><p>Les ocarinas ont la réputation d’être aussi solides qu'un cours de bourse (je ne parle plus du taureau). Comme il est assez difficile de "tester" la solidité d'un objet sans avoir à le casser je vais plutôt parler de <em>sensation de fragilité</em>. Force est de constater que, sûrement due à sa petitesse, ce modèle semble assez robuste et devrait résister à la plupart des chocs (un peu comme un mug).</p><h3>Le son</h3><p>Avant de commencer:</p><ol><li>Je ne suis pas musicien.</li><li>Je n'ai aucun autre ocarina pour comparer.</li><li>Je suis un <s>autodidacte</s> boulet pour ce qui est des instruments à vent (mes cours de flûte y sont sûrement pour beaucoup...).</li></ol><p>Bref, avant de prendre cette review pour argent comptant sachez que vous marchez sur un terrain miné par le noobisme et le haut niveau d’incompétence qui le caractérise. Si vous êtes de ceux là, vous compatirez sûrement. Les autres, vous noterez le ton humoriste bancale visant à ne point faire perdre son temps au lecteur quand bien même il ne trouverait moindre valeur au sujet présent dans cette colonne.</p><p>D'un point de vue purement acoustique j'ai été agréablement surpris. Le son est super jolie :3 #kawaiifaceagain. La différence de souffle nécessaire entre le Do grave (tous les trous bouchés) et le Mi aigu n'est pas énorme et viens naturellement. Un soprano est par définition aigu et celui ci ne déloge pas à la règle. Il est tout à fait possible d'y jouer pendant plusieurs heures mais n’hésitez pas à utiliser des boules Quies si vous jouez longtemps une partition aigu.</p><p>Il n'y a pas des masses de vidéos sur Youtube l'utilisant mais j'ai réussi à en trouver <a hreflang="en" href="https://www.youtube.com/watch?v=EIFULXnc6R8">quelques</a> <a hreflang="en" href="https://www.youtube.com/watch?v=LEZ7CSpJkts">unes</a>.</p><p>J'ai l'impression que l'ocarina produit un son différent (plus strident) lors des premières secondes d'utilisation si ce dernier a été stocké dans un endroit froid. C'est peut être mes oreilles qui déconnent (ou que le mot <em>froid</em> est à prendre au sens montréalais mais ça s'est produit plus d'une fois. Dans ces cas la je bouche le trou principal avec mon pouce, ouvre tous les autres et souffle fort quelques secondes pour "vider" l'air froid et chauffer l'ocarina (ne retirez pas votre pouce à ce moment là ou vos tympan vous lâcheront pour de bon). Si quelqu'un pouvait me confirmer que la chaleur sert a quelque chose dans le son généré qu'il n’hésite pas. :)</p><h3>Tessiture</h3><blockquote><p>Pour les boulets qui ont ratés mon lien plus tôt <a hreflang="fr" href="https://fr.wikipedia.org/wiki/Tessiture">le revoici</a>.</p></blockquote><p>Le Baby DragonTooth est donc un Soprano et produit un son très clair sans nécessairement être extrêmement fort. J'avais très peur de ne pas pouvoir jouer en intérieur mais cela ne pose finalement aucun problème. Je n'ai malheureusement pas d'appareil pour mesurer les décibels et vous donner une idée.</p><p>La page du produit stipule qu'il dispose d'une étendue de Sol4 à Si5 (G5-B6) soit de la touche 59 à 75 d'un piano classique (783,991Hz à 1975,53Hz d'<a hreflang="fr" href="https://fr.wikipedia.org/wiki/Fr%C3%A9quences_des_touches_du_piano">après Wikipedia</a>). En pratique, la première note sonne plutôt comme un Fa# (demi ton avant le Sol). Quand on souffle un peu plus fort on obtient en effet un Sol. C'est suivant la force du souffle (les premières notes y étant beaucoup plus sensible que les dernières).</p><p>Gardez bien à l'esprit que la première note n'est donc pas un Do (comme le petit papier livré avec vous le fait croire). Quand vous jouez seul ce n'est pas très important, vous transposez naturellement. Mais si vous voulez profiter de cet ocarina pour apprendre les bases du solfège il faut le savoir. En effet, si vous voulez vous caler sur une mélodie existante (groupe ou vidéo) commençant par un Do, vous aurez l'impression de jouer cinq tons au dessus.</p><p>Pas de quoi paniquer cela dit, mais si vous avez un esprit ultra cartésien vous serez sûrement tenté d'aller, comme un michu, acheter un accordeur... Juste pour tester... (J'ai acheté un accordeur ok?... Juste pour tester...).</p><h3>Accordage</h3><blockquote><p>Je me demandais: Quelle est le mot qui défini qu'un instrument à vents est accordé ou non? Le mot anglais est <em>tuning</em> mais je n’ai pas trouve l’équivalent français et j'ai comme l'impression que parler d'accordage dans le cas d'un instrument dénudé de toute forme de corde est un non sens. Si vous avez la réponse, un grand merci d'avance pour me laisser un commentaire. :)</p></blockquote><p>Voila.</p><p>Donc, maintenant que les blaireaux du solfège ont sautés sur la rubrique commentaires en vue d'aller étaler leur science ça laisse du temps aux membres de la catégorie suivante que sont les blaireaux ignares de parler de l'accordage. <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>Vous l'aurez compris, un ocarina ne s'accorde qu'une fois: A la fabrication. Si vous le l'avez pas compris, sachez qu'un ocarina est fait en argile cuit (et si vous ne voyez pas le rapport, vous pouvez vous jeter d'un pont). Une tentative de sauvetage est peut être possible (limer certains trous) mais il vaut mieux demander de l'aide sur <a hreflang="en" href="http://theocarinanetwork.com/">The Ocarina Network</a> (TON pour les intimes), le seul forum fureté par des spécialistes...</p><p>Il est important de constater que la force du souffle joue sur le timbre de la note. Ainsi, j'ai remarqué que, tous les trous bouchés et en fonction du souffle, on peut faire varier de presque une note. Jouer en face d'un accordeur et vous le verrez sûrement jouer au yoyo sur les notes basses. Sur certaines partitions, ça peut vous <s>sauver</s> (on parlerais plus de cache misère).</p><p>Je sais que certains artisans utilisent des <a hreflang="en" href="http://www.sixthstreetocarina.com/blogs/frequently-asked-questions/1243212-how-are-sixth-street-ocarinas-tuned">souffleurs electroniques</a> en vue d'accorder leurs ocarinas. C'est sûrement la meilleur façons de faire. Je ne sais pas si Songbird utilise ça mais si quelqu'un a l'info vous pouvez allez rejoindre les blaireaux du solfège plus bas qui ne vont pas tarder à revenir.</p><h3>Truc aux possesseurs</h3><p>Chris Gale a pris l'habitude de nous gratifier d'une ou plusieurs astuces suivant le modèle d'ocarina qu'elle test, chose que je trouve tout à fait appréciable et je vais donc faire de même ici (même si je ne prétend pas avoir son niveau d'expertise):</p><ul><li>N'englobez pas le bec de l'ocarina avec vos lèvres, pressez simplement (et doucement) le bout de vos lèvres dessus. D'une, ça évite (un peu) de dégueulasser votre ocarina avec votre salive (il vous en remercie) et de deux, ça vous permet de vous servir subtilement de votre bouche (mâchoire/langue) pour contrôler le flux d'air que vous lui envoyez (un peu comme quand vous sifflez). Vous ressentirez aussi beaucoup plus ce flux d'air si il touche vos lèvres là ou, en englobant le bec, vous ne sentirez rien. Notez aussi que plus vous gober le bec de l'ocarina, plus vous aurez du mal à fabriquer le fameux "tseuh!" entre chaque note. Sur un morceau lent, on peut s'appuyer sur le contrôle de sa respiration pour couper une note mais sur morceau rapide l’échec est radicale. La pose des lèvres est importante ne soyez pas timide, tentez des trucs différents. Ça permet de <em>sentir</em> votre instrument. Essayez de souffler à un rythme constant en déplaçant votre ocarina, vous verrez que le son qui sort varie de même.</li><li>Les notes aiguës menacent parfois de "souffler" au lieu de sonner. D'une manière générale, augmentez légèrement le flux d'air sur les notes aiguës. Plus subtilement, ramener (très) légèrement l'ocarina proche de votre poitrine ou tournez le (l'ocarina, pas vous!) très légèrement sur le cote (ramenez la pointe vers vous). En faisant cela, vous ne devriez pas avoir à faire varier votre souffle pour sortir les notes aiguës (ce qui est appréciable sur des morceaux rapides).</li><li>Si vous êtes amené à jouer des partitions aiguës longtemps en intérieur, mettez des boules Quies afin d’éviter de finir sourd rapidement. Pour peu que la pièce dans laquelle vous jouez résonne un peu, les sons aiguës mettront beaucoup de temps à se <em>dégrader</em> et ce n'est vraiment pas agréable.</li><li>Commencez toujours par jouer un nouveau morceau en vitesse réduite. On est souvent tenté de suivre la mélodie originale mais, tel un Schumacher junior qui veut sentir l'ivresse de l'asphalte, il y a plus de chances que vous sentiez le sable des sacs de protections du premier virage (et ça c'est si vous avez de la chance...). Je vous assure que vous apprenez plus vite en jouant lentement (paradoxal hein? <img src="media/af8fdcdb.zinzin.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/zinzin.gif" alt=":zinzin:" class="smiley" /> ) un doigté parfait plutôt qu'en ratant toutes les notes. Comme c'est un ocarina six trous, certains doigtés s’enchaînent d'une manière peu naturel (c'est d’ailleurs une remarque que j'entends souvent contre les ocarinas six trous).</li><li>Quand vous commencez à connaître le doigté d'une mélodie (pas avant sinon ça ne marche pas des masses), essayez d'avoir une approche plus instinctive. Chacun a sa méthode. Fermez les yeux et bougez doucement votre corps au fil de votre souffle. Ça ne doit pas être un effort vraiment conscient mais juste un moyen de se laisser porter par la musique que vous jouez. Comme si vous vous berciez dans votre propre musique. Vous serez surpris de voir que parfois vous jouerez un morceau entier sans la moindre fausse note et sans que vous ayez pour autant réfléchi à ou vous placiez vos doigts. C'est la gratification suprême du débutant, celui de <em>jouer</em> un instrument.</li><li>Jouez ce qui vous fait plaisir! Vous n’êtes plus un petit enfant incrédule, vous avez bouffé de la musique comme n'importe quel ado frustré. Bien que piteux musicien, votre oreille est affûté. Vous savez reconnaître une fausse note. L'adulte de la droiture droite qui est en vous saura vous le faire remarquer, vous rappeler que vous êtes une bouse fini, que vous perdez votre temps et n'irez nul part. Il rira de vous comme ce pauvre gars qui vous prenait toujours votre dessert au collège. Mais rassurez vous, c'est tout a fait normal: Le monde qui nous entoure nous flatte constamment. Nous ne supportons pas la difficulté car elle nous rappel qu'on est sacrément con. Nous estimons que nos divertissements doivent être simples (ce qui ne nous élève pas). Réapprendre à apprendre, c'est accepter de se mentir et faire disparaître son incompétence derrière un regards d'enfant: Celui qui jubile à chaque mètre parcouru et franchit des montagnes sans vraiment s'en rendre compte. Quand les premiers morceaux sortiront, vous prendrez conscience que cette incompétence sciemment nié disparaît progressivement au profit d'un plaisir bien réel.</li></ul><h3>Prix</h3><p>Moi ça été $29.95 + $12.00 (FDP vers Canada) = $41.95</p><h3>Conclusion</h3><p>Petit coucou aux gros flemmards qui sautent ici sans lire la moindre ligne des sections précédentes, tu te reconnaîtra (On le fait tous!&nbsp; <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>Et bien très satisfait de mon achat. Je l'utilise souvent. J’essaie d'en faire quelques minutes par jour et ça vient doucement.</p><p>Ne vous laissez pas rebuter par le discours New Age propre à Songbird (si tu est à l’écoute des sons de ton <em>coaaarh</em> ton <em>aaaame</em> va s’élever au huitième ciel grâce aux vibrations acoustiques naturelles utilisées depuis des millénaires par les civilisations <em>ancestraaaaales</em> pour soigner les maladies rares et raffermir l'esprit... <a hreflang="fr" href="https://www.youtube.com/watch?v=t7xG7uVOfVs&amp;t=10s">Ouaih ouaih...</a>).</p><p>J'invite les artisans français (et européen) à se faire connaître ainsi qu'a <a hreflang="fr" href="http://www.partition-ocarina.fr/">partition ocarina</a> (site horrible mais communauté adorable) à les mettre en avant car comme tout secteur de niche, il ne se développe que par le bouche à oreille. <img src="media/98711e7e.france.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/france.gif" alt=":franceHappy:" class="smiley" /></p><p>A bientôt!</p><p>Dorian</p><p style="text-align: center;"><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


feed_id: urn:md5:6a5737b3331337776254def765ae0698
title: Compiler alembic 1.5.8 sous Linux
uri: Compiler-alembic-1-5-8-sous-Linux
url: http://www.fevrierdorian.com/blog/post/2015/09/07/Compiler-alembic-1.5.8-sous-Linux
content:
<p style="margin-bottom: 0in; line-height: 100%"><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="generator" content="LibreOffice 4.2.8.2 (Linux)"><style type="text/css"><!--
		@page { margin: 0.79in }
		p { margin-bottom: 0.1in; line-height: 120% }
		a:link { so-language: zxx }
	--></style><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="generator" content="LibreOffice 4.2.8.2 (Linux)"><style type="text/css"><!--
		@page { margin: 0.79in }
		p { margin-bottom: 0.1in; line-height: 120% }
		a:link { so-language: zxx }
	--></style></p><figure style="float: left; margin: 0 1em 1em 0;"><img style="width: 150px; height: 150px;" class="media" alt="abc_octopus_001_tn.png" src="media/cafa632d.abc_octopus_001_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/abc_octopus_001_tn.png" /></figure><p>Si vous avez déjà essayé de compiler <a href="https://github.com/alembic/alembic">alembic</a>, vous avez sûrement été confronté à pas mal de soucis. Compiler alembic n'est en effet pas simple et les méthodes pour y arriver sont nombreuses suivant ce que vous souhaitez faire.</p><p>Dans ce billet, je vous propose d'expliquer ligne à ligne un script bash afin de voir les différentes étapes. Notez que c'est plus un partage d’expérience qu'un vrai tuto. Il y a de fortes chances que ce script ne fonctionne pas sans modifications de votre part.</p><p>Je préfère prévenir: Mieux vaut être habitué à tout ce qui touche à la compilation. <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>Mon système</h3><p>Avant de commencer, et histoire que vous sachez sur quoi s’appuie ce tuto, sachez que je tourne sur un Linux Mint 17.1 Rebecca (Ubuntu 14.04):</p><pre><code class="language-bash">$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4</code></pre><p>Ça, c'est fait! <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>Prérequis</h3><p>On va commencer par ce qu'on ne va <u>pas</u> compiler mais qui est nécessaire au bon fonctionnement des opérations, à savoir: Les packages.</p><p>D'une manière générale, je vous conseille de lire les <em>READMEs</em> fournis avec chaque archive de fichiers sources car ils contiennent de précieuses indications.</p><p>Petite liste non exhaustives des packages nécessaires:</p><ul><li><em>zlib1g-dev</em>: 1.2.8 chez moi.</li><li><em>libhdf5-dev</em>: 1.8.11 chez moi.</li><li><em>libboost-thread1.54-dev</em>: Alembic spécifie qu'il fonctionne de boost 1.44 à 1.48 et que les versions suivantes posent des soucis avec Python. Comme on ne va pas compiler PyAlembic ici on est tranquille.</li><li><em>graphviz</em>: Pour la documentation Alembic. Pas obligatoire mais vous n'aurez pas les graphs d'héritage dans la documentation généré ce qui est toujours dommage. 2.36.0 chez moi.</li><li><em>cmake</em>:&nbsp; Le build system utilisé par Alembic. 2.8.0 ou supérieur, 2.8.12 chez moi.</li></ul><p>Installez&nbsp;<em>cmake-gui</em> tant qu'à faire, vous risquez d'en avoir besoin.</p><p>Je ne mentionne bien évidemment pas <em>build-essential</em> <img src="media/702ddbb3.tux001.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/tux001.gif" alt=":tux001:" class="smiley" /> .</p><h3>Ce qu'on va compiler</h3><p>Alembic palsambleu! <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>Plus précisément, ce script va compiler:</p><ul><li>IlmBase 2.2.0</li><li>OpenEXR 2.2.0</li><li>Alembic 1.5.8</li></ul><blockquote><p>Pour votre information: Le <em>README</em> de Alembic spécifie qu'il ne nécessite qu'IlmBase 1.0.3 et OpenEXR 1.7.1. Vous pouvez toujours modifier mon script pour utiliser ces versions. J'ai teste et ça fonctionne également.</p></blockquote><h3>Le script</h3><p>Le voici brut de décoffrage&nbsp;:</p><pre><code class="language-bash">export MAINDIR=/home/user/code/alembic_test

mkdir my_env

wget http://download.savannah.nongnu.org/releases/openexr/ilmbase-2.2.0.tar.gz
tar -xzvf ilmbase-2.2.0.tar.gz
rm ilmbase-2.2.0.tar.gz
cd ilmbase-2.2.0
./configure --prefix=$MAINDIR/my_env
make -j8
make install

cd ../

export LD_LIBRARY_PATH=$MAINDIR/my_env/lib

wget http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz
tar -xzvf openexr-2.2.0.tar.gz
rm openexr-2.2.0.tar.gz
cd openexr-2.2.0
./configure --prefix=$MAINDIR/my_env --with-ilmbase-prefix=$MAINDIR/my_env
make -j8
make install

cd ../

wget https://github.com/alembic/alembic/archive/1.5.8.tar.gz
tar -xzvf 1.5.8.tar.gz
rm 1.5.8.tar.gz
cd alembic-1.5.8
cmake -DUSE_PYALEMBIC=OFF \
-DILMBASE_ROOT=../my_env \
-DCMAKE_SYSTEM_PREFIX_PATH=../my_env \
-DCMAKE_INSTALL_PREFIX=../my_env/usr/local ./
make -j8
make test
make install
doxygen Doxyfile</code></pre><h3>Explication ligne&nbsp;à ligne</h3><pre><code class="language-bash">export MAINDIR=/home/user/code/alembic_test</code></pre><p>Cette première ligne est importante. On créé la variable <em>MAINDIR</em>&nbsp;à laquelle on assigne le chemin vers notre dossier principal dans lequel on va faire nos affaires.</p><pre><code class="language-bash">mkdir my_env</code></pre><p>Ici on créé un dossier <em>my_env</em>. C'est une méthode que j'utilise souvent: Afin d'éviter d'avoir à installer mes librairies fraîchement compilées directement sur mon système (ce qui peut potentiellement tout casser si la librairie est importante et mal compilée), je défini un dossier comme étant mon système (on parle souvent de <em>prefix</em>). Ça nécessite souvent de bricoler deux trois choses mais ça finit toujours par marcher :baffed:.</p><h3>IlmBase</h3><pre><code class="language-bash">wget http://download.savannah.nongnu.org/releases/openexr/ilmbase-2.2.0.tar.gz</code></pre><p>On récupère l'archive des fichiers source de IlmBase (lien trouvé <a hreflang="en" href="http://www.openexr.com/downloads.html">ici</a>). On se retrouve donc avec un jolie <em>ilmbase-2.2.0.tar.gz</em> dans sont dossier.</p><pre><code class="language-bash">tar -xzvf ilmbase-2.2.0.tar.gz</code></pre><p>Hahaha!&nbsp;<a hreflang="en" href="https://xkcd.com/1168/">La fameuse</a> commande <em>tar</em>, impossible&nbsp;à retenir. <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /></p><p>En gros, on décompresse le contenu du fichier.</p><pre><code class="language-bash">rm ilmbase-2.2.0.tar.gz</code></pre><p>Une fois décompressé, je supprime l'archive parce que j'aime bien quand c'est propre. <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p><pre><code class="language-bash">cd ilmbase-2.2.0</code></pre><p>On rentre maintenant dans le dossier qu'on vient d'extraire.</p><pre><code class="language-bash">./configure --prefix=$MAINDIR/my_env</code></pre><p>Première apparition du <em>prefix</em> dont je vous ai parlé tout&nbsp;à l'heure. En gros, on exécute le script de configuration. Le script de configuration va s'assurer que tout ce qui est nécessaire&nbsp;à la compilation est présent sur le système. En lui spécifiant un <em>prefix</em>, on lui indique dans quel dossier on souhaite placer les fichiers compilés. Le <em>$MAINDIR</em> vient appeler la variable créer tout en début de script.</p><pre><code class="language-bash">make -j8</code></pre><p>D'ordinaire, la commande <em>make</em> s'occupe de compiler les fichiers sources. L'argument <em>-j8</em> indique le nombre de job&nbsp;à utiliser lors de la compilation pour gagner du temps. Si vous avez <em>ein grô</em> PC, <em>ein grô</em> processeur et de la grosse mémoire, vous pouvez mettre <em>ein grô</em> chiffre (et <em>ein</em>-versement <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /> )</p><pre><code class="language-bash">make install</code></pre><p>Si la compilation c'est bien passée, vous pouvez faire un <em>make install</em> pour envoyer les fichiers compilés se dispatcher dans le dossier <em>my_env</em>.</p><pre><code class="language-bash">cd ../</code></pre><p>On sort du dossier. S'en est fini d'IlmBase!</p><h3>OpenEXR</h3><pre><code class="language-bash">export LD_LIBRARY_PATH=$MAINDIR/my_env/lib</code></pre><p>Alors alors, une petite explication s'impose: Durant la phase de configuration de la compilation d'OpenEXR, ce dernier génère un petit code utilisant la librairie IlmBase afin de vérifier certaines choses. Comme vous le savez, nous avons sauvé les fichiers d'IlmBase dans un environnement spécial, en dehors du système principale (dans <em>my_env</em>). Pour que la phase de configuration d'OpenEXR se passe bien, il faut ajouter le dossier contenant les librairies à la variable d'environnement utilisée pour trouver les librairies des binaires exécutés par le système.</p><p>C'est ce que fait cette ligne. (Plus d'infos sur <em>LD_LIBRARY_PATH</em> <a hreflang="fr" href="http://www.linuxcertif.com/doc/keyword/LD_LIBRARY_PATH/">ici</a>)</p><pre><code class="language-bash">wget http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz
tar -xzvf openexr-2.2.0.tar.gz
rm openexr-2.2.0.tar.gz
cd openexr-2.2.0</code></pre><p>Je ne vais pas m’étaler sur cette partie, c'est la même que précédemment.</p><pre><code class="language-bash">./configure --prefix=$MAINDIR/my_env --with-ilmbase-prefix=$MAINDIR/my_env</code></pre><p>Le script de configuration d'OpenEXR dispose d'un argument supplémentaire (<em>--with-ilmbase-prefix</em>) permettant de lui donner un chemin vers un emplacement non standard où est placé la librairie IlmBase&nbsp;à utiliser. Je ne rentre pas dans les détails. Si vous voulez comprendre, ouvrez le fichier <em>configure</em> et cherchez cette variable :dentcasse:.</p><pre><code class="language-bash">make -j8
make install
cd ../</code></pre><p>On compile, on installe dans <em>my_env</em> et on sort.</p><h3>Alembic</h3><p>Et voici la dernière ligne droite!</p><pre><code class="language-bash">wget https://github.com/alembic/alembic/archive/1.5.8.tar.gz</code></pre><p>Notez que j'ai récupéré le chemin de l'archive sur <a hreflang="en" href="https://github.com/alembic/alembic/releases">la page des releases</a>.</p><pre><code class="language-bash">tar -xzvf 1.5.8.tar.gz
rm 1.5.8.tar.gz
cd alembic-1.5.8</code></pre><p>Je passe. <img src="media/a1e117d8.bed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bed.gif" alt=":reveBinaire:" class="smiley" /></p><pre><code class="language-bash">cmake -DUSE_PYALEMBIC=OFF \
-DILMBASE_ROOT=../my_env \
-DCMAKE_SYSTEM_PREFIX_PATH=../my_env \
-DCMAKE_INSTALL_PREFIX=../my_env/usr/local ./</code></pre><p>Et voila <strong>la</strong> ligne! On va la décortiquer:</p><ul><li><em>cmake</em>: La commande du générateur de <em>makefile</em> de Alembic. Vous remarquez qu'Alembic n'utilise pas l'habituel <em>configure</em> qui est une méthode assez ancienne et laborieuse (il suffit d'ouvrir un script de configuration pour s'en convaincre). <a hreflang="en" href="http://cmake.org/">CMake</a> permet une gestion plus fine des options de compilation pour générer des <em>makefiles</em> aux petits oignions.</li><li><em>USE_PYALEMBIC=OFF</em>: On déclare (d'où le <em>-D</em> au début de chaque argument) la variable <em>USE_PYALEMBIC</em> à <em>OFF</em>. En faisant ça, on va simplement dire à CMake de ne pas générer la partie responsable de la compilation de PyAlembic (pour les raisons évoquées plus haut).</li><li><em>ILMBASE_ROOT=../my_env</em>: On défini que toute les librairies sont&nbsp;à aller chercher dans <em>my_env</em>.</li><li><em>CMAKE_SYSTEM_PREFIX_PATH=../my_env</em>: Le chemin&nbsp;à privilégier pour aller cherche les librairies nécessaires à la compilation (cf: <a hreflang="en" href="http://www.cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_PREFIX_PATH.html">doc</a>).</li><li><em>CMAKE_INSTALL_PREFIX=../my_env/usr/local</em>: L'équivalent du <em>prefix</em> d'un script <em>configure</em>. Notez que j'ai ajoute <em>/usr/local</em> car c'est l'endroit ou Alembic viendrait stocker ces librairies si on ne lui précisait pas.</li><li><em>./</em>: On spécifie simplement qu'il faut exécuter <em>cmake</em> dans le dossier courant.</li></ul><p>Si vous souhaitez savoir ce qui ce passe sous le capot, exécutez <em>cmake-gui ./</em> après avoir exécuté la ligne précédente.</p><pre><code class="language-bash">make -j8</code></pre><p>C'est pas si long 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" /></p><pre><code class="language-bash">make test</code></pre><p>Comme la quantité de message affiché est énorme, vous ne saurez pas forcement clairement si la compilation c'est bien passé. Le plus simple pour tester est d'exécuter la suite de test fournie.</p><p>Si tout fonctionne:</p><pre><code class="language-bash">make install</code></pre><p>Allez dans <em>my_env/usr/local/alembic-1.5.8/lib/static/</em>:</p><figure style="margin: 0 auto; display: block;"><img style="width: 248px; height: 310px; display: block; margin: 0px auto;" class="media" alt="alembic_static_001.png" src="media/8c6f8021.alembic_static_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/alembic_static_001.png" /></figure><p style="text-align: center;">Vous voila l'heureux propriétaire d'une librairie Alembic statique!</p><p>N'oubliez pas de générer la documentation:</p><pre><code class="language-bash">doxygen Doxyfile </code></pre><p>Pour l'ouvrir (et vous en aurez besoin!): <em>alembic-1.5.8/doc/html/index.html</em>.</p><h3>Le viewer</h3><p>Allez dans <em>my_env/usr/local/alembic-1.5.8/bin:</em></p><figure style="margin: 0 auto; display: block;"><img style="width: 159px; height: 153px; display: block; margin: 0px auto;" class="media" alt="alembic_bin_dir_001.png" src="media/55a1c12d.alembic_bin_dir_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/alembic_bin_dir_001.png" /></figure><p style="text-align: center;">Des petites choses que je vous laisse essayer par vous même.</p><p>Pour le fun, faites:</p><pre><code class="language-bash">./SimpleAbcViewer /path/to/any.abc</code></pre><p>Et miracle!</p><figure style="margin: 0 auto; display: block;"><a class="media-link" href="media/e44b2d2b.abc_octopus_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/abc_octopus_001.png"><img style="width: 560px; height: 435px; display: block; margin: 0px auto;" class="media" alt="abc_octopus_001.png" src="media/45a44205..abc_octopus_001_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/.abc_octopus_001_m.png" /></a></figure><p>Gardez la touche <em>shift</em> enfoncé et naviguez comme dans Maya. (Des raccourcis sont disponible pour, entre autre, jouer l'animation)</p><p>Notez qu'il faut avoir précédemment setté la variable <em>LD_LIBRARY_PATH</em> pour pointer vers les librairies nécessaires (un message d'erreur dans le terminal vous le&nbsp;rappellera <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><h3>Linker les librairies Alembics dans vos programme</h3><p>Je vous préviens tout de suite cette partie sera <s>encore</s> plus chaotique que la précédente. <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>Pour faire simple: On va écrire un petit programme mais on va surtout tenter de compiler ce programme avec les librairies.</p><p>Personnellement, j'utilise <a hreflang="en" href="https://netbeans.org/features/index.html">NetBeans IDE</a> mais vous devriez pouvoir configurer ça sur n'importe quel IDE et/ou chaîne de compilation. Créez vous un projet vierge (<em>abc_test</em> dans mon cas).</p><h4>Les headers</h4><p>Voici la liste des dossiers des headers:</p><ul><li><em>../my_env/usr/local/alembic-1.5.8/include</em>: Le dossier des headers d'Alembic</li><li><em>../my_env/include/OpenEXR</em>: Le dossier des headers de IlmBase</li><li><em>/usr/include</em>: Le dossier des headers de votre système (pour HDF5 entre autre)</li></ul><figure style="margin: 0 auto; display: block;"><a class="media-link" href="media/0eb0b53e.abc_compile_config_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/abc_compile_config_001.png"><img style="width: 560px; height: 270px; display: block; margin: 0px auto;" class="media" alt="abc_compile_config_001.png" src="media/308b1854..abc_compile_config_001_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/.abc_compile_config_001_m.png" /></a></figure><h4>Le standard</h4><p>Choisissez le standard C++11:</p><figure style="margin: 0 auto; display: block;"><a class="media-link" href="media/bd43687d.abc_compile_config_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/abc_compile_config_002.png"><img style="width: 560px; height: 120px; display: block; margin: 0px auto;" class="media" alt="abc_compile_config_002.png" src="media/f014b391..abc_compile_config_002_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/.abc_compile_config_002_m.png" /></a></figure><p>On va écrire du C++ de hipster!!! <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /> :</p><h4>Les librairies</h4><p>Et la liste des librairies statiques (l'ordre est important):</p><ul><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbcGeom.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbcFactory.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbc.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbcCoreHDF5.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbcCoreOgawa.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicAbcCoreAbstract.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicOgawa.a</li><li>../my_env/usr/local/alembic-1.5.8/lib/static/libAlembicUtil.a</li><li>../my_env/lib/libHalf.a</li><li>../my_env/lib/libIex.a</li><li>../my_env/lib/libIexMath.a (Pas sure que celle librairie existe avec IlmBase 1.0.3...)</li><li>../my_env/lib/libIlmImf.a</li><li>../my_env/lib/libIlmThread.a</li><li>../my_env/lib/libImath.a</li><li>boost_thread</li><li>hdf5</li><li>hdf5_hl</li></ul><p>Les trois dernières ne sont pas des liens directs car elles font partie du système. Ce qui nous donne:</p><figure style="margin: 0 auto; display: block;"><p><a class="media-link" href="media/2fd3e1be.abc_compile_config_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/abc_compile_config_003.png"><img style="width: 560px; height: 344px; display: block; margin: 0px auto;" class="media" alt="abc_compile_config_003.png" src="media/021162c4..abc_compile_config_003_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2015_09_06_compiler_alembic_linux/.abc_compile_config_003_m.png" /></a></p></figure><h4>Le programme</h4><p>Allez! Faites moi un gros copier/coller <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /> :</p><pre><code class="language-cpp">#include &lt;Alembic/Abc/All.h&gt;
#include &lt;Alembic/AbcCoreFactory/All.h&gt;

int main(int argc, char** argv) {

    // Create needed variables
    Alembic::AbcCoreFactory::IFactory factory;
    Alembic::AbcCoreFactory::IFactory::CoreType coreType;

    // open the abc file
    auto archive = factory.getArchive("/path/to/alembic_octopus.abc", coreType);

    if (archive.valid())
    {
        std::cout &lt;&lt; "Archive name: " &lt;&lt; archive.getName() &lt;&lt; std::endl;
        std::cout &lt;&lt; "Number TimeSampling: " &lt;&lt; archive.getNumTimeSamplings() &lt;&lt; std::endl;
        std::cout &lt;&lt; "Archive version: " &lt;&lt; archive.getArchiveVersion() &lt;&lt; std::endl;

        // retrieve the top IObject of the hierarchy
        auto top = archive.getTop();
        std::cout &lt;&lt; "top valid?: " &lt;&lt; top.valid() &lt;&lt; std::endl;
        std::cout &lt;&lt; "top name: " &lt;&lt; top.getName() &lt;&lt; std::endl;
        std::cout &lt;&lt; "top full name: " &lt;&lt; top.getFullName() &lt;&lt; std::endl;
        std::cout &lt;&lt; "top num children: " &lt;&lt; top.getNumChildren() &lt;&lt; std::endl;

        auto parent = top.getParent();
        std::cout &lt;&lt; "parent of the top valid?: " &lt;&lt; parent.valid() &lt;&lt; std::endl; // of course not!

        auto header = top.getHeader();        
        std::cout &lt;&lt; "top header name: " &lt;&lt; header.getName() &lt;&lt; std::endl;
        std::cout &lt;&lt; "top header full name: " &lt;&lt; header.getFullName() &lt;&lt; std::endl;

        auto metadata = top.getMetaData();
        std::cout &lt;&lt; "metadata size: " &lt;&lt; metadata.size() &lt;&lt; std::endl;
        std::cout &lt;&lt; "metadata serialize: " &lt;&lt; metadata.serialize() &lt;&lt; std::endl;

        // iterate over abc metadatas
        for(auto &amp;it : metadata)
        {
            auto key   = it.first;
            auto value = it.second;
            std::cout &lt;&lt; key &lt;&lt; " = " &lt;&lt; value &lt;&lt; std::endl;
        }
    };
    return 0;
}

</code></pre><p>Et voici ce qu'affiche ce programme une fois exécuté:</p><pre><code>Archive name: /home/narann/code/cpp/abc_test/alembic_octopus.abc
Number TimeSampling: 2
Archive version: 10000
top valid?: 1
top name: ABC
top full name: /
top num children: 1
parent of the top valid?: 0
top header name: ABC
top header full name: /
metadata size: 4
metadata serialize: _ai_AlembicVersion=Alembic 1.0.0 (built Aug  5 2011 16:14:46);_ai_Application=Maya 2012-2.1.SPI x64 AbcExport v1.0;_ai_DateWritten=Tue Aug  9 13:14:24 2011;_ai_Description=Exported from: /mcp/Alembic_Octopus_Example/alembic_octopus.mb
_ai_AlembicVersion = Alembic 1.0.0 (built Aug  5 2011 16:14:46)
_ai_Application = Maya 2012-2.1.SPI x64 AbcExport v1.0
_ai_DateWritten = Tue Aug  9 13:14:24 2011
_ai_Description = Exported from: /mcp/Alembic_Octopus_Example/alembic_octopus.mb
</code></pre><p>Si vous êtes arrivé jusqu'ici: Félicitation! Vous pouvez maintenant commencer a jouer avec Alembic. Je vous invite à fouiller les codes d'exemples (à commencer par celui ci) et&nbsp;à lire la documentation que vous avez générée (Mais si! Rappelez vous, dans <em>../alembic-1.5.8/doc/html/</em>). <img src="media/9ca8344d.sign0012.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sign0012.gif" alt=":RTFM:" class="smiley" /></p><p>J'espère que ce billet vous aura aidé et donné envie de pousser tout ça plus loin.</p><p>Dorian</p><p style="text-align: center;"><img src="media/f4c892e9.marioCours.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/marioCours.gif" alt=":marioCours:" class="smiley" /></p>


feed_id: urn:md5:1303fbca1a4c9f870a402f67d205724a
title: "FBXASC032" dans mes noms de noeuds Maya quand j'importe un FBX
uri: FBXASC032-dans-mes-noms-de-noeuds-Maya-quand-j-importe-un-FBX
url:
http://www.fevrierdorian.com/blog/post/2016/10/07/FBXASC032-dans-mes-noms-de-noeuds-Maya-quand-j-importe-un-FBX

content:
    <figure style="float: left; margin: 0 1em 1em 0;"><img alt="mobu.png" class="media" src="media/6ede37e0.mobu.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/mobu.png" /></figure>

<p>Si vous importez un fichier FBX provenant de Motion Builder 2016 dans Maya 2016, il se peut que vous obteniez des noms bizarres. C'est simplement un espace les amis! <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>Si votre objet se nomme "tree 1" dans Motion Builder, et que vous importez le FBX dans Maya, Maya nommera le nœud "treeFBXASC0321". Pour une raison étrange, Maya remplace l'espace par FBXASC032, l'espace étant le 32eme caractère ascii. <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>Motion Builder autorise l’écriture des espaces dans les noms des objets. En fait, il le fait même automatiquement quand deux objets porte le même nom <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /> . Je suppose que Maya devrait remplacer ça par un underscore ("tree_1"), ou au moins remonter un warning dans le log.</p>

<p>Soit vous résolvez le problème avant l'export du FBX, soit vous le faites dans Maya via une simple recherche et remplacement.</p>

<p>En espérant que ça en aide d'autres. <img src="media/f3a39cb6.hehe.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hehe.gif" alt=":hehe:" class="smiley" /></p>


feed_id: urn:md5:0874aa56beac5c61f49be78c2c8a2796
title: Est-ce que glTexSubImage2D est asynchrone?
uri: Est-ce-que-glTexSubImage2D-est-asynchrone
url: http://www.fevrierdorian.com/blog/post/2016/11/15/Est-ce-que-glTexSubImage2D-est-asynchrone
content:
    <figure style="float: left; margin: 0 1em 1em 0;"><img alt="OpenGL_logo_tn150.png" class="media" src="media/9a0fcd51.OpenGL_logo_tn150.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/OpenGL_logo_tn150.png" /></figure>

<p>Je traduis une réponse claire <a href="https://www.reddit.com/r/opengl/comments/5cwna5/is_gltexsubimage2d_asynchronous/" hreflang="en" title="Is glTexSubImage2D asynchronous?">trouvée sur reddit</a>:</p>

<p>Si le paramètre <code>data</code> de la fonction n’est pas un <em><a href="https://www.opengl.org/wiki/Buffer_Object" hreflang="en" title="Buffer Object">buffer object</a></em>, alors <code><a href="https://www.opengl.org/sdk/docs/man/html/glTexSubImage2D.xhtml" hreflang="en" title="glTexSubImage2D">glTextSubImage2D</a></code> doit bloquer pendant que le pilote OpenGL copie les données sur la mémoire du GPU (à la manière d’un <code><a href="http://www.cplusplus.com/reference/cstring/memcpy/" hreflang="en" title="memcpy">memcpy</a></code>). C'est nécessaire car OpenGL n’a aucun moyen de vous forcer à conserver les données en mémoire en attendant que la fonction se termine.</p>

<p>Les <em>buffer objects</em> permettent un transfert asynchrone (à la discrétion du pilote), car le pilote peut les conserver jusqu’à ce que les données soient transférés.</p>


feed_id: urn:md5:0af08e8fcdd66bc0644bd3c6216db1aa
title: Pourquoi les instances Maya sont si lourdes?
uri: Pourquoi-les-instances-Maya-sont-si-lourdes
url: http://www.fevrierdorian.com/blog/post/2017/03/25/Pourquoi-les-instances-Maya-sont-si-lourdes
content:
<p><img alt="" class="media" src="media/5c9470ac.maya_2017_logo.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/maya_2017_logo.png" style="float: left; margin: 0 1em 1em 0;" />Comme vous le savez sûrement, Maya propose un moyen de faire des instances.</p>

<p>Comme vous vous en doutez peut-être, ce n’est pas si simple.</p>

<p>Et ce que vous ne savez peut-être pas c’est qu’en pratique (plus de 1000 instances) <a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum/suggestions/3910650-instances-are-slow-in-becuase-of-material-connecti" hreflang="en">ça ne fonctionne</a> <a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum/suggestions/4475236-speed-up-instance-handling-when-amount-around-10" hreflang="en">pas des masses</a>…</p>

<p>Essayons de comprendre pourquoi. <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>Grossièrement une instance c’est ça:</p>

<p><img alt="" class="media" src="media/f1733886.instance_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_001.png" style="margin: 0 auto; display: table;" /></p>

<ul>
	<li>Une géométrie (Qu’on nomme "GEO" ici) mise en mémoire.</li>
	<li>Un transform (ici "XFORM_01") qui pointe vers "GEO".</li>
	<li>Un second transform ("XFORM_02") qui pointe aussi vers "GEO".</li>
	<li>Un troisième… etc.</li>
</ul>

<p>Ainsi, on ne stock la géométrie qu’une seule fois en mémoire, tout le reste étant des position+rotation+scale (un transform) qui y font référence.</p>

<p>C’est très pratique dans le cas, par exemple, d’une forêt ou l’arbre est la géométrie et les milliers de points, des instances.</p>

<h3>La monté en charge</h3>

<p>Jusqu’ici c’est plutôt pas mal. Sauf que vous allez voir que la collision de deux choix d'architecture ont littéralement claqué la porte a toute possibilité de monté en charge du système.</p>

<p>Le premier est dû a la manière dont Maya fonctionne: Tout est connexion.</p>

<p>Le second est dû&nbsp;à un problème d’expérience utilisateur: Comme il est tout à fait légitime pour un utilisateur de vouloir assigner un material différent à chaque instance, quand Maya créé une instance, cette dernière dispose de son propre slot de material. Ce qui nous donne ceci (voir le bonhomme énervé):</p>

<p><a class="media-link" href="media/c7ce4975.instance_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_002.png"><img alt="" class="media" src="media/716d6fd6..instance_002_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/.instance_002_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>Comme vous pouvez le constater, la shape (en mauve car c'est une instance) possède autant de connexion au shading group qu'il y a d'instance:</p>

<pre>
<code class="language-cpp">shape.instObjGroup[0].initialShadingGroup.dagSetMembers[0]
shape.instObjGroup[1].initialShadingGroup.dagSetMembers[1]
…
shape.instObjGroup[999].initialShadingGroup.dagSetMembers[999]</code></pre>

<p>L'objectif étant, encore une fois, pour Maya, de garder la possibilité d'assigner un material différent à chaque instance.</p>

<p>Ce choix, bien que légitime, porte un gros préjudice aux performances. Vers 1000 instances, il faut plus d’une seconde, quand vous sélectionnez un objet, pour afficher l’<em>Attribut Editor</em>. La plupart des interfaces se mettent à ramer, le <em>delete all by history</em> pédale, le temps de sauvegarde est énorme et je ne parle même pas de certaines opérations en script qui deviennent très lente (<em>parent</em> par exemple).</p>

<p>Il aurait été intéressant de pouvoir forcer un material unique par shape d’instance. Évitant ainsi des milliers de connexions qui, bien souvent, pointent vers le même material.</p>

<h3>Des solutions?</h3>

<p>Disons que ça dépend de ce que vous faites dans Maya. Si vous voulez faire du rendu, je suppose que ça dépend du moteur mais naïvement je dirais que c’est mort et que vous allez souvent devoir bricoler pour utiliser le système d’instance du-dis moteur. Ce dernier se chargeant d’interpréter le bricolage qu’il vous impose (ah le bon vieux <em>locator</em> avec une connexion <em>message</em> vers un groupe <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>Si vous ne faites que de la manipulation de transform (des forets!), une solution consiste à briser toutes les connections de material de votre shape:</p>

<p><img alt="" class="media" src="media/da9e5951.instance_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_003.png" style="margin: 0 auto; display: table;" /></p>

<p>Vous vous retrouverez donc sans material (mesh transparent/vert):</p>

<p><a class="media-link" href="media/3c2e68b8.instance_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_004.png"><img alt="" class="media" src="media/f9402521..instance_004_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/.instance_004_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>Vous pouvez toujours passer en <em>use default material</em>:</p>

<p><img alt="" class="media" src="media/e64b59eb.instance_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_005.png" style="margin: 0 auto; display: table;" />Notez que lors de mes tests (Maya 2016), ceci ne marchait pas en <em>Viewport 2.0</em>. Il fallait repasser en <em>Legacy Default Viewport</em>. <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>Conclusion</h3>

<p>Les instances dans Maya restent assez complexe à mettre en place. Le vrai problème vient du fait qu’on ne peut pas travailler avec des milliers d’objets (ce qui est quand même un comble).</p>

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


feed_id: urn:md5:8b3610fc9eca64d91706d89c8a81839c
title: Lister les channels d'un fichier OpenVDB avec Guerilla
uri: Lister-les-channels-d-un-fichier-OpenVDB-avec-Guerilla
url:
http://www.fevrierdorian.com/blog/post/2017/05/13/Lister-les-channels-d-un-fichier-OpenVDB-avec-Guerilla

content:
<p><img alt="" class="media" src="media/be264a55.2017_05_13_openvdb_channel_guerilla_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_13_openvdb_channel_guerilla/2017_05_13_openvdb_channel_guerilla_tn.png" style="float: left; margin: 0 1em 1em 0;" />Si vous utilisez Guerilla et que vous devez rendre des fichiers OpenVDB, vous devez connaitre les noms des <em>channels</em> afin de les utiliser dans vos shaders de volumétrique.</p>

<p>Il y a plusieurs façons d’introspecter un fichier OpenVDB (plugin Maya, ligne de commande officielle, etc.) mais toute ne sont pas forcement disponible sur votre machine.</p>

<p>Je vous propose une petite méthode qui s’appuie sur les informations que Guerilla donne quand il rend. <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /> )</p>    <ul>
	<li>Ouvrez Guerilla</li>
	<li>Importez votre fichier .vdb en référence (<em>Create</em>/<em>Create Reference</em>)</li>
	<li>Sélectionnez le nœud <em>Preferences</em></li>
	<li>Dépliez <em>Rendering</em>/<em>Logs &amp; Diagnostics</em></li>
	<li>Mettez <em>Verbosity</em> à «&nbsp;Diagnostics&nbsp;»</li>
	<li>Activez <em>Diagnostics Shapes</em></li>
	<li>Ouvrez la console (<em>View</em>/<em>Show/Hide console</em> ou Alt+2)</li>
	<li>Videz le contenu du log via bouton droit de souris <em>Clear</em></li>
	<li>Faites un rendu (Ctrl+R)</li>
</ul>

<p><img alt="" class="media" src="media/dd49972e.2017_05_13_openvdb_channel_guerilla_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_13_openvdb_channel_guerilla/2017_05_13_openvdb_channel_guerilla_001.png" style="margin: 0 auto; display: table;" /></p>

<p>Vous devriez obtenir un retour de la forme suivante:</p>

<pre>
<code>Starting render: 1 jobs
05/12/2017 15:26:38  SHAP DIA: loaded shape 'C:\Users\narann\Downloads\fire.vdb\fire.vdb' 'fire.RenderGeometry'
05/12/2017 15:26:38  SHAP DIA: Voxel shape
05/12/2017 15:26:38  SHAP DIA: density - 1 float(s) - 4458790 voxels
05/12/2017 15:26:38  SHAP DIA: temperature - 1 float(s) - 4139727 voxels
Render RenderPass RenderPass: 1.08s
Total render: 1.08s</code></pre>

<p>On peut voir que ce .vdb (disponible <a href="http://www.openvdb.org/download/" hreflang="en">sur le site officiel</a>) contient deux <em>channels</em>: <em>density</em> et <em>temperature</em>.</p>

<p>Si vous relancez le rendu, vous remarquerez que ça ne réaffichera pas. C’est dû au fait que le cache Guerilla ne recharge pas ce qu’il a déjà en mémoire (pas bête la guêpe <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>Il faut donc faire un <em>Clear cache</em> avant de relancer le rendu.</p>

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

<p>Dorian</p>

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


feed_id: urn:md5:7a7da803d93bb0f6b397817ff1a597b3
title: Construire un clavier mécanique pour le fun
uri: Construire-un-clavier-mécanique-pour-le-fun
url: http://www.fevrierdorian.com/blog/post/2017/05/24/Construire-un-clavier-m%C3%A9canique-pour-le-fun
content:
<p><img alt="" class="media" src="media/0a61792a.clavier_atreus_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_tn.png" style="float: left; margin: 0 1em 1em 0;" />Cela faisait un moment que je voulais construire un truc. En fait, quand je ne code pas, j’ai toujours envi de faire des trucs. En fait, quand je fais des trucs j’ai toujours envi de faire d’autres trucs. Je ne voyais rien qui puisse me motiver à aller jusqu’au bout. Puis l’idée d’un projet qui mélangeait électronique et bois passa: Un clavier mécanique fait maison. «&nbsp;Haha&nbsp;» me dis-je, «&nbsp;Faut vraiment rien avoir à faire de sa vie pour se lancer dans un truc aussi con&nbsp;».</p>

<p>Je partais donc là dessus avec entrain. <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>L’inception</h3>

<p>Ce qui me donne envi de commencer un projet est souvent le fruit d’une maturation qui peut parfois commencer des années plus tôt.</p>

<p>Ici, suite à une augmentation du <a href="https://fr.wikipedia.org/wiki/Syndrome_du_canal_carpien" hreflang="fr">syndrome de canal carpien</a> j’ai commencé&nbsp;à m’intéresser&nbsp;à l’ergonomie autour des claviers. J’ai découvert (et enfin compris) que les <a href="https://www.qwant.com/?q=claviers%20chiclet&amp;t=images" hreflang="fr">claviers chiclet</a> (clavier plat d’Apple et d’ordinateurs portables) sont très mauvais pour le poignet, car ils stoppent le mouvement du doigt sur la touche très (trop) tôt et usent le muscle. Je suis rapidement tombé sur les claviers <a href="https://www.ergodox.io/" hreflang="en">Ergodox</a> puis <a href="http://imgur.com/account/favorites/sbipG" hreflang="en">mécaniques</a> <a href="https://deskthority.net/wiki/Main_Page" hreflang="en">en général</a>, les <a href="http://www.millenium.org/hardware/hardware/actualites/claviers-mecaniques-le-dossier-un-descriptif-complet-sur-ce-type-de-clavier-que-sont-les-claviers-mecanique-79235?page=3" hreflang="fr">différents types d’interrupteurs</a> et j’ai profité d’une offre intéressante sur le site <a href="https://www.massdrop.com/" hreflang="en">Massdrop</a> (un site pour riche voulant devenir pauvre) pour <a href="https://www.massdrop.com/buy/20575?mode=guest_open" hreflang="en">m’en offrir un</a>.</p>

<p>Mais ce qui me fascinait c’était les gars qui <a href="https://www.pinterest.com/search/pins/?q=keyboard%20atreus" hreflang="en">construisaient leur clavier eux-mêmes</a>… Il faut savoir que les kits à faire soi-même sont assez chers. Et c’est ainsi que je tombe sur le clavier <em>Atreus</em> dont je le me suis laissé aller à la lecture des différents journaux de construction <a href="https://github.com/technomancy/atreus/wiki/BuildLogs" hreflang="en">disponible sur le dépôt</a>. <a href="http://keathley.io/keyboards/atreus/diy/2015/05/31/Building-a-Keyboard.html" hreflang="en">Celui-ci</a> fut d’ailleurs ma référence principale.</p>

<h3>Le résultât</h3>

<p>Et sans plus attendre, la bête&nbsp;:</p>

<p><a class="media-link" href="media/2a47bd77.clavier_atreus_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_001.jpg"><img alt="" class="media" src="media/d9242d0a..clavier_atreus_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_001_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>OK, j’avoue, ce n’est pas si impressionnant que ça. Mais c’est du bois qui brille et qui sent le bois tu vois… <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>Pour être honnête, je me suis foiré sur pas mal de points (ponçage et surtout traitement). Un bon prétexte pour en refaire un, un jour. <img src="media/00461682.1420.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/1420.gif" alt=":grenadelauncher:" class="smiley" /></p>

<h3>L’<em>Atreus</em></h3>

<p>L’<em>Atreus</em> est un clavier dit 40&nbsp;% (utilisant 40&nbsp;% du nombre de touche classique) crée par Phil Hagelberg <a href="https://geekhack.org/index.php?topic=54759.0" hreflang="en">qui était fan de son clavier Ergodox</a> mais voulait une version plus petite pour pouvoir s’en servir dans les cafés où il avait l’habitude d’aller. Le bonhomme a donc créé son clavier (design, conception et tout le tintouin), <a href="https://atreus.technomancy.us/" hreflang="en">proposé un kit à l’achat</a> et a mis l’<a href="https://github.com/technomancy/atreus" hreflang="en">ensemble en ligne</a> pour que chacun puisse faire le sien (franchement, c’est la classe <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 donc un clavier portable open source assez simple à monter et bidouiller qui est resté dans ma tête longtemps et que j’ai décidé de commencer comme un projet à long terme, sans trop savoir dans quoi je me lançais.</p>

<h3>Prix</h3>

<p>Je commence directement par le prix, sans trop de contexte, j’expliquerais après. <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>J’ai compris assez vite que, comparé à ce qu’on pourrait imaginer, les coûts allaient être importants. Les claviers mécaniques sont souvent chers. Ceux à faire soi-même n’y échappe pas, surtout au démarrage, quand on a pas le matériel. Il faut savoir que pour tout ce qui est électronique, ebay.com (avec la case Free Shipping coché) est votre ami. <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>Voici ce que j’ai payé&nbsp;:</p>

<table>
	<tbody>
		<tr>
			<th>Description</th>
			<th>Site</th>
			<th>Prix</th>
		</tr>
		<tr>
			<td>Découpe laser du boîtier</td>
			<td>sculpteo.fr</td>
			<td>41.03 €</td>
		</tr>
		<tr>
			<td>120 Interrupteurs Gateron marrons</td>
			<td>massdrop.com</td>
			<td>$32.99</td>
		</tr>
		<tr>
			<td><a href="https://www.pjrc.com/teensy/" hreflang="en">Teensy 2.0</a></td>
			<td>ebay.com</td>
			<td>$14.00</td>
		</tr>
		<tr>
			<td>100 <a href="https://fr.wikipedia.org/wiki/1N4148" hreflang="fr">Diodes 1N4148</a></td>
			<td>ebay.com</td>
			<td>$1.00</td>
		</tr>
		<tr>
			<td>100 fils de soudure en étain double tête</td>
			<td>ebay.com</td>
			<td>$2.30</td>
		</tr>
		<tr>
			<td>61 touches en plastique PBT noir</td>
			<td>ebay.com</td>
			<td>$18.00</td>
		</tr>
		<tr>
			<td>10 vis et leur écrou</td>
			<td>Castorama</td>
			<td>4.00 €</td>
		</tr>
		<tr>
			<td>Pistolet à colle</td>
			<td>Castorama</td>
			<td>10.00 €</td>
		</tr>
	</tbody>
</table>

<p>Soit un total d’environs 116&nbsp;€.</p>

<p>Notez que c’est une estimation grossière (pour les interrupteurs j’ai pris un paquet de 120 alors que seul 42 étaient nécessaires), mais ça vous donne une idée.</p>

<p>Viennent ensuite les frais annexes&nbsp;:</p>

<table>
	<tbody>
		<tr>
			<th>Description</th>
			<th>Site</th>
			<th>Prix</th>
		</tr>
		<tr>
			<td>Fer à souder</td>
			<td>amazon.fr</td>
			<td>20.00 €</td>
		</tr>
		<tr>
			<td>Fil d’étain</td>
			<td>amazon.fr</td>
			<td>5.00 €</td>
		</tr>
		<tr>
			<td>Pince électronique</td>
			<td>Castorama</td>
			<td>2.00 €</td>
		</tr>
		<tr>
			<td>Multimètre (franchement ça aide)</td>
			<td>Castorama</td>
			<td>10.00 €</td>
		</tr>
		<tr>
			<td>1L d’acétone</td>
			<td>Castorama</td>
			<td>8.00 €</td>
		</tr>
		<tr>
			<td>500&nbsp;ml d’huile de lin</td>
			<td>Castorama</td>
			<td>8.00 €</td>
		</tr>
		<tr>
			<td>Pot de cire</td>
			<td>Castorama</td>
			<td>15.00 €</td>
		</tr>
		<tr>
			<td>Convertisseur Micro-USB vers Mini-USB</td>
			<td>ebay.com</td>
			<td>$1.00</td>
		</tr>
		<tr>
			<td>Câble Mini-USB vers USB (3&nbsp;mètres)</td>
			<td>ebay.com</td>
			<td>$6.55</td>
		</tr>
	</tbody>
</table>

<p>Je possédais déjà un certain nombre de ces objets (fer à souder, fil, multimètre).</p>

<p>Vous comprenez que ça revient cher. Si votre but est de faire des économies ce n’est pas la bonne voie. <img src="media/f1f7d503.nannan.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nannan.gif" alt=":nannan:" class="smiley" /></p>

<h3>Découpe du boîtier via Sculpteo</h3>

<p>Sur le <a href="https://github.com/technomancy/atreus" hreflang="en">dépôt officiel du projet</a> il existe <a href="https://github.com/technomancy/atreus/tree/master/case/dxf" hreflang="en">une version</a> prête à être envoyé à un service de coupe laser à la demande&nbsp;: <a href="https://www.ponoko.com/" hreflang="en">Pokono</a>.</p>

<p>Le service n’est pas très cher mais étant placé aux États-Unis, les frais de port atteignaient, de mémoire, 50&nbsp;$ pour, toujours de mémoire, 27&nbsp;$ de coupe…</p>

<p>J’ai donc cherché un service similaire pour la France sans trop y croire et je suis tombé sur <a href="https://www.sculpteo.com/fr/" hreflang="fr">Scultpeo</a> qui est beaucoup plus acceptable (même s’il force à utiliser l’envoie express, assez cher, ce qui est franchement dommage). Le site est plutôt bien fait et permet d’expérimenter les prix des matériaux assez facilement. J’ai donc modifié le fichier svg de Pokono pour Sculpteo.</p>

<p>Je suis parti sur un matériau en contre-plaqué (<em>Plywood</em>), qui permet de garder les rainures originales du bois, en peuplier (<em>poplar</em>):</p>

<p><a class="media-link" href="media/df1bb858.clavier_atreus_002.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_002.jpg"><img alt="" class="media" src="media/43def4a0..clavier_atreus_002_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_002_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>J’ai retrouvé la facture finale (mais leurs tarifs ont un peu changés depuis):</p>

<table>
	<tbody>
		<tr>
			<td>Coût de fabrication</td>
			<td>22,53&nbsp;€</td>
		</tr>
		<tr>
			<td>Envois express</td>
			<td>11,66&nbsp;€</td>
		</tr>
		<tr>
			<td>Total HT</td>
			<td>34,19&nbsp;€</td>
		</tr>
		<tr>
			<td>TVA</td>
			<td>6,84&nbsp;€</td>
		</tr>
		<tr>
			<td>Total</td>
			<td>41,03&nbsp;€</td>
		</tr>
	</tbody>
</table>

<p>Il n’y a pas d’autres choix que l’envoie express et c’est franchement dommage vu le prix… Mais bon…</p>

<p>Comme c’est de la découpe laser, le profile de la partie coupe est toute noir, il faut donc poncer. Je l’ai fais à la main puis je me suis dit que c’était un bon prétexte pour acheter un Dremel en promotion…</p>

<h3>Traitement du bois</h3>

<p>Allons-y tout de go&nbsp;: J’ai raté le traitement de mon bois (Avouez que c’est con sachant que c’était le principal intérêt du projet… <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>J’ai d’abords poncé les bords de chacune des pièces pour retirer la brulure de la coupe laser (jusqu’ici ça va) puis j’ai voulu poncer la surface des pièces ce qui a eu pour effet de casser un certain nombre de fibres du bois.</p>

<p>Puis vient le traitement&nbsp;à l’huile de lin. Je suis parti sur un mélange térébenthine/huile de lin (la térébenthine servant à diluer l’huile de lin en vu de la faire pénétrer dans le bois) en augmentant le pourcentage d’huile de lin sur trois couche (70/30, 50/50, 30/70).</p>

<p>Pour ma première couche, je décide d’utiliser du brou de noix pour foncer le bois et accentuer les rainures. Premier fail, sans vraiment comprendre pourquoi, le brou de noix ne s’est pas dilué dans le mélange ce qui formait des petites gouttes sombres plutôt qu’un aplat uniforme.</p>

<p>Bon, ce n’est pas si grave me dis-je… <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>J’ai ensuite fini avec une dernière couche 100&nbsp;% huile de lin. Et bien il ne fallait mieux pas… Cette couche fit des gruaux (que vous pouvez constater dans les photos qui suivent). Je pense qu’une petite dilution 10/90 n’aurait pas fait de mal. <img src="media/53728ad7.nervous.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nervous.gif" alt=":nervous:" class="smiley" /></p>

<p>C’est à ce moment-là que je décide d’acheter de la cire à bois pour sauver les meubles ( <img src="media/990690f6.whistle2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /> ). Il faut bien avouer que l’efficacité de la cire n’a d’égale que la longueur de la liste des produits chimiques qui la compose…</p>

<h3>Les interrupteurs</h3>

<p>Je ne vais pas faire un énième guide des différents interrupteurs de clavier mécanique, il en existe des dizaines pour peu qu’<a href="https://www.google.fr/search?q=guide+switches+clavier+mecanique" hreflang="fr">on sache se servir de Google</a>.</p>

<p>Comme je vous disais précédemment, j’avais déjà en ma possession un Keycool Hero 84 blanc (acheté sur Massdrop) avec des interrupteurs <a href="http://www.kailh.com/en/products.asp?Categoryid=113&amp;rel=15" hreflang="en">Kaihua Kailh bleu</a>. J’ai fait une partie de <a href="https://www.youtube.com/watch?v=M5-LjE4LSLA" hreflang="en">Ballerina</a> et tout Croc-Blanc dessus. Ils sont super mais un peu bruyant. J’ai eu l’occasion de tester des interrupteurs de la marque Gateron bleu et marron. Franchement ils sont vraiment géniaux. Du-coup je me suis fixé sur le Gateron marron. Puis une offre intéressante passa sur Massdrop et j’en pris un pack (120 pour n’en utiliser que 42 (coïncidence, je ne crois pas <img src="media/24b98f53.riva.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/riva.gif" alt=":pasClasse:" class="smiley" /> ), le prix plus haut est donc un peu biaisé)…</p>

<p><a class="media-link" href="media/84e36254.clavier_atreus_003.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_003.jpg"><img alt="" class="media" src="media/9c19e2f0..clavier_atreus_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_003_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p><a class="media-link" href="media/b545ae86.clavier_atreus_004.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_004.jpg"><img alt="" class="media" src="media/a5edea72..clavier_atreus_004_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_004_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>J’ai “soudé” les interrupteurs au pistolet&nbsp;à colle. C’est assez efficace, bien que les trous de la planche maintiennent déjà bien les interrupteurs&nbsp;:</p>

<p><a class="media-link" href="media/137d2ab3.clavier_atreus_005.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_005.jpg"><img alt="" class="media" src="media/6577d7ca..clavier_atreus_005_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_005_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<h3>Les soudures</h3>

<p>C’est mon moment préféré. Je faisais ça le soir après une journée de boulot en écoutant de la musique.</p>

<p><a class="media-link" href="media/089bc5a3.clavier_atreus_007.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_007.jpg"><img alt="" class="media" src="media/890e0db4..clavier_atreus_007_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_007_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Vous l’aurez compris, on construit une matrice en soudant les LED horizontalement les unes aux autres. Il faut bien faire attention&nbsp;à la polarité des différents composants. Pour ça, la lecture du <a href="media/5e3abbcc.assembly.pdf" data-original-source="https://atreus.technomancy.us/assembly.pdf" hreflang="en">guide d’assemblage</a> en amont est fondamentale et on y revient souvent, d’où l’intérêt de l’avoir&nbsp;à coté.</p>

<p><a class="media-link" href="media/0395a61d.clavier_atreus_008.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_008.jpg"><img alt="" class="media" src="media/c5c5b1f8..clavier_atreus_008_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_008_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Puis vient la partie verticale, un peu plus complexe. L’idée est de dénuder les fils&nbsp;à l’endroit ou ils vont être en contact (et uniquement là pour éviter les faux contacts).</p>

<p><a class="media-link" href="media/60de8acb.clavier_atreus_009.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_009.jpg"><img alt="" class="media" src="media/8173786f..clavier_atreus_009_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_009_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Puis on connecte chaque ligne de la matrice au microcontrôleur&nbsp;:</p>

<p><a class="media-link" href="media/fc373336.clavier_atreus_010.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_010.jpg"><img alt="" class="media" src="media/c16669df..clavier_atreus_010_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_010_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Notez que j’ai utilise des couleurs différentes suivant qu’on soude la ligne horizontale ou verticale.</p>

<p><a class="media-link" href="media/af2fa06e.clavier_atreus_011.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_011.jpg"><img alt="" class="media" src="media/e87b5494..clavier_atreus_011_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_011_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Le Teensy 2.0 est un peu vicieux, car les numéros des broches ne se suivent pas. Jugez par vous-même&nbsp;:</p>

<p><img alt="" class="media" src="media/cc57a3e4.microcontrolleur_tensy_2_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/microcontrolleur_tensy_2_001.jpg" style="margin: 0 auto; display: table;" /></p>

<p>Il faut donc faire attention si on ne souhaite pas se payer une resoudure intégrale. <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>Une autre astuce consiste à <a href="https://geekhack.org/index.php?topic=57007.0" hreflang="en">utiliser des fils mâles/femelle</a> pour éviter les bêtises et simplifier le montage. Sur un premier montage je trouve l’idée très intéressante. Et forcement, je n’ai découvert ça qu’à la fin de l’étape de soudure.</p>

<h3>Les touches</h3>

<p>Je voulais un <a href="media/f2b3654a.keycaps.jpg" data-original-source="https://img.zwame.pt/forum/misc/teclados/keycaps.jpg" hreflang="en">profil SP SA</a> (que je trouve super classe et <em>vintage</em>) mais la seule entreprise en fabriquant encore se situe aux États-Unis, est constamment en rupture de stock et les frais de port sont délirants. J’ai donc dû me rabattre sur un ensemble de touche sur ebay.com. J’ai simplement inversé la dernière rangée (celle du haut) avec la rangée du bas pour que les touches soient orientées vers mes pouces… Au final je suis assez content du résultat.</p>

<h3>Le microcontrôleur</h3>

<p>Les différents journaux de construction que j’avais lu m’avaient donnés envi de faire les soudures moi-même, sans circuit imprimé. J’optais donc pour le microcontrôleur <a href="https://www.pjrc.com/teensy/" hreflang="en">Teensy 2.0</a>, une petite planche de développement USB pas cher, compatible <a href="https://www.arduino.cc/" hreflang="en">Arduino</a> embarquant une puce <a href="http://www.microchip.com/wwwproducts/en/ATmega32U4" hreflang="en">ATmega32U4</a>.</p>

<h3>Le firmware</h3>

<p>C’est souvent là qu’on panique. Je n’ai pas échappé à la règle. Je ne suis pas un habitué du développement sur microcontrôleur. J’ai donc fait quelques erreurs qui m’ont amené à dessouder et ressouder un certain nombre de choses alors que j’avais simplement compile avec les mauvaises options… Au lieu de ne rien faire quand j’appuyais sur les touches, le clavier renvoyait des lettres de manière bizarre (mais toujours logique).</p>

<p>La dernière chose bizarre que j’avais était que <a href="https://geekhack.org/index.php?topic=88204" hreflang="en">les touches Ctrl et Alt étaient inversées</a>. Que voila un bon prétexte pour aller modifier le code de l’agencement des touches. <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p>

<p>Au passage, <a href="https://github.com/technomancy/tmk_keyboard" hreflang="en">le code</a> du firmware de l’<em>Atreus</em> s’appuie sur le firmware <a href="https://github.com/tmk/tmk_keyboard" hreflang="en">TMK</a> (un firmware très connu après des bidouilleurs de clavier).</p>

<h3>Montage final</h3>

<p>Comme vous allez le voir, je n’ai pas trouvé de vis pile poil adapte&nbsp;à la hauteur du boîtier&nbsp;:</p>

<p><a class="media-link" href="media/77673a14.clavier_atreus_012.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_012.jpg"><img alt="" class="media" src="media/47586804..clavier_atreus_012_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_012_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p><a class="media-link" href="media/8a22aacf.clavier_atreus_013.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_013.jpg"><img alt="" class="media" src="media/3f9509b3..clavier_atreus_013_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_013_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p><a class="media-link" href="media/84612289.clavier_atreus_014.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_014.jpg"><img alt="" class="media" src="media/16eb83a3..clavier_atreus_014_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_014_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Si j’avais cherché un peu, j’aurais vu que qu’ebay regorge de ce type de vis (cherchez «&nbsp;m2 flat head&nbsp;» pour vous en convaincre). Qu’a cela ne tienne, il suffit donc de scier les bouts de vis avec une scie à métaux&nbsp;!</p>

<p>Après un combat sans pitié contre les probabilités, je conservais mes doigts et pouvais enfin fermer mon clavier&nbsp;:</p>

<p><a class="media-link" href="media/b58dd279.clavier_atreus_015.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_015.jpg"><img alt="" class="media" src="media/901c295f..clavier_atreus_015_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_015_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p><a class="media-link" href="media/32dccdcc.clavier_atreus_016.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_016.jpg"><img alt="" class="media" src="media/0fbbf028..clavier_atreus_016_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_016_m.jpg" style="margin: 0 auto; display: table;" /></a></p>

<p>Enfin, on branche son clavier pour commencer à écrire ses premières phrases et se familiariser avec l’agencement des touches. Puis, comme tout projet <em>DIY</em>, on le pose dans un coin pour ne plus jamais y toucher. <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>

<h3>Peut mieux faire&nbsp;?</h3>

<p>A peine…</p>

<p>En fouillant dans le depot, je suis tombé sur un <a href="https://github.com/technomancy/atreus/tree/master/case/openscad" hreflang="en">script OpenSCAD</a>&nbsp;:</p>

<p>De que quoi&nbsp;? <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>Ctrl+T, openscad&lt;enter&gt;, <a href="http://www.openscad.org/" hreflang="en">OpenSCAD</a>&nbsp;:</p>

<blockquote>
<p>OpenSCAD is not an interactive modeller. Instead it is something like a 3D-compiler that reads in a script file that describes the object and renders the 3D model from this script file. This gives you (the designer) full control over the modelling process and enables you to easily change any step in the modelling process or make designs that are defined by configurable parameters.</p>
</blockquote>

<p><img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /></p>

<blockquote>
<p>it is something like a 3D-compiler</p>
</blockquote>

<p><img src="media/31e65c2e.idee.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/idee.gif" alt=":idee:" class="smiley" /></p>

<p>Un truc de TD en manque de sensation&nbsp;! Génial&nbsp;!</p>

<p>J’installe OpenSCAD, j’ouvre le script et&nbsp;:</p>

<p><a class="media-link" href="media/25c37891.clavier_atreus_018.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_018.png"><img alt="" class="media" src="media/ceb4121c..clavier_atreus_018_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_018_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>On dirait un truc fait pour moi&nbsp;! <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>Mais regardons ce script de plus près&nbsp;:</p>

<pre>
<code class="language-cpp">// -*- mode: c -*-
/* All distances are in mm. */

/* set output quality */
$fn = 50;

/* Distance between key centers. */
column_spacing   = 19;
row_spacing      = column_spacing;

/* This number should exceed row_spacing and column_spacing. The
 default gives a 1mm = (20mm - 19mm) gap between keycaps and cuts in
 the top plate.*/
key_hole_size = 20;

/* rotation angle; the angle between the halves is twice this
   number */
angle = 10;

/* The radius of screw holes. Holes will be slightly bigger due
   to the cut width. */
screw_hole_radius = 1.5;
/* Each screw hole is a hole in a "washer". How big these "washers"
   should be depends on the material used: this parameter and the
   `switch_hole_size` determine the spacer wall thickness. */
washer_radius     = 4 * screw_hole_radius;

/* This constant allows tweaking the location of the screw holes near
   the USB cable. Only useful with small `angle` values. Try the value
   of 10 with angle=0. */
back_screw_hole_offset = 0;

/* Distance between halves. */
hand_separation        = 0;

/* The approximate size of switch holes. Used to determine how
   thick walls can be, i.e. how much room around each switch hole to
   leave. See spacer(). */
switch_hole_size = 14;

/* Sets whether the case should use notched holes. As far as I can
   tell these notches are not all that useful... */
use_notched_holes = true;

/* Number of rows and columns in the matrix. You need to update
   staggering_offsets if you change n_cols. */
n_rows = 4;
n_cols = 5;</code></pre>

<p>Mhhh… On dirait un script avec des variables globales pour générer la structure du clavier… Si j’essayais de modifier deux trois variables, comme ça, juste pour voir… Après tout c’est vrai que l’<em>Atreus</em> n’a pas beaucoup de touches, une rangée supplémentaire de chaque coté ne ferait pas de mal… Et puis l’alignement des touches est un peu fort, sans parler de l’épaisseur… Qu’est ce qui se passe si je…</p>

<blockquote>
<p>Quelques heures plus tard…</p>
</blockquote>

<p><a class="media-link" href="media/3693a4cf.clavier_atreus_017.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/clavier_atreus_017.png"><img alt="" class="media" src="media/3739f334..clavier_atreus_017_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_28_clavier_atreus/.clavier_atreus_017_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>Il semble que les interrupteurs restant vont finalement trouver une utilité. <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>A bientôt&nbsp;!</p>

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


feed_id: urn:md5:c4b7ef687147cc53a32e497dc6c44746
title: Personnaliser ses AOV dans Guerilla
uri: Personnaliser-ses-AOV-dans-Guerilla
url: http://www.fevrierdorian.com/blog/post/2017/05/27/Personnaliser-ses-AOV-dans-Guerilla
content:
<p><img alt="" class="media" src="media/d527162e.guerilla_custom_aov_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_tn.png" style="float: left; margin: 0 1em 1em 0;" />Ça fait un moment que je n’ai pas fais de tutoriel. En voici un tout petit principalement à destination des étudiants utilisant ou voulant (les biens inspirés :P ) utiliser Guerilla pour leur projet de fin d’année.</p>

<p>L’idée étant de faire un tuto pour sortir une aov personnalisé assignant une couleur suivant les objets. Nous allons ici utiliser des simples couleurs (rouge et bleu dans le cas d’un masque) mais sachez que vous pouvez remplacer cette couleur par une texture, de l’occlusion ou pleins d’autres choses.</p>

<p>En avant&nbsp;! <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>Ouvrez Guerilla. La première chose à faire c’est une petite scène de test. Un plan, une sphère c’est parfait&nbsp;:</p>

<p><img alt="" class="media" src="media/4faffaf1.guerilla_custom_aov_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_001.png" style="margin: 0 auto; display: table;" /></p>

<p style="text-align: center;">Avec ça, Votre projet de fin d’étude semble bien partis. Encore un peu de boulot et Pixar pleurera devant vos rendus. <img src="media/491fa5e5.evilgrin0002.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/evilgrin0002.gif" alt=":gniarkgniark:" class="smiley" /></p>

<p>Ouvrez le rendergraph par défaut, glissez-déposer la sphère et le plan depuis la <em>Node List</em> pour créer un <em>path</em> puis créez un <em>material override</em> (Ctrl+Espace dans le rendergraph, tapez «&nbsp;mat&nbsp;», puis Entrer). Enfin connectez-moi tout ça sous cette forme&nbsp;:</p>

<p><img alt="" class="media" src="media/9202a047.guerilla_custom_aov_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_002.png" style="margin: 0 auto; display: table;" /></p>

<p>Je traduis le graph ci-dessus&nbsp;: L’objet <em>Sphere</em> va se faire <em>overrider</em> un paramètre par le nœud <em>MaterialOverride</em>. Cette opération est ensuite fusionnée aux modifications de la branche principale via un nœud union. Il en va de même pour l’objet <em>Plane</em>. <img src="media/af8fdcdb.zinzin.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/zinzin.gif" alt=":zinzin:" class="smiley" /></p>

<p>Ensuite, on clique sur <em>MaterialOverride</em>, on tape le nom de l’<em>override</em> que l’on souhaite créer. Ici (par exemple) «&nbsp;MyMask1&nbsp;» de type <em>Color</em>. On assigne la couleur rouge. On fait de même pour le <em>MaterialOverride</em> du <em>Plane</em> mais de couleur bleu&nbsp;:</p>

<p><a class="media-link" href="media/968fc40a.guerilla_custom_aov_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_003.png"><img alt="" class="media" src="media/bc6194c0..guerilla_custom_aov_003_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/.guerilla_custom_aov_003_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>Information intéressante a cette étape&nbsp;: Si vous cliquez sur le petit «&nbsp;M&nbsp;» a droite, vous pourrez sélectionner un sous-shader, notamment <em>Texture</em>, <em>Occlusion</em> et <a href="http://guerillarender.com/doc/1.4/Library_Attributes_Cloud.html" hreflang="en">Cloud</a>. Si vous êtes joueur et que vous souhaitez rendre des attributs présents dans vos alembic vous pouvez regarder du côté de <em>PrimVar</em> <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>Maintenant nous avons des <em>overrides</em> sur des objets. Il faut pouvoir les rendre&nbsp;! <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>Créez un nouvel aov (Cliquez sur le + à cote de l’aov de <em>Beauty</em>). Renommez-le comme vous le voulez (je l’ai appelé «&nbsp;MyMask1&nbsp;» mais en fait ce n’est pas important ici):</p>

<p><img alt="" class="media" src="media/238ee6d0.guerilla_custom_aov_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_004.png" style="margin: 0 auto; display: table;" /></p>

<p>Cliquez dessus puis, dans le champ <em>Shader Color</em>, mettez «&nbsp;MyMask1&nbsp;» (c’est là qu’il faut mettre le même nom que les noms des <em>overrides</em> créés précédemment):</p>

<p><img alt="" class="media" src="media/dd8fec41.guerilla_custom_aov_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_005.png" style="margin: 0 auto; display: table;" /></p>

<p>Faites un rendu (Ctrl+R) puis sélectionnez l’aov «&nbsp;MyMask1&nbsp;» (dans le menu déroulant en bas à gauche de la <em>RenderView</em>) :</p>

<p><a class="media-link" href="media/0cff1b40.guerilla_custom_aov_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov_006.png"><img alt="" class="media" src="media/689b8577..guerilla_custom_aov_006_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/.guerilla_custom_aov_006_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>Et une petite image finale pour avoir une vision d'ensemble. <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><a class="media-link" href="media/6145f8c0.guerilla_custom_aov.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/guerilla_custom_aov.png"><img alt="" class="media" src="media/956c7be7..guerilla_custom_aov_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_05_27_aov_personalise_guerilla/.guerilla_custom_aov_m.png" style="margin: 0 auto; display: table;" /></a></p>

<p>En espérant que ça vous mette le pied à l’étrier, n’hésitez pas à creuser un peu et à expérimenter. <img src="media/5442ec71.0010.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/0010.gif" alt=":joue:" class="smiley" /></p>

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

<p>Dorian</p>

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


feed_id: urn:md5:1826ba5e2f7dc3130d6ad2a0ff0fb402
title: Faire un override pour supprimer un shader dans Guerilla
uri: Faire-un-override-pour-supprimer-un-shader-dans-Guerilla
url:
http://www.fevrierdorian.com/blog/post/2017/06/04/Faire-un-override-pour-supprimer-un-shader-dans-Guerilla

content:
<p><img alt="" class="media" src="media/1b1122a5.supprimer_override_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_tn.png" style="float: left; margin: 0 1em 1em 0;" />Si vous assignez un shader (de volume par exemple) il peut être utile de pouvoir le désassigner, plus loin dans le rendergraph.</p>

<p>Il me semble que c’était possible en 1.3 mais que ce ne soit plus possible en 1.4. <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>Je vous propose donc une petite méthode pour désassigner un shader. <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>Mais expliquons un peu le souci. <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>Faites une petite scène «&nbsp;sphère et plan&nbsp;» puis faite un override d’assignation de shader mais videz le nom du shader&nbsp;:</p>

<p><img alt="" class="media" src="media/629bcc1a.supprimer_override_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_003.png" style="margin: 0 auto; display: table;" /></p>

<p>Puis connectez l’override à la branche principale. Comme vous pouvez le constater, l’assignation reste faite en bout de graph&nbsp;:</p>

<p><img alt="" class="media" src="media/68ff7b52.supprimer_override_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_001.png" style="margin: 0 auto; display: table;" /></p>

<p style="text-align: center;"><em>Bon sang, quand j’override par «&nbsp;rien du tout&nbsp;» Guerilla garde la valeur de l’override original. </em> <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>Et Guerilla semble sciemment considérer que vous avez fais une erreur&nbsp;:</p>

<p><img alt="" class="media" src="media/8479139d.supprimer_override_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_002.png" style="margin: 0 auto; display: table;" /></p>

<p>On va résoudre ça.&nbsp; <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /> Supprimez l’assignation puis créez un nœud de Script (Ctrl+Espace, «&nbsp;scri&nbsp;», Entrée):</p>

<p><img alt="" class="media" src="media/3648dadd.supprimer_override_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_004.png" style="margin: 0 auto; display: table;" /></p>

<p>Connectez le dans le graph à la place de votre assignation précédente&nbsp;:</p>

<p><img alt="" class="media" src="media/1b00a283.supprimer_override_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_005.png" style="margin: 0 auto; display: table;" /></p>

<p>Regardez ses attributs. Le script arrive avec un petit exemple pour illustrer son comportement. Mais nous n’allons pas en avoir besoin. Supprimez les deux propriétés (en cliquant sur les croix en haut à droite), puis cliques sur le bouton «&nbsp;Edit&nbsp;»:</p>

<p><img alt="" class="media" src="media/cb42b4c8.supprimer_override_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_006.png" style="margin: 0 auto; display: table;" /></p>

<p>Sans vous soucier des commentaires regardez ce que vous avez&nbsp;:</p>

<pre>
<code>if Input then
	Output = duplicate (Input)
	Output["variable."..ColorName] = CustomShaderColor
end
</code></pre>

<p>Je vous explique rapidement&nbsp;: Ce script duplique la table (c’est la <a href="http://lua-users.org/wiki/TablesTutorial" hreflang="en">structure de données</a> en <a href="https://fr.wikipedia.org/wiki/Lua" hreflang="fr">lua</a>) <em>Input</em> en <em>Output</em>, modifie l’entrée «&nbsp;variable.DiffuseColor&nbsp;» (car il récupère la valeur de l’attribut «&nbsp;ColorName&nbsp;» que nous avons supprimé précédemment) pour lui mettre la valeur de l’attribut «&nbsp;CustomShaderColor&nbsp;» que nous avons, lui aussi, supprimé (c’était la couleur rouge). <img src="media/61b0b317.tuComprendRien.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/tuComprendRien.gif" alt=":tuComprendRien:" class="smiley" /></p>

<p>On va utiliser ce mécanisme pour venir supprimer l’assignation du shader. Mais reste la question&nbsp;: Quel est le nom de l’attribut à modifier&nbsp;? <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>Pour cela rien de plus simple&nbsp;: Ouvrez la console (menu «&nbsp;View|Show/Hide console (Alt+2)&nbsp;»), sélectionnez votre sphère puis faites Shift+D. Ceci va afficher, dans la console, la liste de tous les attributs ainsi que leur valeur telles qu’elles seraient envoyées au rendu. Cherchez «&nbsp;shader&nbsp;»:</p>

<pre>
<code>shade.shadebothsides: 0
shade.textureapproximation: "glossy"
shade.texturemaxsize: 0
shader.displacement: ""
shader.surface: "Surface"
shader.volume: ""
shape.cached: 1
shape.combineprocedural: 0
shape.compression: 0</code></pre>

<p>Vous l’avez&nbsp;! «&nbsp;shader.surface&nbsp;» (ou «&nbsp;shader.volume&nbsp;» ou même «&nbsp;shader.displacement&nbsp;» si vous souhaitez supprimer le shader de displacement).</p>

<p>Modifiez le script pour supprimer l’assignation&nbsp;:</p>

<pre>
<code>if Input then
	Output = duplicate (Input)
	Output["shader.surface"] = ""
end
</code></pre>

<p>Sauvez Ctrl+S puis vérifiez par vous même&nbsp;:</p>

<p><img alt="" class="media" src="media/419a62a0.supprimer_override_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_14_supprimer_override_guerilla/supprimer_override_007.png" style="margin: 0 auto; display: table;" /></p>

<p>Comme vous pouvez le voir, le shader est désassigné. <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>En espérant que ça en débloque certains.</p>

<p>À bientôt&nbsp;!</p>

<p>Dorian</p>

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


feed_id: urn:md5:107657fad4613eb3c9236696f77dd681
title: Post mortem: Ballerina
uri: Post-mortem-Ballerina
url: http://www.fevrierdorian.com/blog/post/2017/06/11/Post-mortem%3A-Ballerina
content:
<p><img alt="" class="media" src="media/5e596cb2.post_mortem_ballerina_tn.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/post_mortem_ballerina_tn.jpg" style="float: left; margin: 0px 1em 1em 0px; width: 150px; height: 150px;" />Je viens enfin de finir le post mortem de mon travail sur le long-métrage Ballerina. Je vous préviens, c'est long.</p>

<p>En espérant que ça vous plaise. <img src="media/94b95129.popcorn.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/popcorn.gif" alt=":popcorn:" class="smiley" /></p>    <h3>La bande annonce</h3>

<p>Ce post mortem contient évidemment son lot de <em>spoil</em>. Je considère que vous avez déjà vu le film. Si vous ne l’avez pas fait, franchement faites-le. Le montage est rapide et on ne s’ennuie pas et vous lâcherez sûrement une petite larme. Dans tous les cas, voici la bande annonce&nbsp;:</p>

<p style="text-align: center;"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/M5-LjE4LSLA" width="560"></iframe></p>

<h3>Mon poste</h3>

<p>J’ai eu plusieurs casquettes durant le projet (comme d’hab’ en fait…). C’était du pip’, du pip’, du pip’. Voici une liste non exhaustive de ce que j’ai fais&nbsp;:</p>

<ul>
	<li>Lookdev (<a href="http://www.guerillarender.com/" hreflang="en">Guerilla</a>)</li>
	<li>Lighting (<em>Guerilla</em>)</li>
	<li>Renderfarm (<em><a href="http://www.pipelinefx.com/" hreflang="en">Qube</a></em>)</li>
	<li>Hair/Végétation (Maya/<em><a href="http://peregrinelabs.com/yeti/" hreflang="en">Yeti</a></em>)</li>
</ul>

<h3>Un démarrage difficile</h3>

<p>Sans rentrer dans les détails, le studio appartenait aux producteurs du film. C’était leur premier long-métrage. Le projet a connu un certain nombre de difficultés et a dû “recommencer” en cours de route. Je suis arrivé alors que le projet avait été mis en pause et une bonne partir des équipes, mise <span class="st">à</span> pied. Il n’y avait pas (plus en fait) d’outils, pas de pipeline. Nous n’étions pas nombreux dans le studio (moins de dix). La R&amp;D commençait le pipeline et le département artistique continuait ses recherches. Il était d’ailleurs difficile de se dire, en arrivant le matin, qu’un film allait sortir de tout ça. La masse de travail abattu lors des premiers mois fut importante.</p>

<h3>Shotgun</h3>

<p>Le temps et les ressources disponibles étant limitées, nous avons opté pour <em><a href="http://shotgunsoftware.com/" hreflang="en">Shotgun</a></em> pour gérer l’intégralité de notre base de données (comprenez qu’il n’y avait aucune autre base de données que <em>Shotgun</em>, même pas un petit <a href="https://www.mysql.com/" hreflang="en">MySQL</a>, planqué sur un serveur en loucedé près des toilettes, rien&nbsp;!). C’est (très) cher mais au vu de la configuration du studio et de ce que <em>Shotgun</em> propose, je pense, avec du recul, que c’était un bon choix.</p>

<p>Une grosse partie du travail de départ concernait les <em>template</em> de chemin de fichier de <em>Shotgun</em> pour réussir à publier en utilisant <em>Shotgun</em> mais notre propre structure de fichier.</p>

<p>Viens ensuite la suppression des step/task de <em>Shotgun</em> au profit d’un système maison. C’est vraiment un truc idiot, dans <em>Shotgun</em>, que les steps et les tasks puissent être créées et modifiées par les coordinateurs, car on ne peut, du-coup, pas s’appuyer dessus en termes d’infrastructure. Il fallait donc les remplacer pour faire la même chose mais en plus robuste.</p>

<p>Comme tout changeait tout le temps, les chemins de fichier n’utilisaient pas les noms des assets et des plans mais leurs ids, donnant des chemins de fichier difficile à lire. Bien que ça puisse paraître dangereux, cela n’a posé aucun soucis majeur en pratique car tout était fait pour éviter aux personnes d’avoir à naviguer dans la structure des dossiers.</p>

<p><em>Shotgun</em> est lent. Quand le builder est arrivé (voir plus bas) on c’est retrouvé à littéralement mettre <em>Shotgun</em> à terre avec des requêtes importantes (en gros, notre hiérarchie de scène c’était <em>Shotgun</em>…). Après pas mal d’optimisation de leur part, on a aussi mis un système de cache basé sur <em><a href="https://redis.io/" hreflang="en">Redis</a></em> (<em>Redis</em> c’est bon, mangez-en).</p>

<h3>Modeling, Rigging et Lookdev commencent</h3>

<p>Ces trois départements ont commencé rapidement et fonctionné en parallèle presque immédiatement, ce qui nécessitait, du fait de l’impossibilité d’anticiper, un nombre conséquent d’aller-retour. Il fallait être continuellement vigilant sur ce que chaque département livrait/récupérait. Ce fut épuisant pour tout le monde mais, et c’est peut être du fait des Québécois, personne ne râlait quand il fallait repasser sur un certain nombre de choses (chapeau aux modeleurs pour le nombre incroyable de retake techniques). Souvent nous comprenions tous pourquoi tel ou tel chose devait être modifié. L’ambiance générale était très bonne malgré les journées de travail éreintantes (c’est peut-être lié). Ça été ça pendant vraiment longtemps, doute-investigation-stresse-correction-test-avance.</p>

<h4>Tout override&nbsp;!</h4>

<figure style="margin: 0 auto; display: table;"><img alt="guerilla.png" class="media" src="media/457ea340.guerilla.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/guerilla.png" /></figure>

<blockquote>Note&nbsp;: Il faudra que je prenne le temps, un jour, d’expliquer le principe du lighting par override. Bien que cette pratique soit très utilisée en long-métrage et série, tout le monde ne la connaît pas nécessairement.</blockquote>

<p><em>Guerilla</em> est un superbe outil, je le crie à qui veut l’entendre. La logique mise en place sur <em>Ballerina</em> a été la suivante&nbsp;:</p>

<p>Un RenderGraph initial pour mettre les paramètres par défaut. Par exemple, appliquer un shader gris-neutre sur tous les objets, assigner un shader de curve sur les objets de type curve, modifier des paramètres en fonction des tags assignés sur les objets, etc.</p>

<p>Le second RenderGraph était appliqué par asset. Ce sont les RenderGraphs que les artistes du lookdev faisaient et publiaient. Il assignait des séquences d’UDIM par attribut du shader (spéculaire, couleur diffuse, etc.) et modifiait les paramètres ne nécessitant pas de textures. Le tout en s’accrochant aux tags des objets.</p>

<p>Enfin venaient les RenderGraphs du Lighting séparés en trois&nbsp;: Un pour la séquence, un pour un groupe de plan et le dernier pour le plan.</p>

<p>Chacun de ces RenderGraph changeait (overridait) les paramètres du RenderGraph précédent.</p>

<p>Cette liste ne s’est pas faite d’un coup. Par exemple, les lighters ont longtemps travaillé qu’avec un RenderGraph de plan unique, les RenderGraph de séquence sont arrivés plus tard, tout comme les RenderGraph de groupe de plan arrive quasiment à la fin.</p>

<h3>Recrutement des TDs</h3>

<figure style="margin: 0 auto; display: table;"><img alt="modus_fx_logo.jpg" class="media" src="media/9606fa69..modus_fx_logo_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/logos/.modus_fx_logo_m.jpg" /></figure>

<p style="text-align: center;">Ceci n’est pas un fournisseur d’accès internet. <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>On a eu de la chance (dira-t-on), Modus FX a <a href="http://www.3dvf.com/actualite-9002-modus-fx-ferme-ses-portes-une-centaine-d-employes-licencies.html" hreflang="fr" title="Modus FX ferme ses portes, une centaine d'employés licenciés">fermé ses portes</a> au moment où on cherchait des TDs. On c’est donc récupéré énormément de TD expérimentés. Avec le recul, il aurait été difficile de sortir le pipeline sans leur aide, ils ont vraiment fait du bon boulot. Chaque TD avait la responsabilité d’un (ou plusieurs) département mais nous codions dans le même repo git avec les mêmes standards de code. Il était d’ailleurs vraiment impressionnant de pouvoir sauter dans le code de ses collègues sans avoir l’impression d’être largué. Cette approche (très rigide à l’entrée) a réussi à créer une cohésion entre les TD qui a vraiment permise une «&nbsp;avancée de front&nbsp;». Au passage&nbsp;: <a href="https://www.python.org/dev/peps/pep-0008/" hreflang="en">PEP 8</a> est un compromis, pas un standard.</p>

<p>Mon travail concernait principalement le lookdev. Nous avons utilisé <em><a href="https://www.foundry.com/products/mari" hreflang="en">Mari</a></em> et <em>Guerilla</em>. Comme la hiérarchie n’était pas fixe, nous nous somme appuyé sur les tags. C’est un peu fastidieux et contre productif au premier abords, car les graphistes doivent placer leurs tags dans Maya, exporter leur abc et faire leur surfacing dans <em>Guerilla</em>. Mais il faut bien garder à l’esprit que la hiérarchie changeait constamment à cette période (rien n’était encore décidé en rig) il fallait donc trouver un moyen au lookdev de livrer sans dépendre d’autres département. Ça été, je pense, une bonne décision.</p>

<p>Le travail consistait grossièrement à travailler dans <em>Mari</em>, exécuter un script qui sortait en <em>.tif</em> les UDIMs des channels sélectionnés, puis faire un Update dans <em>Guerilla</em> qui transformait ses mêmes <em>.tif</em> en <em>.tex</em> pour le rendu. C’était fastidieux et nous aurions pu améliorer la détection des updates pour éviter beaucoup de temps perdu, notamment lors de petites retakes. Notez que seul les <em>.tex</em> étaient publiés. Cela n’a pas posé de soucis en pratique.</p>

<h3>Builder</h3>

<p>Le builder (layout), c’est la colonne vertébrale d’un pipeline d’un film. Il permet la relation entre les informations de plan en base de donne et les logiciels. Un des gros chantiers de tout long-métrage c’est la capacité à construire les plans, si possible dans n’importe quel logiciel. Je ne me suis pas occupé du Builder du côté de la base de donne, mais de son intégration dans <em>Guerilla</em>. C’est d’ailleurs quand les plans ont commencés à se builder sans trop de soucis que j’ai réellement pris confiance en notre capacité à sortir le projet. Tant que vous n’avez pas le moyen de reconstruire des plans, à jour, en partant de rien, vous êtes dans une situation difficile (et si vous avez des équipes qui travaillent sur des plans avant d’avoir cet outil vous êtes franchement dans la m… Ouai nan… Faites un builder avant toute chose…). Du builder découla les quality check d’animation (Ambiant Occlusion) et leur automatisation sur la render farm.</p>

<h3>Instanciation implicite</h3>

<p>Une fois que vous avez un builder, vous construisez des plans de plus en plus gros, jusqu’à ce qu’ils ne rendent plus. L’intérieur de l’opéra (entre autre) montait anormalement en mémoire. On a donc creusé un peu pour se rendre compte que les transforms des objets était automatiquement freeze au modeling (pour une question de rig si je me souviens bien). Cela avait pour effet, lors de l’export en alembic, de casser les instances implicites.</p>

<h4>C’est quoi</h4>

<p>Le principe est simple&nbsp;: Quand deux shapes sont identiques, on considère qu’elles sont en instance. Ce qui définit une shape c’est (entre autre) la position de ces points par rapport à son centre. Si chaque objet a un centre différent, leurs points, une fois dans l’alembic, sont à des positions différentes. Ainsi, si vous dupliquez mille fois un objet, que vous écrasez les transforms de tous les objets, chaque objet a son centre au centre du monde, et donc, chaque objet a un centre différent de celui du voisin, et donc, tous les point qui compose un objet sont différents de ceux du voisin.</p>

<blockquote>
<p>Note&nbsp;: Maya fait une distinction entre le centre géométrique et le point de pivot. Il est donc possible de déplacer le point de pivot sans déplacer le centre géométrique.</p>
</blockquote>

<h4>Comment résoudre ça</h4>

<p>On était très avancé en modeling, il fallait une solution simple sans trop d’intervention humaine. L’approche prise est pragmatique et pas super mathématique&nbsp;: On avait remarqué que la topologie des objets étaient conservés. Nous avions donc la garantie que les deux premières arêtes connectées au premier point étaient les même sur tous les objets. S’ensuit un peu d’algèbre linéaire (produit vectoriel, scalaire, merci PyMEL) et on avait une algo capable de récupérer les objets qui pouvaient être implicitement instancié et récupérer un centre identique. Une UI plus tard les modeleurs pouvaient repasser sur les gros sets pour récupérer l’instanciation implicite des objets en quelques cliques.</p>

<p>Il n’empêche que malgré cet outil, il fallait quand même rouvrir tous les assets pour repasser dessus. Un travail assez laborieux et ingrats. Il y eu quelques tensions autour de ça (parce qu’il a déjà fallu repasser sur presque tous les assets auparavant pour des histoires de hiérarchie). J’avoue avoir pas mal forcé auprès de la prod pour que ce soit fait. Ce n’est jamais très apprécié de faire du forcing de la sorte, mais je pense que tout le monde a bien compris qu’on allait avoir de gros soucis si on ne le faisait pas.</p>

<h4>Effet indirect</h4>

<p>On a remarqué qu’en plus de diminuer drastiquement la consommation mémoire de <em>Guerilla</em>, les gros assets, en particulier les buildings, se chargeaient bien plus vite et étaient bien plus fluide à la navigation dans <em>Mari</em>.</p>

<h3>Hiérarchie des assets</h3>

<p>Comme je vous le disais, le rig n’était pas défini. Il a donc fallu repasser sur tous les assets pour conformer leur hiérarchie. On a donc fait des petites boucles qui ouvraient tous les assets du film pour passer un sanity check et savoir exactement quels assets devaient être rouvert. Mais on est allez plus loin&nbsp;: Avec les modeleurs, on a identifié les cas de “correction scriptable” pour le faire automatiquement. Après que les modeleurs aient teste la méthode sur quelques assets, on envoyait ça sur tous les assets de la prod. Si envoyer une boucle qui ouvre tous les assets pour faire passer un sanity check n’engage à rien. Le fait de modifier, en batch, des centaines d’assets est extrêmement risqué. On a fait la procédure et le suivi à deux, l’un à coté de l’autre pendant plusieurs jours ce qui permettait une réflexion et une remise en question continue (ne jamais laisser une seule personne faire du batch qui modifie les scènes toute seul). Car derrière l’apparente simplicité, le risque de casser des centaines d’asset est réel. On a donc fait ça avec le sérieux et le professionnalisme qui s’imposait, on a relu plusieurs fois notre code, on a fait des tests et forcement, on a tout pété! <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>Bon, on a été malin, le commentaire de publication utilisé pour mettre à jour les assets contenait un mot très particulier. Il a donc été assez simple de rechercher les publications puis de les omettre dans Shotgun. Mais bon, je me rappelle qu’à ce moment, l’état d’esprit de la production c’était&nbsp;: <img src="media/57cd5fc6.alkap.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/alkap.gif" alt=":mitraille:" class="smiley" /> <img src="media/9c0a1b5a.as253.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/as253.gif" alt=":enerve:" class="smiley" /> <img src="media/61b0b317.tuComprendRien.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/tuComprendRien.gif" alt=":tuComprendRien:" class="smiley" /> <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /> <img src="media/6e363cce.casseTeteMur.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/casseTeteMur.gif" alt=":casseTeteMur:" class="smiley" /> <img src="media/53728ad7.nervous.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nervous.gif" alt=":nervous:" class="smiley" /> <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>Un petit fix, on a relancé la boucle et c’était bon… <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>Hair</h3>

<p>Les hairs ont été faits avec <em>Yeti</em>. Du fait des autres chantiers, les hairs sont restés longtemps sans personne (en R&amp;D) pour leur assurer un pipeline propre. On savait qu’on allait le payer et ça n’a pas raté. La liste des problèmes rencontrés est très longue et, il faut bien l’avouer, assez misérables. Le rig n’était pas recentre, c’est-à-dire que plus les personnages étaient loin du centre, plus la géométrie avait des problèmes de précision (J’entends souvent que «&nbsp;c’est le B-A BA&nbsp;» mais je n’ai jamais vu son application sur un long. Le rigs étant souvent trop complexe).</p>

<p>En pratique les soucis de précision n’auraient pas dû être un problème car dans tous les cas, nous recentrions les scènes. C’était sans compter sur la boite noire qu’était <em>Yeti</em>. Nous n’avons jamais eu la confirmation de quoi que ce soit (les échanges de mail étant assez improductif) mais je soupçonne que <em>Yeti</em> essai de se rattacher à la surface d’une distance au prorata de la densité de point. C’est-à-dire que plus il y a de point, moins <em>Yeti</em> va chercher la surface. Le problème que cela posait était le suivant&nbsp;: Afin de pouvoir générer un vecteur de motion blur, chaque point de chaque courbe qui compose les hairs doit être présent deux fois&nbsp;à t et t+0.5. Sauf que si <em>Yeti</em> n’arrivait pas à retrouver une surface lors d’un des sample, il ne calculait pas la courbe, le nombre de point devenait donc inconsistant entre t et t+0.5. Sans un nombre consistant de point, <em>Guerilla</em> ne pouvait générer les motion vecteur, il ne lui restait donc qu’à cacher la partie des hairs qui posait problème en affichant un warning. La solution? Recentrer les hairs avant l’export de la simulation, sauvegarder l’offset et l’appliquer dans <em>Guerilla</em> avant rendu B-D. Je vous passe les détails mais ça été un beau bordel. Toutefois, le truc cool en code c’est qu’à force d’effort et d’acharnement, ça finit par marcher mais ça été long et fastidieux.</p>

<h3>La végétation</h3>

<p>Une autre de mes taches sur le projet a été de faire un outil pour gérer la végétation, en particulier les arbres et les buissons. La première question est pourquoi ne pas utiliser <em>Yeti</em> ? C’est difficile à expliquer si on ne sait pas comment fonctionne un pipeline. <em>Yeti</em> génère des <em>.fur</em> tout-en-un qui sont “déroulés” dans <em>Guerilla</em> au moment du rendu. Cette étape est très longue, la mémoire prise par <em>Yeti</em> lors de la génération des primitives est énorme, la bounding box est globale, l’instanciation compliquée et surtout&nbsp;: Une mise à jour d’un des assets nécessite un reexport du système de <em>.fur</em> entier. Dans une logique de pipeline d’animation, chaque département n’est supposé publier que le minimum de ce qui est nécessaire. Dans le cas de la végétation seul des informations de position/rotation/échelle ainsi que l’id de l’asset à placer (avec ses attributs de variations) sont nécessaires. Ainsi, dans <em>Guerilla</em>, on amène l’alembic contenant uniquement les positions des assets, la géométrie source de l’asset (que l’on cache), un script pour lier chaque position à la source et c’est terminé. On avait quelques soucis de performances, isolé dans ticket, résolu par les gars de <em>Mercenaries</em> (les développeurs de <em>Guerilla</em>) dans la semaine et on avait un système d’instance très léger, qui rendait immédiatement.</p>

<p>L’outil a été un peu long à écrire, mais on l’a étendu à un certains nombre de plans, notamment pour placer des personnages en instance sur les vues d’ensemble.</p>

<p>Mon seul regret de technophile à poil dur fut la demande de diminuer le nombre d’arbres “parce qu’il y en avait trop” alors qu’on avait virtuellement aucune limite.</p>

<h3>Lighting</h3>

<p>La production a fait du bon boulot, car Le Petit Prince venait de se terminer et on a pu embaucher bon nombre de lighters déjà formé sous <em>Guerilla</em>. Je me rappelle avoir présenté le pipeline à une juniore qui, après m’avoir écouté déclarer mon amour pour les overrides, me fit comprendre qu’elle connaissait déjà tout ça. Tous les lighters étaient à l’aise avec <em>Guerilla</em>. Ils avaient travaillé avec une ancienne version pendants un long-métrage entier et découvrait également que beaucoup de leurs soucis avaient été résolus depuis.</p>

<h4>Publier</h4>

<p>On a choisi de versionner les séquences d’image de manière granulaire, à l’AOV (pass/layer/aov/&lt;version&gt;). Comme nous avions beaucoup d’AOV, il y avait énormément de versions à publier à chaque fois. On a fait une UI tout-en-un pour simplifier le travail de gestion des rendus des lighter (et aussi éviter qu’ils aillent se perdre et tout casser dans la hiérarchie de dossier :P). Sous le capot, l’interface était threadé à mort. Il fallait, en effet, s’assurer que le lighter voit, quand une séquence était incomplète, quelles images manquaient (et il y avait beaucoup de séquences). Le gros problème venait de <em>Shotgun</em> qui lâchait parfois prise et bloquait les publications sans raisons apparente, il fallait donc reprendre là ou il s’était arrêté (heureusement les cas d’arrêt pendant la copie d’une séquence d’image était rare).</p>

<h4>Override à la séquence, par groupe de plan, puis par plan</h4>

<p>Il est intéressant de constater qu’une des feature du pipeline qui permet d’économiser énormément de temps n’est arrivé que lors des six/sept derniers mois du projet. C’est quelque chose qui a été discuté très tôt, avant même l’arrivée du modeling. C’est un des trucs dont je suis le plus fier et qui a réellement augmenté la vitesse de sortie des plans. Le principe est de pouvoir overrider à la séquence mais surtout par groupe de plan. Dans la pratique, le lighter pouvait grouper les plans d’une même séquence similaires (exemple&nbsp;: champ/contre-champ) et appliquer des overrides pour chacun des groupes puis de propager sur toute la séquence. Ainsi, les lighter ne travaillaient plus au plan mais à la séquence. Les seniors ont rapidement sauté dessus. De manière surprenante, certains juniors ont également vite emboîté le pas. Ce n’était pas parfait, les rigs de light devaient toujours être propage manuellement et la UI de gestion des groupes n’était pas terrible, mais les séquences passaient en revu en entier très rapidement après avoir été commencé. La vitesse gagne en lighting sur certaines séquences simples était vraiment énorme.</p>

<h4>Shot group</h4>

<p>Il y avait deux façons de publier un rendergraph de lighting&nbsp;: À la séquence, et au plan. Le rendergraph de plan overridant le rendergraph de séquence. L’idée était que, quand un graphiste commençait une séquence, il remonte toutes les modifications nécessaires sur toute la séquence dans le rendergraph de séquence pour ne laisser dans le rendergraph de plan que les modifications spécifiques au plan. C’est une approche assez conventionnelle quand on travaille avec des overrides, car bien souvent, le pipeline permet de publier des choses&nbsp;à la séquence ou au plan. Mais elle laisse un trou énorme&nbsp;: Que faire quand on souhaite éclairer deux plans similaires. <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>Si par exemple votre séquence se compose de quelques plans d’intro (souvent large), puis d’un enchainement de champ/contre champ, identique en termes de lighting, puis trois plans de sortie, vous avez 4 groupes de plan&nbsp;:</p>

<ul>
	<li>intro (2 plans)</li>
	<li>part_1_char_1 (4 plans)</li>
	<li>part_2_char_2 (5 plans)</li>
	<li>outro (3 plans)</li>
</ul>

<p>Chaque studio semble faire sa tambouille mais après quelques semaines de travail, on a commencé à réfléchir a un moyen de publier des choses «&nbsp;par groupe de plan&nbsp;». Et ne croyez pas que c’est évidant. Sur un plan purement ingénierie, cette approche est «&nbsp;anti-hiérarchique&nbsp;» dans un pipeline, car si la hiérarchie «&nbsp;studio/projet/séquence/plan/cam&nbsp;» est fixe, les groupes de plan peuvent être défini différement suivant qu’on est en lighting ou en animation (ou autre). Il s’agissait donc d’une structure par séquence (il fallait bien la mettre quelque part) non connu à l’avance, donc difficilement structurable.</p>

<p>Les lighters avait donc moyen, par séquence, de faire des groupes de plan. Ils visualisaient la séquence et commençait déjà à réfléchir comment ils allaient publier chacun de leur rendergraph.</p>

<p>Au moment de construire le plan, on faisait récupérait le rendergraph publie a séquence, au plan, puis on demandait le groupe dans lequel était le plan en cours, puis on récupérait le rendergraph publie dans ce groupe. Les rendergraph s’enchainaient dans cet ordre&nbsp;: «&nbsp;sequence/shot group/shot&nbsp;».</p>

<p>Cette méthode est arrive très tard sur le film (je dirais le dernier quart en termes de planning) mais elle a permis quelque chose d’énorme&nbsp;: Les lighteurs pouvaient prendre et éclairer des séquences complètes. Ça prenait un peu plus de temps de départ (compare a un éclairage au plan) mais quand ils avaient fini, ils envoyaient toute leur séquence en rendu et l’itération se faisait par séquence.</p>

<p>Un autre effet fut que l’éclairage était beaucoup plus cohérent entre les plans. Très souvent, les éclairages au plan tendent à casser l’homogénéité de la séquence. Ce sont les lead qui veillent constamment a l’homogénéité de l’ensemble (éclairage, couleur, etc.), mais malgré ça, ça se voit toujours. Le fait de repousser la modification par plan aussi loin que possible permettait de sucrer une bonne partie des retakes d’homogénéité. Au final, le rendergraph de plan était quasiment vide d’information d’éclairage.</p>

<p>J’avoue ne jamais avoir vu de système semblable aussi pousse. Bien entendu, ce n’est pas parce que je n’en ai pas vu que ça n’existe pas. Mais bien souvent ce sont des outils de propagation qui permettent d’envoyer l’éclairage d’un plan dans un autre plan, pas une publication entre la séquence et le plan.</p>

<h3>Render farm</h3>

<p>Disons-le clairement, la gestion de la render farm n’était vraiment (mais alors vraiment) pas quelque chose qui m’attirait. Et pourtant, ça été très intéressant. Et pour cause, la render farm ne concerne pas uniquement le rendu. C’est de la puissance disponible pour de l’automatisation de tâche. Et on en a bien usé:</p>

<ul>
	<li>Génération des alembic en sortie du modeling, de l’animation et des fx.</li>
	<li>Export automatique des séquences de <em>.fur</em> (<em>Yeti</em>) en sortie du département d’animation.</li>
	<li>Build et calcul des ambiant occlusion pour le contrôle de qualité des animations.</li>
	<li>Trigger lors des validations.</li>
	<li>Mise à jour automatique des plans de lighting avant rendu.</li>
	<li>Build et rendu des precomps.</li>
	<li>Et bien entendu&nbsp;: Rendu des images</li>
</ul>

<p>On a utilisé <em>Qube</em>. Un truc qu’il faut savoir concernant les gestionnaires de ferme de rendu c’est le “bruit réseaux” qu’ils produisent. Le nombre de machine augmentant (certaines n’étaient pas situe dans la boite mais à plusieurs une centaine de mètres du studio), il peut arriver qu’une quantité non négligeable des accès réseau ne soit prise que par le gestionnaire de ferme de rendu qui communique avec ses clients. Le problème apparaît lorsqu’il y a congestion ou chaque client a besoin de contacter le serveur sans que ce dernier ne soit capable de répondre, s’ensuit un effondrement des performances générales. Certains gestionnaires, plein de fonctionnalités qui se veulent pro-actifs (vérifier que toutes les images sont sorties, qu’elles ne sont pas corrompues, etc.) sont capables, de par leur activité, minime mais intrusive, de mettre à terre un réseau déjà bien occupé à charger des gigas de données. C’est un détail à prendre en compte quand on commence à monter en charge. Au-delà de ça, Qube a une API assez soviétique sur les bords, on sent le logiciel mature, stable et tu le payes par une API complexe.</p>

<h3>Matte Painting</h3>

<p>On ne peut pas vraiment parler de pipeline pour le département de matte painting, mais de support. C’était rafraîchissant&nbsp;: Transfert de caméras de projection entre <em>Guerilla</em> et <em>Nuke</em> (avec ce sentiment de satisfaction quand on attend enfin le <em>pixel-perfect</em>). J’ai également pu constater à quel point <em>Nuke</em> était mauvais en 3D et à quel point un “vrai” logiciel de matte painting manquait. Je ne parle bien évidemment pas pour la peinture digitale mais pour la gestion de la 3D (projection et manipulation de la géométrie).</p>

<h3>Commentaire de plan</h3>

<p>Sur un long-métrage, chaque plan a une histoire. Entre le nombre de département qui passe dessus (modeling, layout, animation, rendu, compositing) et les allez-retours de validation entre chaque étape, chaque personne ayant travaille sur le projet a une d’histoire à raconter. En revoyant le film, je me suis dit que j’avais envie de commenter les plans. C’est parti&nbsp;!</p>

<p style="text-align: center;"><a class="media-link" href="media/daa8ca16.post_mortem_ballerina_comment_001.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_001.jpg"><img alt="" class="media" src="media/833447c1..post_mortem_ballerina_comment_001_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_001_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Voici un plan typique avec des arbres et de l’herbe. Je pense qu’il y a eu une difficulte de communication autour du placement des arbres. Aucun décors breton (et français d’une manière générale) ne ressemble a ça, les arbres sont supposés délimiter les champs alors qu’ils sont placés de manière très aléatoire ici. Je soupçonne que l’esthétisme a été privilégié mais du-coup ça manque un peu de vie. Autre remarque sur Yeti&nbsp;: On l’a aussi utilise pour place de branches et des cailloux, mais on se retrouvait avec des bounding box énormes pour finalement peu de géométrie ce qui a pas mal ralenti le rendu.</p>

<p style="text-align: center;"><a class="media-link" href="media/448b5076.post_mortem_ballerina_comment_002.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_002.jpg"><img alt="" class="media" src="media/d81ff8bc..post_mortem_ballerina_comment_002_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_002_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Le décor de l’orphelinat, l’un de mes préférés.</p>

<p style="text-align: center;"><a class="media-link" href="media/4d46d76e.post_mortem_ballerina_comment_003.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_003.jpg"><img alt="" class="media" src="media/e123cae1..post_mortem_ballerina_comment_003_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_003_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Il est à noter que cette pièce est utilise à la fois pour la cuisine et pour le dortoir. Les lits remplaçant les tables. Ça passe super bien dans le film et ça a permis de se focaliser sur une seule pièce.</p>

<p style="text-align: center;"><a class="media-link" href="media/23622b14.post_mortem_ballerina_comment_006.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_006.jpg"><img alt="" class="media" src="media/330d4d94..post_mortem_ballerina_comment_006_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_006_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Je ne peux plus vérifier, mais je crois que ce plan a été rendu dans les derniers, quand la farm était quasi vide et mettait 14&nbsp;h l’image <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /> . Si je me rappelle bien, on savait que c’était lié à tous les rochers et branches par terre, mais on a décidé de ne pas trop chercher plus loin.</p>

<p style="text-align: center;"><a class="media-link" href="media/47c6ec15.post_mortem_ballerina_comment_008.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_008.jpg"><img alt="" class="media" src="media/95f2cf3f..post_mortem_ballerina_comment_008_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_008_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>La boite à musique, ou comment un plan totalement anodin peut rendre fou. Dans Maya les sous frames de l’animation étaient parfaites, mais une fois exporte en alembic puis réimporte, le motion blur explosait certaines pièces (notamment le <a href="https://fr.wikipedia.org/wiki/Trisk%C3%A8le" hreflang="fr">triskèle</a>). C’était devenu un <em>running gag</em>… Je ne sais même plus comment on a fini par résoudre le souci, mais je ne serais pas surpris qu’on ait totalement désactivé le motion blur 3d sur ce plan.</p>

<p style="text-align: center;"><a class="media-link" href="media/39e256cd.post_mortem_ballerina_comment_009.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_009.jpg"><img alt="" class="media" src="media/36b63851..post_mortem_ballerina_comment_009_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_009_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Les escaliers sont souvent une tanne à rendre, mais je trouve que l’épique lighting s’en est sorti à merveille.</p>

<p style="text-align: center;"><a class="media-link" href="media/ec5aa327.post_mortem_ballerina_comment_010.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_010.jpg"><img alt="" class="media" src="media/73f03d9d..post_mortem_ballerina_comment_010_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_010_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>J’adore cette séquence de nuit. Le fait d’avoir une seule source principale de lumière (celle de la moto) donne à la séquence un aspect dramatique. Encore une fois, je pense qu’on a trop négligé le placement des arbres, ça manque de vie.</p>

<p style="text-align: center;"><a class="media-link" href="media/dc4919ce.post_mortem_ballerina_comment_011.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_011.jpg"><img alt="" class="media" src="media/c4003ad5..post_mortem_ballerina_comment_011_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_011_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Notez le renfoncement de la route sur toute cette séquence. L’objectif, vous vous en doutez, est d’éviter d’avoir à travailler l’horizon sur l’ensemble des plans.</p>

<p style="text-align: center;"><a class="media-link" href="media/c75a9506.post_mortem_ballerina_comment_012.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_012.jpg"><img alt="" class="media" src="media/d933e3a1..post_mortem_ballerina_comment_012_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_012_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Et voila un keyshot. Le principe d’un «&nbsp;keyshot&nbsp;» (ou «&nbsp;plan-clef&nbsp;») sur un long-métrage (et en animation 3d d’une manière générale) est de valider l’éclairage type d’une séquence (couleur, ombres et tout ce qu’il est possible de définir dès cette étape en fait). Ils sont donc souvent plus travaillés que les autres et permettent aussi de mettre le doigt sur les problèmes technique avant d’entamer le travail à la séquence. Ce sont souvent les seniors qui font ses plans. L’objectif est de se représenter l’intégralité de la séquence et comment tous les plans vont être fait et de «&nbsp;passer la main&nbsp;» aux graphistes juniors qui (en principe mais là on rêve un peu) ajuste un éclairage donne sans se prendre la tête.</p>

<p style="text-align: center;"><a class="media-link" href="media/2c7a102a.post_mortem_ballerina_comment_013.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_013.jpg"><img alt="" class="media" src="media/8753ebac..post_mortem_ballerina_comment_013_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_013_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Le train a été utilisé pour faire quelque chose d’assez peu courant (longue explication en approche): Sur ce projet, le layout avait la possibilité de bouger les contrôleurs de certains objets des assets pour éviter la répétition. Un bon exemple sont les volets des maisons, les portes, les tables, etc. Le problème c’est que du-coup, les assets en questions ne sont plus vraiment en position d’origine ce qui est assez problématique, car vous ne pouvez plus simplement considérer, dans votre base de donne, qu’un shot contient une instance d’asset place a tel endroit, il faut aussi avoir la liste des modifications de placement quelque part. Très souvent (enfin j’ai vu ça partout jusqu’à présent), la solution retenue face à ce dilemme est&nbsp;: «&nbsp;Si ce n’est pas juste un déplacement du contrôleur global, c’est de l’animation&nbsp;» et donc, c’est exporté avec l’alembic d’animation du plan (qui contient les personnages et les props déplacés). Mais avouez que c’est bête d’imposer l’export par plan d’un asset au complet quand seul un des objets qui le compose (un volet, une porte, etc.) est modifie… On a donc décidé de se lancer dans une quête un peu folle consistant à récupérer les modifications de placement des sous objets au layout pour pouvoir les appliquer sur l’asset original lors de la construction du plan au rendu. Pour être honnête, on eut pas vraiment le choix, le layout avait fait un gros travail de placement (il y a des contrôleurs, ils les bougent, c’est normal) quasiment plus aucun asset ne correspondait a sa position d’origine… Il fallait donc, pour les assets en questions, stocker la position des objets qui ne sont pas à leur placement d’origine. Sauf qu’il peut y avoir une différence entre le placement d’un contrôleur (que le layout déplace) et le placement de la géométrie qu’il contrôle. Le rig garantie (en principe, mais ce n’est pas le problème ici) que la relation de position entre un contrôleur et la géométrie qu’il contrôle est toujours la même. Mais il ne garantit pas que l’origine de la géométrie en question soit constante entre les versions de rig. Pas grave me diriez-vous, c’est pas le truc qui change souvent… Et devinez quoi&nbsp;? Oui, c’est ce qui c’est passé, l’origine des géométries bougeait entre les versions de rig <img src="media/ac1b2cba.nexath.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nexath.gif" alt=":smileFou:" class="smiley" /> . Rappelez-vous, le rig n’a été défini que très tard sur le projet et chaque choix se confrontait a ce qui était déjà en place. On ne pouvait donc pas s’appuyer sur la position des géométries mais uniquement sur celle des contrôleurs… Bon, on a les positions des contrôleurs modifiant un asset au plan, mais comment je connais la relation avec la géométrie&nbsp;? C’est ici que les histoires sérieuses de sanity check on commencées. Il a fallu être extrêmement rigoureux sur la façon dont les contrôleurs «&nbsp;non-déformant&nbsp;» étaient connectées aux objets qu’ils contrôlaient. De sorte qu’il n’y eut qu’une simple matrice (intitulée sobrement <em>offset matrice</em> ou «&nbsp;matrice de décalage&nbsp;») à appliquer sur la position en espace monde du contrôleur pour obtenir la position en espace monde de la géométrie (matrice du contrôleur + offset matrice = position identique dans Maya et Guerilla&nbsp;!). Il fallait donc stocker, par publication de rig, l’offset matrice de chaque contrôleur «&nbsp;non-déformant&nbsp;» puis l’utiliser lors de l’import d’un asset dans un plan. Mais attendez&nbsp;! Attendez&nbsp;! C’est même pas fini en plus lol&nbsp;! Certains objets nécessitaient une hiérarchie de contrôleurs non-déformant et il fallait que mon bordel fonctionne avec eux aussi&nbsp;! XD Il fallait donc stocker des numéros indiquant la profondeur du contrôleur pour appliquer les offset matrice dans le bon sens&nbsp;! <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /> Le wagon était le premier assez du genre. La porte du wagon étant coulissante et compose d’un second objet (la serrure de la-dite porte). Je me rappelle de ma scène Guerilla que je passais mon temps a builder en tournant mon wagon et les contrôleurs de la porte et de la serrure dans tous les sens, a tous les niveaux de la hiérarchie en croisant les doigts pour obtenir le même résultât. J’ai du y passer une ou deux semaines à plein temps en mode chien méchant mais ça été super robuste car c’est une partie du code que je n’ai plus du tout touche par la suite.</p>

<p style="text-align: center;"><a class="media-link" href="media/3896697a.post_mortem_ballerina_comment_015.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_015.jpg"><img alt="" class="media" src="media/05c036b0..post_mortem_ballerina_comment_015_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_015_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Cette séquence dans le wagon me fait toujours rire car Victor allume et éteint une lampe a huile en la touchant vaguement et certaines pommes sont posées sur des surfaces plates sans bouger alors que les plans subissent un <em>shake cam</em> pour simuler le mouvement des wagons <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 style="text-align: center;"><a class="media-link" href="media/eb73dafb.post_mortem_ballerina_comment_017.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_017.jpg"><img alt="" class="media" src="media/72dc8a2f..post_mortem_ballerina_comment_017_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_017_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Éclairer le contenu d’une boite fermée… Tout un programme. Si je me souviens bien les planches du fond et du dessus n’étaient pas visible des lights. Vous pouvez le remarquer sur les cheveux et le bras de Félicie. Les pommes étaient faites en particule. Je me rappelle avoir bossé sur un moyen de faire des variations de teinte sur le lookdev des pommes suivant un attribut de particule. Un effet subtil de variation de teinte.</p>

<p style="text-align: center;"><a class="media-link" href="media/0b4a9e29.post_mortem_ballerina_comment_018.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_018.jpg"><img alt="" class="media" src="media/a1c1ea8b..post_mortem_ballerina_comment_018_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_018_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Un des <em>money shot</em> du film. Un <em>money shot</em> (qui peut se traduire de deux façons suivant qu’on l’achète ou suivant qu’on le budget <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /> ) est un plan qui est caractérisé par le cout nécessaire a sa fabrication et par l’effet <em>Woaw&nbsp;!</em> qu’il est suppose engendrer chez le spectateur. Celui-ci part du <a href="https://fr.wikipedia.org/wiki/Pont_d%27I%C3%A9na" hreflang="fr">pont d’Iéna</a>, passe entre les fondations de la tour Eiffel puis fini sur une vue d’ensemble. C’était LE plan test du builder. Beaucoup de bâtiment, beaucoup de géométrie, beaucoup de personnages, beaucoup de spéculaire, beaucoup de textures, beaucoup de matte painting, etc. Paradoxalement, le fait de voir venir ces plans de loin (dès le layout tu te fais une idée de la difficulté) fait qu’au final il n’a pas pose de problèmes majeurs. Les problèmes vraiment contraignant arrivent souvent sur des plans totalement anodins.</p>

<p style="text-align: center;"><a class="media-link" href="media/b7d1898c.post_mortem_ballerina_comment_020.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_020.jpg"><img alt="" class="media" src="media/3054846e..post_mortem_ballerina_comment_020_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_020_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Celui-là je ne mets pas parce qu’il est joli ( <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" /> ) mais pour la petite histoire&nbsp;: Pour une raison qu’on ignore totalement, la texture des bouées (sur les bords du bateau) popait au rendu. On a jamais compris pourquoi et malgré tous nos tests (hashing des textures, hashing des uvs, compression, etc.) on a pas eu le temps de régler le souci suffisamment rapidement. Du-coup (et après discussion) elles ont été supprimées du bateau. Notez que ce n’est pas la règle. On ne supprime pas un truc à chaque fois qu’il nous embête, simplement qu’il faut constamment prioritiser les choses à faire, et parfois il faut trancher. Mais ce n’est jamais fait de gaité de cœur.</p>

<p style="text-align: center;"><a class="media-link" href="media/ccc33bcb.post_mortem_ballerina_comment_021.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_021.jpg"><img alt="" class="media" src="media/bffa1512..post_mortem_ballerina_comment_021_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_021_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce plan (et la séquence d’une manière générale) fut le plan de test. On y est reste longtemps pour affiner nos méthodes d’exports d’alembic, de rendu sur la farm, déterminer quels AOVs on sort… Bref, pousser le pipeline pour faire, ce que j’appelle, la première boucle (un pipeline qui marche du début jusqu’au plan final composite). À l’époque il n’y avait pas de lighters ni de compositeurs, seul les superviseurs de ces deux départements étaient présents. C’est, je trouve, un des plans les plus travaille du film. La subtilité du rendu du sol ne se retrouve sur aucun plan. Il est aussi moins sature que le reste des plans.</p>

<p style="text-align: center;"><a class="media-link" href="media/885bd76f.post_mortem_ballerina_comment_022.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_022.jpg"><img alt="" class="media" src="media/1f9ddcfb..post_mortem_ballerina_comment_022_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_022_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Le plan qui suit. Notez la qualité du SSS de la peau, assez différente du reste du film.</p>

<p style="text-align: center;"><a class="media-link" href="media/a73fe6db.post_mortem_ballerina_comment_023.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_023.jpg"><img alt="" class="media" src="media/31a3bfa3..post_mortem_ballerina_comment_023_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_023_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Juste pour préciser qu’il n’existe aucun axe dans Paris qui permet cette vue sur l’opéra. <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 style="text-align: center;"><a class="media-link" href="media/c768675d.post_mortem_ballerina_comment_024.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_024.jpg"><img alt="" class="media" src="media/d4577fd5..post_mortem_ballerina_comment_024_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_024_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Encore un plan de cette séquence que je trouve magnifique. C’est exactement comme Paris&nbsp;: Des pavés luisants avec un petit brouillard de fond. Ce cadrage est repris plusieurs fois dans le film mais le rendu n’a rien à voir.</p>

<p style="text-align: center;"><a class="media-link" href="media/c22ca2ba.post_mortem_ballerina_comment_025.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_025.jpg"><img alt="" class="media" src="media/f4d80d5f..post_mortem_ballerina_comment_025_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_025_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Les pavés sont 100&nbsp;% displacement. On a essayé en normal map et tout mais vers la fin du plan, le sol apparaissait beaucoup trop plat.</p>

<p style="text-align: center;"><a class="media-link" href="media/36832d62.post_mortem_ballerina_comment_026.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_026.jpg"><img alt="" class="media" src="media/9460b837..post_mortem_ballerina_comment_026_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_026_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Anecdote intéressante, le temps de rendu de l’AOV des pavés sur ce plan prenait énormement de temps car, étant en displacement ET de biais, les rayons de la caméra faisait des tests d’intersections sur beaucoup de triangles avant d’en toucher un. Ce n’est pas forcement une bonne tactique d’avoir de gros temps de rendu sur des plans comme ceux-là qui risquent de passer beaucoup de temps avant d’être valide.</p>

<p style="text-align: center;"><a class="media-link" href="media/784a6bb4.post_mortem_ballerina_comment_027.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_027.jpg"><img alt="" class="media" src="media/934f6b2b..post_mortem_ballerina_comment_027_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_027_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce décor a été fait sur plan. On avait énormément de livres au studio sur l’Opéra de Paris et même une petite maquette carton. Ce fut aussi un des candidats pour l’outil de récupération d’instance implicite car nombre d’objets se répètent. J’ajoute qu’il ne fut pas simple du tout à éclairer. Sur des plans rapprochés, on remplaçait les lights hors cadre chacun des lampadaires (4-5 par lampadaire, sans compter les bougies) par une seule light, plus grosse, mais a l’intensité et la couleur globale similaire. Cette méthode de «&nbsp;dégrossissement&nbsp;» du lighting permettait de diminuer le nombre de lights sur un plan (et donc diminuer le temps de rendu et le grain) sans modifier le retour visuel. Donc oui, gros travail sur ce décor.</p>

<p style="text-align: center;"><a class="media-link" href="media/4d0b7ae0.post_mortem_ballerina_comment_031.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_031.jpg"><img alt="" class="media" src="media/cf45908c..post_mortem_ballerina_comment_031_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_031_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/4e7b8e42.post_mortem_ballerina_comment_034.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_034.jpg"><img alt="" class="media" src="media/4115b73e..post_mortem_ballerina_comment_034_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_034_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Je vous présente mon personnage favori sur ce film&nbsp;: Odette. J’avais très peur que ses vêtements à base de laine ne passent pas ou mal&nbsp;à l’écran. Au final je trouve que ce sont les vêtements les mieux réussi du film. L’écharpe et le petit drape sur les épaules sont faits en displacement pour l’épaisseur de la laine. Ça fait toute la différence.</p>

<p style="text-align: center;"><a class="media-link" href="media/9201c76d.post_mortem_ballerina_comment_035.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_035.jpg"><img alt="" class="media" src="media/7af68f01..post_mortem_ballerina_comment_035_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_035_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/f0a5b866.post_mortem_ballerina_comment_074.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_074.jpg"><img alt="" class="media" src="media/08eb37e5..post_mortem_ballerina_comment_074_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_074_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>J’ai remarqué un truc sur les longs-métrages&nbsp;: L’attachement des différentes personnes travaillant sur le projet aux personnages du film est réel et souvent révélateur de la profondeur du film. Si sur un projet, aucun personnage ne semble intéresser les gens ou donner envie d’en savoir plus, c’est que quelque chose n’est pas bien passe. Je ne parle pas d’animation, mais de chara-design&nbsp;: Le faciès, l’attitude, la voix et l’histoire du personnage doivent questionner, donner envie que le personnage réussisse (ou perde dans le cas du méchant). C’est assez caractéristique dans les films «&nbsp;commerciaux&nbsp;» il faut réussir à développer suffisamment de personnage pour qu’une cible de spectateurs puisse s’identifier. À un rôle crucial la dedans. Merante avait aussi une histoire très développée.D</p>

<p style="text-align: center;"><a class="media-link" href="media/96bcd2fb.post_mortem_ballerina_comment_033.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_033.jpg"><img alt="" class="media" src="media/a46e4ca7..post_mortem_ballerina_comment_033_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_033_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/f4767071.post_mortem_ballerina_comment_062.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_062.jpg"><img alt="" class="media" src="media/804bd34b..post_mortem_ballerina_comment_062_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_062_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Les plans de nuit sont rares dans les films d’animation. Pourtant, une grande partie de Ballerina se passe la nuit ce qui donne des effets super intéressants. L’éclairage du visage d’Odette par la lampe (blanche et froide vous aurez remarqué) de la grande méchante, ainsi que l’alternance classique bleu marin/orange cache une décision plus rationnelle&nbsp;: À l’origine, énormément de plans devait se dérouler dans les rues de Paris. Une des premières décisions fut de s’arranger pour que ces plans se passent de nuit de manière à diminuer le nombre de personnage secondaires. C’est encore plus tard que presque tous les plans de Paris disparurent au profit de plans dans la cour intérieure.</p>

<p style="text-align: center;"><a class="media-link" href="media/51cb2fa1.post_mortem_ballerina_comment_036.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_036.jpg"><img alt="" class="media" src="media/c1588705..post_mortem_ballerina_comment_036_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_036_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>L'éclairage des escaliers se révèle toujours assez compliqué. En effet, il faut beaucoup de lumières éclairant différentes parties distinctes, mais le <em>path tracer</em> a souvent du mal à deviner quelle lumière éclaire quelle partie, ce qui amène facilement du grain.</p>

<p style="text-align: center;"><a class="media-link" href="media/cd8cfad1.post_mortem_ballerina_comment_037.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_037.jpg"><img alt="" class="media" src="media/ca88481f..post_mortem_ballerina_comment_037_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_037_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce plan fut assez compliqué à faire en raison du nombre de miroir et d’AOV nécessaire a la recomposition de l’image. En effet, quand on a une réflexion pure (un miroir) il faut trouver un moyen de propager les AOV dans la réflexion pour pouvoir les sortir séparéments. Ensuite, il faut recompositer chacun des miroirs pour finalement les intégrer au plan. Bon, le problème vient du fait qu’il fallait aussi fournir une Z de qualité pour la version stéréo. Il fallait donc aussi propager la Z.</p>

<p style="text-align: center;"><a class="media-link" href="media/0554b11a.post_mortem_ballerina_comment_038.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_038.jpg"><img alt="" class="media" src="media/33f01fd2..post_mortem_ballerina_comment_038_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_038_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce plan fut mon plan de test pour les outils de projection en matte painting. J’avoue ne plus me rappeler du tout pourquoi la projection était nécessaire mais que j’étais trop fier quand mes petits calculs me rendaient une projection «&nbsp;pixel-perfect&nbsp;» du rendu dans Nuke&nbsp;!</p>

<p style="text-align: center;"><a class="media-link" href="media/f167dcd1.post_mortem_ballerina_comment_039.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_039.jpg"><img alt="" class="media" src="media/58af2550..post_mortem_ballerina_comment_039_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_039_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Le directeur de l’Opéra fut le premier adulte en lookdev. Il a été utilisé pour par mal d’expérimentation concernant le rendu des visages et en particulier le nez qui devait avoir des bords bien définis. L’origine remonte a une décision de rig qui avait demande au modeling de diminuer la complexité des maillages des visages, cassant ainsi les bordures du nez. Je pense qu’on aurait pu faire différemment, mais je n’avais pas mon mot a dire. Bref, donc&nbsp;: À la charge du rendu d’afficher quelque chose de convaincant. On est naturellement parti sur des normales mais le problème du normal mapping basse fréquence c’est qu’il commence a devenir bizarre en gros plan quand l’axe de la caméra devient tangent à la surface (en faisant apparaitre une sorte de liseré sur la couche de réflexion). J’ai donc dû me pencher sur un peu de math pour proposer un moyen de switcher du normal map au displacement suivant les plans. Pour être honnête, je ne suis pas sûr que le displacement fut utilise sur beaucoup de plans.</p>

<p style="text-align: center;"><a class="media-link" href="media/59b8c1a8.post_mortem_ballerina_comment_040.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_040.jpg"><img alt="" class="media" src="media/7ce95db1..post_mortem_ballerina_comment_040_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_040_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Il a eu un truc de vraiment problématique avec les intérieurs de l’Opéra de Paris et en particulier ce plan&nbsp;: Tout est plat et répétitif. Je me rappelle d’un couloir tellement basique que le DA était assis près du superviseur ligthing pendant plusieurs jours pour réussir a faire un truc «&nbsp;regardable&nbsp;». Au final, la réalisation et l’animation des personnages prends le dessus et on y attache peu d’importance mais oui, éclairer des murs plats ce n’est pas la joie.</p>

<p style="text-align: center;"><a class="media-link" href="media/645ff78f.post_mortem_ballerina_comment_041.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_041.jpg"><img alt="" class="media" src="media/55429ace..post_mortem_ballerina_comment_041_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_041_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/41a09848.post_mortem_ballerina_comment_064.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_064.jpg"><img alt="" class="media" src="media/92722d8d..post_mortem_ballerina_comment_064_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_064_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Cette pièce est le premier «&nbsp;gros&nbsp;» intérieur qui a été préparé pour le rendu. Il apparait en effet sur beaucoup de plans du teaser. Lui aussi était dur à aborder car si on enlève les parquets, il y a peu de zones vraiment intéressantes en termes d’éclairage. Notez aussi que tout l’éclairage est diffus et il y a peu d’éclairage direct. Anecdote intéressante&nbsp;: Un grand miroir se situe au centre de la pièce mais posait pas mal de soucis autant techniques que narratifs. Au final, un grand drap a été mis dessus ni vue ni connue.</p>

<p style="text-align: center;"><a class="media-link" href="media/1673974d.post_mortem_ballerina_comment_043.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_043.jpg"><img alt="" class="media" src="media/20023ce8..post_mortem_ballerina_comment_043_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_043_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ici, la manche de Victor est en gros plan. Le lighting a donc choisi d’appliquer du displacement pour ajouter du détail et de la nuance dans la forme. Mais comme le rig n’était pas recentrable, les vertices de la géométrie vibraient légèrement. En soi, ce n’est pas trop problématique quand les vertices sont éloignés les uns des autres. Mais quand on displace, il y a un vertice tous les deux/trois pixels, du-coups le flickering commence à se voir (sous la forme d’un léger «&nbsp;bourdonnement&nbsp;» de la manche). Comment régler ce souci comme un vrai pro&nbsp;? On prend la scène d’anim, on décale le personnage d’une distance particulière en vu de le rapprocher du centre (2000 en x par exemple), on ré-exporte l’alembic, on met a jour l’alembic dans Guerilla, puis on décale le personnage de 2000 en x dans l’autre sens. <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 style="text-align: center;"><a class="media-link" href="media/a5afcdd7.post_mortem_ballerina_comment_044.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_044.jpg"><img alt="" class="media" src="media/5c2b51fc..post_mortem_ballerina_comment_044_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_044_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce plan séquence fut surement le plus compliqué du film. Il a pris plus d’un mois a un graphiste senior à plein temps pour en venir a bout. Chaque personnage était présent deux a trois fois dans la scène et le layout les a faits s’alterner pour donner l’impression d’une continuation. L’éclairage était un cauchemar (extérieur, intérieur puis extérieur) du-coup beaucoup de choses ont été séparé ce qui est très risqué car cela entraine souvent de la mauvaise intégration et une difficulté à garder un éclairage cohérent (c’est souvent le cas sur les plans «&nbsp;sur-composités&nbsp;»). Et pourtant, j’avoue ne pas lui trouver de défauts. Franchement le boulot est impeccable de bout en bout.</p>

<p style="text-align: center;"><a class="media-link" href="media/c3961f92.post_mortem_ballerina_comment_057.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_057.jpg"><img alt="" class="media" src="media/95214f2c..post_mortem_ballerina_comment_057_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_057_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Regardez les variations de positionnement des volets. C’est à ça qu’a servi le travail que je vous exposais plus haut avec l’histoire de la porte du wagon. Vous allez me dire que tout le monde s’en fout mais tous les objets ont bénéficié d’un travail de cadrage (on parle souvent de «&nbsp;set-dressing&nbsp;») de la part du layout et je pense vraiment que ça rend l’image plus naturelle.</p>

<p style="text-align: center;"><a class="media-link" href="media/355fddf2.post_mortem_ballerina_comment_059.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_059.jpg"><img alt="" class="media" src="media/3f12ffef..post_mortem_ballerina_comment_059_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_059_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/81a5b256.post_mortem_ballerina_comment_060.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_060.jpg"><img alt="" class="media" src="media/a55dadee..post_mortem_ballerina_comment_060_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_060_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/ffb79b5f.post_mortem_ballerina_comment_061.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_061.jpg"><img alt="" class="media" src="media/992c3ba2..post_mortem_ballerina_comment_061_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_061_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Cette séquence fut une des première&nbsp;à être éclaire en utilisant le principe des shot groups, par un seul graphiste. L’ensemble est hyper homogène.</p>

<p style="text-align: center;"><a class="media-link" href="media/40a577e0.post_mortem_ballerina_comment_063.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_063.jpg"><img alt="" class="media" src="media/c6d48c69..post_mortem_ballerina_comment_063_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_063_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Hahaha&nbsp;! Je me rappelle bien cette séquence&nbsp;: L’échelle du projet était de 1&nbsp;unité = 10&nbsp;cm. C’est peut-être peu commode mais ça résolvait pas mal de soucis. C’était un bon compromis. Le FX guy avait mal configuré son échelle de décimation. Du-coup, le premier export des volumétriques de ce plan était monstrueusement énorme, genre un triangle par pixel&nbsp;! Mais le pire c’est qu’on avait mis en place un système qui appliquait une subdivision de 1 a tous les mesh <img src="media/6bf85d36.IFuckTheWorld.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/IFuckTheWorld.gif" alt=":IFuckTheWorld:" class="smiley" /> . <a class="media-link" href="media/5b2100bc.atomic_bomb.gif" data-original-source="http://www.fevrierdorian.com/blog/public/gif/atomic_bomb.gif">Resultat</a>.</p>

<p style="text-align: center;"><a class="media-link" href="media/59d5a2a9.post_mortem_ballerina_comment_065.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_065.jpg"><img alt="" class="media" src="media/ed604aba..post_mortem_ballerina_comment_065_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_065_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Le toit de l’opéra était un des assets les plus massifs en termes de travail pour les textures. Les instances implicites ont eu un gros impact sur le quotidien des graphistes travaillant sur cet asset.</p>

<p style="text-align: center;"><a class="media-link" href="media/2f9e04ce.post_mortem_ballerina_comment_067.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_067.jpg"><img alt="" class="media" src="media/79e4d34b..post_mortem_ballerina_comment_067_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_067_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>L’atelier fut le plan de test ultime pour la builder. Il y a des objets partout, dans toutes les positions. Si ça build correctement, tout le film devrait marcher (pas vrai&nbsp;? <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 style="text-align: center;"><a class="media-link" href="media/52be4716.post_mortem_ballerina_comment_070.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_070.jpg"><img alt="" class="media" src="media/6d548d1e..post_mortem_ballerina_comment_069_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_069_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /><img alt="" class="media" src="media/43ff2109..post_mortem_ballerina_comment_070_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_070_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Dans le bar breton, un des drapeau fait référence&nbsp;à l'endroit ou ce film a été fabriqué. Saurez-vous trouver lequel?</p>

<p style="text-align: center;"><a class="media-link" href="media/c67b6f90.post_mortem_ballerina_comment_072.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_072.jpg"><img alt="" class="media" src="media/a9b87071..post_mortem_ballerina_comment_072_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_072_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Un plan pour lequel je me serai beaucoup battu mais qui aura eu raison de moi. Je ne sais pas si vous avez déjà fais des soirées (nuits&nbsp;?) à Paris mais la réflexion des éclairages publiques sur les paves (très sombres) est très présent, quand bien même il n’a pas plu. Sur ce plan la réflexion était trop plate, car la normal map semblait devenir neutre après quelques mètres, donnant un effet tout lisse. Malgré mes tentatives pour redonner un peu de consistance au sol, la réflexion a été très atténué pour pouvoir livrer à temps. Au final il passe très bien dans le film. J’ai juste un blocage personnel dessus.</p>

<p style="text-align: center;"><a class="media-link" href="media/24cbf7e8.post_mortem_ballerina_comment_079.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_079.jpg"><img alt="" class="media" src="media/5d3024ec..post_mortem_ballerina_comment_075_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_075_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /><img alt="" class="media" src="media/4f1dffbd..post_mortem_ballerina_comment_079_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_079_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>OK, j’avoue, ce projet a développé en moi un fétichisme pour les vieux parquets bien lustrés… <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 style="text-align: center;"><a class="media-link" href="media/b11228fe.post_mortem_ballerina_comment_080.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_080.jpg"><img alt="" class="media" src="media/9d6312f3..post_mortem_ballerina_comment_080_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_080_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Pour faire valider les diamants de la couronne de ce personnage, les lookdev a dû honteusement tricher en augmentant l’intensité de ces derniers aux points qu’ils créaient de la lumière. Path tracer oblige, on se retrouvait avec des points blancs sur les plans ou ce personnage apparaissait. On a mis un peu de temps&nbsp;à trouver, mais des petits points blancs dans un plan (appelés <em>fireflies</em>) sont souvent&nbsp;dû à un shader qui renvoi une haute valeur.</p>

<p style="text-align: center;"><a class="media-link" href="media/5adc662b.post_mortem_ballerina_comment_084.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_084.jpg"><img alt="" class="media" src="media/26ddd23b..post_mortem_ballerina_comment_084_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_084_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Comme bien souvent avec les «&nbsp;trucs à plume&nbsp;» la poule est un asset qui a demande beaucoup de travail, avec du Yeti et quelques morceaux de shader écris pour l’occasion. Un des running gag original du film consistait a la faire revenir plusieurs fois a l’écran tout au long du film.</p>

<p style="text-align: center;"><a class="media-link" href="media/a9ba139b.post_mortem_ballerina_comment_085.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_085.jpg"><img alt="" class="media" src="media/a86ab09f..post_mortem_ballerina_comment_085_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_085_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Ce plan est très différent des autres en termes de colorimétrie. On est beaucoup plus sur des teintes Pixar/Illumination. Au passage, le personnage de la mère de Félicie fut la favorite d’une partie de l’équipe pendant longtemps mais le fait qu’elle apparaisse qu’une seule fois (sur un plan fait vers la fin de la production), n’a, je pense, pas permis aux différentes personnes intervenants dessus d’y passer le temps nécessaire.</p>

<p style="text-align: center;"><a class="media-link" href="media/2c31d181.post_mortem_ballerina_comment_086.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_086.jpg"><img alt="" class="media" src="media/c1204f15..post_mortem_ballerina_comment_086_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_086_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Tu passes une prod à régler les soucis de hairs des personnages, les uns après les autres. Au bout d’un moment tout marche, tu penses que les problèmes de hair c’est fini, tu as déjà fêté ça il y a deux mois et BAM&nbsp;! Tu as un nouveau plan qui tombe un peu avant la fin du projet. Avec au programme, un nouveau perso, visible uniquement sur ce plan, en gros plan avec les cils et les sourcils qui flickent&nbsp;!</p>

<p style="text-align: center;"><a class="media-link" href="media/2e301ee9.post_mortem_ballerina_comment_088.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_088.jpg"><img alt="" class="media" src="media/27c9cc0d..post_mortem_ballerina_comment_088_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_088_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a><a class="media-link" href="media/dc54622a.post_mortem_ballerina_comment_096.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/post_mortem_ballerina_comment_096.jpg"><img alt="" class="media" src="media/852d36a5..post_mortem_ballerina_comment_096_m.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_27_post_mortem_ballerina/commentaire_plan/.post_mortem_ballerina_comment_096_m.jpg" style="margin: 0px auto; display: table; width: 560px; height: 236px;" /></a>Je vais finir ce commentaire avec deux plans et un petit mot concernant l’animation. On l’entend souvent, l’animation est le truc le plus important et c’est vrai&nbsp;: Si les personnages ne sont pas «&nbsp;vivants&nbsp;», c’est terminé. Le lighting et le compo n’y pourront pas grand-chose. Le <em>chara-design</em> de Ballerina c’est pas le plus simple&nbsp;à aborder. Pour une raison qui m’échappe (je ne m’occupais pas du département anim), je trouve l’animation sur le projet inégale, mais il faut avouer que certains plans sont de belles réussites. Le plan du dessus est le tout dernier d’une séquence qui monte en puissance ou Félicie, malgré n’avoir plus aucune chance de devenir ballerine enfile ses chaussons, commence quelques pas puis fait des gestes de plus en plus complexe pour finir sur une pirouette plein plan le regard vers le dos de la caméra (Paris) avec deux sentiments en même temps sur son visage. Un sentiment clair, c’est bien pour du cartoon. Mais ce qui rend un personnage en 3d&nbsp;humain c’est en grande partie la manière dont il exprime (ou tente de cacher) l’ambivalence de ses sentiments. Ce sont des attitudes qu’on retrouve fréquemment dans le film. Disney excellait dans sa capacité à le faire en 2d et peu de films y arrivent vraiment. Je trouve que Ballerina s’en sort très bien là-dedans.</p>

<h3>Conclusion</h3>

<p>Il est bien évident que tout ceci est un effort collectif, nous n’étions jamais seuls à faire des choix et c’est sûrement ce qui a permis au projet d’aboutir. Je n’ai pas nommé les personnes, mais il me semble important de rappeler que c’est pourtant avec de l’humain que tout se joue, du haut de la hiérarchie jusqu’au graphiste parfois derrière des tableaux à vérifier que l’intégralité des retakes des plans ont été faites (et pour qui je peux vous garantir que ce n’est pas la tasse de café). Si personne ne le veut, le film ne sort pas, c’est aussi simple que ça.</p>

<p>Je ne parle pas d’aller se tailler les veines à faire des heures supplémentaires pendants des mois pour le plaisir de montrer qu’on souffre à la tache mais au contraire d’une volonté farouche que tout ce passe pour le mieux à tous les niveaux et sur la longueur. Je n’ai dû faire qu’une vingtaine d’heure supplémentaires (pour finir et peaufiner le builder si ne me souvient bien car «&nbsp;Pas d’builder&nbsp;: Pas d’projet…&nbsp;»). Le fait de voir qu’il y a une volonté générale de réussite du projet et de bienveillance mutuel (OK je m’enflamme peut-être un peu sur le dernier mais quand même c’est l’idée) pousse les gens&nbsp;à fournir l’effort supplémentaire nécessaire&nbsp;à la sortie d’images propre et livrées dans les temps. La peur de se faire virer n’est pas déterminante, chacun sait qu’une fois le projet fini on passe (presque tous) à la porte. À partir de là, ce qui compte pour chacun c’est de faire un travail dont il est fier. À quoi bon livrer des images, sensé divertir les gens qui les regarde, faites dans la tension et dont tous le monde garde un gout amer&nbsp;? À mes yeux, et malgré un double démarrage difficile, Ballerina semble également avoir réussi sur ce terrain et pour un premier long-métrage, c’est la classe ! <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>A bientôt&nbsp;!</p>

<p>Dorian</p>

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


feed_id: urn:md5:88b132d883e85fe0aee35fcca778bc06
title: L'instanciation implicite du format Alembic
uri: L-instanciation-implicite-du-format-Alembic
url: http://www.fevrierdorian.com/blog/post/2017/06/17/L-instanciation-implicite-du-format-Alembic
content:
<p><img alt="" class="media" src="media/60030d3c.instance_implicite_alembic_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_tn.png" style="float: left; margin: 0 1em 1em 0;" />Suite&nbsp;à la publication de <a class="ref-post" href="http://www.fevrierdorian.com/blog/post/2017/06/11/Post-mortem%3A-Ballerina">mon post mortem sur Ballerina</a>, certains d'entre vous semblaient intrigués par le paragraphe concernant l'instanciation implicite des fichiers Alembics.</p>

<p>Dans ce billet, je vous propose d'aller un peu plus loin avec une explication théorique, un peu de pratique et un peu de code (la recette du bonheur en somme <img src="media/7a81a9b4.petrus.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/petrus.gif" alt=":petrus:" class="smiley" /> ).</p>    <h4>Le principe</h4>

<p>Dans un fichier Alembic, les géométries sont stockées sous forme de tableaux.:</p>

<ul>
	<li>Les positions des sommets&nbsp;: [point1.x, point1.y, point1.z, point2.x, point2.y, point2.z, point3.x, …]</li>
	<li>Les nombres de «&nbsp;points par face&nbsp;» (souvent quatre, comme vous pouvez vous en doutez): [4, 4, 4, 4, 4, 4, 4, …]</li>
	<li>Les indices de positions par face&nbsp;: [0, 1, 2, 3, 3, 2, 4, 5, …]</li>
</ul>

<p>Le dernier est le plus subtil à comprendre&nbsp;: Combiné au second, il permet de construire les faces&nbsp;: La face 1 est compose de 4 indices. On prend donc, dans le tableau de position, les indices de position (dernier tableau): 0, 1, 2, 3. La face 2, est compose de 4 indices. On prend donc, dans le tableau d’indice de position, les 4 indices suivants qu’on va chercher dans le tableau des positions&nbsp;: 3, 2, 4, 5. Et ainsi de suite.</p>

<p>C’est un peu bizarre si on n’est pas habitué, mais on stocke très souvent les données géométriques de cette façon et je vais tenter de vous expliquer pourquoi. <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>Vous l’aurez compris, le premier tableau ne concerne que les positions des sommets (<em>vertices</em> en anglais) et les deux seconds tableaux, la topologie de la géométrie. Quand un objet est animé, ce ne sont souvent que ses sommets qui bougent. Sa topologie (l’ordre de ses faces, arêtes et sommets) ne change pas.</p>

<p>Mais comment, quand on exporte de la géométrie image après image, la lib Alembic sait-elle que la topologie n’a pas changée&nbsp;? C’est la magie des <a href="https://fr.wikipedia.org/wiki/Fonction_de_hachage" hreflang="fr">fonctions de hachage</a>.</p>

<p>Histoire de vous éviter la lecture de la page Wikipédia, une fonction de hachage sert, grosso modo, à générer une signature numérique (qui ressemble vaguement à «&nbsp;867fc32883baaa34&nbsp;») depuis une suite de bit.</p>

<p>Comme vous vous en doutez, la suite de bit en question ce sont nos tableaux. En langage bas niveau (C++ en l’occurrence), un tableau est une suite de valeur fortement typées. Un chiffre flottant <a href="https://fr.wikipedia.org/wiki/IEEE_754#Format_simple_pr.C3.A9cision_.2832_bits.29" hreflang="fr">se stock sur 32 bits</a>. Une position se stocke sur 3 chiffres flottants (x, y, z), soit 3x32=96bits. Pour 8 positions (un cube) il faut donc 8x96=768bits. Ce sont ces 768bits que la fonction de hachage (<a href="https://github.com/alembic/alembic/blob/d75360416b1b20df85c4f58195d0898695ceb525/lib/Alembic/Util/SpookyV2.h#L37" hreflang="en">Spooky</a> de son petit nom) va ingurgiter pour nous sortir une valeur bizarre (eg. «&nbsp;867fc32883baaa34&nbsp;»): La signature numérique du tableau de position. Si on renvoie le même tableau (avec des positions parfaitement identiques), on a la même signature.</p>

<p>Vous venez juste de vous farcir un cours de science informatique en vitesse de la lumière la&nbsp;! <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /></p>

<p>Dans un Alembic, chaque tableau possède donc sa signature numérique.</p>

<p>À chaque fois que vous envoyez un nouveau tableau à Alembic&nbsp;(pour chaque image en fait), ce dernier calcule sa signature numérique (son hash). S’il est déjà présent dans le fichier, il ne l’ajoute pas au fichier mais précise simplement que l’image en question utilise le tableau avec le hash que vous venez de calculer.</p>

<p>Avec ce système on peut avoir plusieurs tableaux contenant la position des sommets animés (un par image en fait) tout en gardant les deux tableaux de topologie unique pour tout le fichier.</p>

<p>Pour résumer, si vous exporter l’animation d’un simple cube déformé sur 10 images vous aurez&nbsp;:</p>

<ul>
	<li>10 tableaux de position (un par image)</li>
	<li>1 tableau de point par face (celui de la première image, réutilise sur toutes les images)</li>
	<li>1 tableau de position par face (celui de la première image, réutilise sur toutes les images)</li>
</ul>

<p>Pour les plus curieux d’entre vous, voici <a href="https://github.com/alembic/alembic/blob/895a7c6a8b3396a21c6ba03ddf91ed91514d7b93/maya/AbcExport/MayaMeshWriter.cpp#L983" hreflang="en">la ligne de code</a> de l’exporteur Alembic de Maya qui s’occupe d’envoyer les différents tableaux que je vous ai présenté ci-dessus dans un fichier Alembic. Notez que l’exporteur ne fait aucune distinction. Pour chaque image, il envoie tout à l’Alembic et c’est ce dernier qui décide de stocker les tableaux dans le fichier ou non.</p>

<p>Une fois qu’on a un beau fichier tout optimisé qu’est ce qui se passe&nbsp;?</p>

<p>Et bien quand l’application (un moteur de rendu par exemple) demande, les tableaux de l'image 5 à un fichier Alembic, ce dernier (enfin le code de la lib Alembic) renvoi le tableau de position de l'image 5, puis les deux tableaux de la topologie de la première image.</p>

<blockquote>
<p>Notez que je ne vous ai pas parlé des UVs, normals, vertex color, etc. Mais sachez que le concept est le même que pour les positions et la topologie.</p>
</blockquote>

<p>Et les instances implicites la dedans&nbsp;?</p>

<p>J’arrive au dernier point, celui qui devrait vous faire tilter. <img src="media/31e65c2e.idee.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/idee.gif" alt=":idee:" class="smiley" /></p>

<p>En plus de stocker de la géométrie, Alembic stock aussi la hiérarchie. Un <em>transform</em> est un objet présenté sous la forme de translation, rotation, échelle et dont la représentation mathématique est une matrice 4x4 (je ne rentre pas dans les détails mais sachez que quand vous manipulez un <em>transform</em>, vous manipulez en fait une matrice). Une hiérarchie de <em>transform</em> est donc une hiérarchie de matrice.</p>

<p><img alt="" class="media" src="media/2153e00d.instance_implicite_alembic_022.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_022.png" style="margin: 0 auto; display: table;" /></p>

<p style="text-align: center;">Derrière les paramètres que vous manipulez tous les jours se cache un objet mathématique bien cool: La matrice&nbsp;! <img src="media/d52870c6.youplaBoum.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/youplaBoum.gif" alt=":youplaBoum:" class="smiley" /></p>

<p>Au même titre que pour les tableaux de position et de topologie, les matrices peuvent être animé par image (quand on anim un simple déplacement qui ne déforme pas la géométrie de l’objet)</p>

<p>Notez que dans mon exemple précédant, j’ai précisé qu’il s’agissait d’un cube déformé. L’animation ne se situait donc pas sur le <em>transform</em> du cube mais directement sur les sommets (c’est la géométrie qui bouge à chaque image, comme un personnage skinné en fait).</p>

<p>Sauf que si, au lieu de déformer l’objet vous n’animer que son <em>transform</em> (translation, rotation, échelle), le tableau des positions des sommets ne change pas d’une image à l’autre, seule le <em>transform</em> parent de la <em>shape</em> (la matrice parent) change.</p>

<p>Ce qui veut dire&nbsp;(arriver ici vous devriez l’avoir compris) que si on modeleur duplique des centaines d’objets sans les modifier puis exporte un Alembic, les sommets et topologies des objets ne sont stockés qu’une seule fois dans le fichier et seul la position des matrices (différentes pour chaque objet) sont stockés de manière individuelle. Et ça, <em>c’est</em> la définition d’une instance géométrique&nbsp;!</p>

<p>Je reprends un schéma que <a class="ref-post" href="http://www.fevrierdorian.com/blog/post/2017/03/25/Pourquoi-les-instances-Maya-sont-si-lourdes">j’avais utilisé</a> pour expliquer le principe des instances Maya (c’est pas super adapté mais ça représente bien le principe):</p>

<p><img alt="" class="media" src="media/f1733886.instance_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_03_26_instance_lourde_maya/instance_001.png" style="margin: 0 auto; display: table;" /></p>

<h4>Un exemple concret</h4>

<p>Comme je sais que vous ne me croyez pas, je vous propose un exemple concret à l’aide de Maya. <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>Créez une sphère&nbsp;:</p>

<p><img alt="instance_implicite_alembic_001" class="media" src="media/c7011dde.instance_implicite_alembic_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_001.png" style="margin: 0px auto; display: table; width: 404px; height: 101px;" /></p>

<p><img alt="instance_implicite_alembic_002" class="media" src="media/16c12160.instance_implicite_alembic_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_002.png" style="margin: 0px auto; display: table; width: 254px; height: 207px;" /></p>

<p>Subdivisez-la histoire qu’on puisse voir des différences de poids facilement lors de l’export&nbsp;:</p>

<p><img alt="instance_implicite_alembic_003" class="media" src="media/627c7ddd.instance_implicite_alembic_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_003.png" style="margin: 0px auto; display: table; width: 192px; height: 243px;" /></p>

<p><img alt="instance_implicite_alembic_004" class="media" src="media/11b4738b.instance_implicite_alembic_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_004.png" style="margin: 0px auto; display: table; width: 201px; height: 184px;" /></p>

<p>Quatre, c’est très bien&nbsp;:</p>

<p><a class="media-link" href="media/e8985b03.instance_implicite_alembic_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_005.png"><img alt="" class="media" src="media/7d45fc68..instance_implicite_alembic_005_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_005_m.png" style="margin: 0px auto; display: table; width: 560px; height: 246px;" /></a></p>

<p><img alt="instance_implicite_alembic_006" class="media" src="media/aa415851.instance_implicite_alembic_006.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_006.png" style="margin: 0px auto; display: table; width: 434px; height: 429px;" /></p>

<p style="text-align: center;"><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>Détruisez l’historique afin de ne garder que la <em>shape</em>&nbsp;:</p>

<p><img alt="instance_implicite_alembic_007" class="media" src="media/6ca5dfdd.instance_implicite_alembic_007.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_007.png" style="margin: 0px auto; display: table; width: 393px; height: 254px;" /></p>

<p><img alt="instance_implicite_alembic_008" class="media" src="media/795a3396.instance_implicite_alembic_008.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_008.png" style="margin: 0px auto; display: table; width: 455px; height: 121px;" /></p>

<p>C’est parti&nbsp;! Dupliquez ça plusieurs fois&nbsp;:</p>

<p><a class="media-link" href="media/c2f87406.instance_implicite_alembic_009.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_009.png"><img alt="" class="media" src="media/0de2bc1c..instance_implicite_alembic_009_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_009_m.png" style="margin: 0px auto; display: table; width: 560px; height: 137px;" /></a></p>

<p>Notez qu’il ne s’agit en aucun cas d’instances Maya au sens propre. Ce sont de simple duplication. Notez aussi comment, malgré le poids de la géométrie, Maya reste réactif. Je soupçonne en effet que ce dernier utilise aussi l’instance implicite quand on fait des duplications et ne duplique la géométrie de chaque objet en mémoire qu’une fois qu’on commence à modifier l’objet. <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>Mais on ne s’arrête pas&nbsp;! <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><a class="media-link" href="media/e703eed4.instance_implicite_alembic_010.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_010.png"><img alt="" class="media" src="media/6292285e..instance_implicite_alembic_010_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_010_m.png" style="margin: 0px auto; display: table; width: 560px; height: 316px;" /></a></p>

<p>C’est pas mal, maintenant on exporte tout ça&nbsp;:</p>

<p><img alt="instance_implicite_alembic_011" class="media" src="media/d8e635e7.instance_implicite_alembic_011.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_011.png" style="margin: 0px auto; display: table; width: 327px; height: 160px;" /></p>

<p>Une seule image (vous pourrez refaire le test sur un range plus large, ça ne changera pas grand-chose):</p>

<p><img alt="instance_implicite_alembic_012" class="media" src="media/19d3556f.instance_implicite_alembic_012.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_012.png" style="margin: 0px auto; display: table; width: 417px; height: 199px;" /></p>

<p>Pas besoin des normales ni des UVs&nbsp;:</p>

<p><img alt="instance_implicite_alembic_013" class="media" src="media/f643a9bf.instance_implicite_alembic_013.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_013.png" style="margin: 0px auto; display: table; width: 381px; height: 281px;" /></p>

<p>Puis validez (ou exécutez cette commande MEL):</p>

<pre>
<code class="language-bash">AbcExport -j "-frameRange 1 1 -dataFormat ogawa -file /home/narann/test/test1.abc";</code></pre>

<p>L’export devrait être assez rapide. Chez moi, le fichier fait 3.12Mo. Clairement, toute la géométrie n’est pas stockée. C’est parce qu’Alembic a reconnu que toutes les sphères étaient identiques. Les données qui composent sa géométrie (tableau de position des sommets et topologie) ne sont donc stocke qu’une seule fois, le reste étant des <em>transforms</em> (matrices) pointant vers la même géométrie. <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>Mais peut-être qu’avec 3.12Mo vous n’êtes toujours pas convaincu. Peut-être que 105 sphères subdivise à 4 ça ne pèse que 3.12Mo après tout… <img src="media/7df0b8d8.perplex.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/perplex.gif" alt=":perplex:" class="smiley" /></p>

<p>On va donc faire un truc qui est très souvent fait en production, un truc souvent demande par le rig pour pleins de bonne raisons&nbsp;: On va réinitialiser les <em>transforms</em>. Sélectionnez tout&nbsp;:</p>

<p><a class="media-link" href="media/f077d83b.instance_implicite_alembic_014.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_014.png"><img alt="" class="media" src="media/697a5762..instance_implicite_alembic_014_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_014_m.png" style="margin: 0px auto; display: table; width: 560px; height: 320px;" /></a></p>

<p>Faites un "<em>Freeze Transformations</em>":</p>

<p><img alt="instance_implicite_alembic_015" class="media" src="media/864b713f.instance_implicite_alembic_015.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_015.png" style="margin: 0px auto; display: table; width: 201px; height: 100px;" /></p>

<p>Les valeurs des positions sont donc revenus à 0 mais les centres géométriques des objets n’ont pas bouge. C’est dû au fait que Maya permet de désolidariser le point de pivot de l’objet par rapport au centre géométrique.</p>

<p><img alt="instance_implicite_alembic_016" class="media" src="media/d624686d.instance_implicite_alembic_016.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_016.png" style="margin: 0px auto; display: table; width: 321px; height: 291px;" /></p>

<p>On va donc faire un "<em>Reset Transformations</em>"&nbsp;:</p>

<p><img alt="instance_implicite_alembic_017" class="media" src="media/54c3f597.instance_implicite_alembic_017.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_017.png" style="margin: 0px auto; display: table; width: 208px; height: 91px;" /></p>

<p>Celui-ci vient modifier les valeurs géométriques de tous les sommets pour qu’ils correspondent au point de pivot. Dans notre cas, chaque objet a maintenant son <em>transform</em> ainsi que son centre géométrique au centre de la scène&nbsp;:</p>

<p><img alt="instance_implicite_alembic_018" class="media" src="media/b5a2f257.instance_implicite_alembic_018.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_018.png" style="margin: 0px auto; display: table; width: 350px; height: 244px;" /></p>

<p>Cela veut dire que chaque sommet de chaque sphère possède une position identique à sa position dans le monde (0, 0, 0). Chaque sommet ayant une position unique par rapport à son centre géométrique, on a donc perdu toute forme d’instanciation implicite pour Alembic. Mais qu’a cela ne tienne, testez pas vous même&nbsp;:</p>

<pre>
<code class="language-bash">AbcExport -j "-frameRange 1 1 -dataFormat ogawa -file /home/narann/test/test2.abc";</code></pre>

<p>Chez moi, le fichier fait 121Mo. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /> Chaque sphère possède ses propres tableaux de position de sommet. En principe les tableaux de topologie sont instanciés car notre petite manipulation des points de pivot n’a pas change la topologie. Si on modifiait la topologie aléatoirement pour chaque sphère, le fichier aurait été encore plus gros.</p>

<p>Bon, on a deux fichiers, il serait peut-être temps de les tester dans nos moteurs de rendu favoris pour savoir ce qu’il en est.</p>

<h4>Dans Guerilla</h4>

<p>Je vais tester dans Guerilla car c’est avec lui que je suis le plus à l’aise et il dispose d’un bon retour pour savoir si l’alembic est correctement interprété.</p>

<p>Importez votre premier Alembic. Les applications étant souvent friandes de moyen d’optimiser le chargement des fichiers, elles s’appuient sur l’instanciation implicite que leur propose Alembic (comme expliqué dans le post mortem, ce fut flagrant sur Mari). Guerilla n’y échappe pas et c’est assez rapide&nbsp;:</p>

<p><a class="media-link" href="media/0ce101a8.instance_implicite_alembic_019.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_019.png"><img alt="" class="media" src="media/975be280..instance_implicite_alembic_019_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_019_m.png" style="margin: 0px auto; display: table; width: 560px; height: 335px;" /></a></p>

<p>Avant de faire le premier rendu, activez la <em>Verbosity</em> à <em>Diagnostics</em> puis cochez <em>Diagnostic Shapes</em> et <em>Diagnostic Accelerator</em>:</p>

<p><a class="media-link" href="media/0ce101a8.instance_implicite_alembic_019.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_019.png"><img alt="" class="media" src="media/daa488dc.instance_implicite_alembic_020.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_020.png" style="margin: 0px auto; display: table; width: 236px; height: 515px;" /></a></p>

<p>Puis faites un rendu. Voici le log&nbsp;:</p>

<pre>
<code>06/19/2017 15:36:48  RNDR DIA: hash for 'test:pSphere61|test:pSphereShape61' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  RNDR DIA: build accel 'test:pSphere61|test:pSphereShape61'
06/19/2017 15:36:48  SHAP DIA: loaded shape '/home/narann/test/test1.abc' '/pSphere61/pSphereShape61.RenderGeometry'
06/19/2017 15:36:48  SHAP DIA: P float3[99842] min=(-0.979728,-0.997817,-0.979728) max=(0.979728,0.997817,0.979728)
06/19/2017 15:36:48  SHAP DIA: N float3[99842] min=(-1.000000,-1.000000,-1.000000) max=(1.000000,1.000000,1.000000)
06/19/2017 15:36:48  MBVH DIA: Building triangle accelerator for 'test:pSphere61|test:pSphereShape61'
06/19/2017 15:36:48  MBVH DIA: Built accelerator for 'test:pSphere61|test:pSphereShape61', 199680 triangles, 8.81M (geo 3.81M, tree 5.00M)
06/19/2017 15:36:48  RNDR DIA: hash for 'test:pSphere62|test:pSphereShape62' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  BRDF DIA: hash for 'test:pSphere76|test:pSphereShape76' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  BRDF DIA: hash for 'test:pSphere49|test:pSphereShape49' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  BRDF DIA: hash for 'test:pSphere33|test:pSphereShape33' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  BRDF DIA: hash for 'test:pSphere18|test:pSphereShape18' is 867fc32883baaa34:60c4e1c779f31ee
06/19/2017 15:36:48  BRDF DIA: hash for 'test:pSphere48|test:pSphereShape48' is 867fc32883baaa34:60c4e1c779f31ee
...</code></pre>

<p>Comme vous pouvez le constater, la <em>shape</em> n’est chargée qu’une seule fois (<em>loaded shape</em> dans le log) puis Guerilla s’appuie sur le hash, toujours identique, pour placer les autres sphères.</p>

<p>Si vous changez de fichier Alembic et que vous relancez le rendu, vous constaterez que le message de chargement de la <em>shape</em> «&nbsp;<em>loaded shape</em>&nbsp;» s’applique pour chaque sphère du fichier et que le rendu met plus de temps avant de démarrer.</p>

<p>Là ou c’est intéressant (et je suis sûr que tous les autres moteurs le font) c’est que quand Guerilla charge plusieurs Alembic, il instancie entre fichier. Si un modeleur a utilisé deux objets identique dans deux Alembic différents, Guerilla le remarque et ne le charge qu’une fois en mémoire. Forcément, quand tes bâtiments ne sont que des variantes de silhouette utilisant des objets géométriques identiques c’est du pain béni pour le moteur.</p>

<h4>Comment permettre aux modeleurs de savoir quand deux objets vont être instancie dans un Alembic&nbsp;?</h4>

<blockquote>
<p>Si vous ne connaissez pas Python, vous risquez d’être un peu perdu sur cette dernière partie, je préfère vous prévenir. :)</p>
</blockquote>

<p>Sur Ballerina nous avions une commande développée en externe qui nous permettait d’avoir le même hash que ceux qui allaient être mis généré par l’Alembic. C’est assez difficile à faire et mon but c’est de vous mettre le pied à l’étrier.</p>

<p>Je vous propose deux code&nbsp;:</p>

<ul>
	<li>Un très simple, à base de commande Python qui ne s’occupe que des sommets.</li>
	<li>Un autre, plus compliqué, faisant des appels à l’API Maya en Python mais qui prends en compte les UVs.</li>
</ul>

<p>Bien entendu, ce sont des codes que j’ai fais chez moi sur des scènes cubes et sphère mais absolument pas teste en production. À vous de voir ce qu’ils valent.</p>

<h4>En commande Maya</h4>

<p>Voici le premier code&nbsp;:</p>

<pre>
<code class="language-python">import collections

import maya.cmds as mc

h_vtx = collections.defaultdict(set)

for shp in mc.ls(type='mesh'):
    h = hash(frozenset(mc.xform(shp+'.vtx[*]', query = True, objectSpace = True, translation = True)))
    h_vtx[h].add(shp)</code></pre>

<p>Et l’explication ligne à ligne&nbsp;:</p>

<pre>
<code class="language-python">h_vtx = collections.defaultdict(set)</code></pre>

<p>On crée d’abords un dictionnaire (<a href="https://docs.python.org/2/library/collections.html#collections.defaultdict" hreflang="en">defaultdict</a>, qui permet d’ajouter un objet, ici un set, à la volée):</p>

<ul>
	<li>Les clefs seront les hash des positions des sommets (comme <em>14653146579</em>)</li>
	<li>Les valeurs un <em>set()</em> de <em>shape</em> correspondant au hash en clef (comme <em>set('|pSphere1|pSphereShape1', '|pSphere2|pSphereShape2')</em>)</li>
</ul>

<pre>
<code class="language-python">for shp in mc.ls(type='mesh'):</code></pre>

<p>Via cette boucle nous allons traverser toutes les <em>shapes</em> de type <em>mesh</em> de la scène.</p>

<pre>
<code class="language-python">    h = hash(frozenset(mc.xform(shp+'.vtx[*]', query = True, objectSpace = True, translation = True)))</code></pre>

<p>Il y a plusieurs commandes empaquetées ici&nbsp;:</p>

<ul>
	<li><a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/CommandsPython/xform.html" hreflang="en">mc.xform()</a> renvoi la position des sommets en espace objet.</li>
	<li><a href="https://docs.python.org/2/library/stdtypes.html#set-types-set-frozenset" hreflang="en">frozenset()</a> permet d’avoir un <em>set()</em> ordonné duquel on pourra générer un hash (plus d’info <a href="https://stackoverflow.com/questions/7027199/hashing-arrays-in-python" hreflang="en">ici</a>).</li>
	<li><a href="https://docs.python.org/2/library/functions.html#hash" hreflang="en">hash()</a> permet de générer une signature depuis une variable (la liste des positions des sommets).</li>
</ul>

<p>On stock le hash dans la variable… «&nbsp;<em>h</em>&nbsp;».</p>

<pre>
<code class="language-python">    h_vtx[h].add(shp)</code></pre>

<p>Ici on ajoute la <em>shape</em> à la liste des <em>shapes</em> ayant le même hash que celui trouvé précédemment.</p>

<p>Imaginons une scène qui ressemble à ça (juste des sphères dupliquées avec une, au centre, dont j’ai bouge un vertex):</p>

<p><a class="media-link" href="media/45a34e53.instance_implicite_alembic_021.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/instance_implicite_alembic_021.png"><img alt="" class="media" src="media/d3a4afc2..instance_implicite_alembic_021_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/.instance_implicite_alembic_021_m.png" style="margin: 0px auto; display: table; width: 560px; height: 401px;" /></a></p>

<p>Si on exécute ce bout de code et qu’on print "<em>h_vtx</em>" on obtient&nbsp;:</p>

<pre>
<code class="language-python"># Result: defaultdict(&lt;type 'set'&gt;, {-1145497079: set([u'pSphereShape9', u'pSphereShape3', u'pSphereShape2', u'pSphereShape1', u'pSphereShape10', u'pSphereShape7', u'pSphereShape6', u'pSphereShape5', u'pSphereShape4', u'pSphereShape12', u'pSphereShape11']), 1873436783: set([u'pSphereShape8'])}) # 
</code></pre>

<p>Le dictionnaire montre deux hashes (<em>-1145497079</em> et <em>1873436783</em>), le dernier n’ayant qu’une sphère, celle dont le vertex a été bouge. Vous pouvez sélectionner les sphères du premier groupe&nbsp;:</p>

<pre>
<code class="language-python">mc.select(list(h_vtx[h_vtx.keys()[0]]))</code></pre>

<p>Modifiez <em>0</em> par <em>1</em> pour sélectionner la sphère du second groupe.</p>

<p>Dès lors, vous pouvez commencer à expérimenter&nbsp;: Dupliquer la sphère du centre (celle avec un vertex en vrac) plusieurs fois puis réexécutez le code et voyez comment il reconnait, dans le dictionnaire «&nbsp;h_vtx&nbsp;», les sphères identiques. Ensuite, faite une autre modification sur une sphère puis réexécutez le code et voyez comment cette sphère dispose maintenant de son propre hash.</p>

<p>Dans tous les cas, vous remarquerez que le script les regroupe bien qu’il ne s’agisse pas d’instances réelles Maya.</p>

<p>Arrivez ici.</p>

<h4>En utilisant l’API Maya</h4>

<p>Ici c’est un peu plus compliqué, mais on se rapproche beaucoup plus de ce que fait Alembic&nbsp;:</p>

<pre>
<code class="language-python">import maya.OpenMaya as om

sel = om.MSelectionList()

om.MGlobal.getActiveSelectionList(sel)

fn_meshes = []

for i in xrange(sel.length()):
    dag_path = om.MDagPath()
    sel.getDagPath(i, dag_path)
    fn_mesh = om.MFnMesh(dag_path)
    fn_meshes.append((fn_mesh.fullPathName(), fn_mesh))

# on aurait pu ajouter les normals, les crease edges, les colors mais osef
h_pt = {}
h_vtx_counts = {}
h_vtx_ids = {}
h_uv_counts = {}
h_uv_ids = {}
h_uvs = {}

for full_path, fn_mesh in fn_meshes:
    
    # vertex positions
    pts = om.MPointArray()
    fn_mesh.getPoints(pts)

    h = hash(frozenset((pts[i].x, pts[i].y, pts[i].z) for i in xrange(pts.length())))
    h_pt[full_path] = h
    
    # vertex topology
    vtx_counts = om.MIntArray()
    vtx_ids = om.MIntArray()
    fn_mesh.getVertices(vtx_counts, vtx_ids)

    h = hash(frozenset(vtx_counts[i] for i in xrange(vtx_counts.length())))
    h_vtx_counts[full_path] = h

    h = hash(frozenset(vtx_ids[i] for i in xrange(vtx_ids.length())))
    h_vtx_ids[full_path] = h
    
    # uv positions
    uv_us = om.MFloatArray()
    uv_vs = om.MFloatArray()
    fn_mesh.getUVs(uv_us, uv_vs)
    
    assert uv_us.length() == uv_vs.length()
    
    h = hash(frozenset((uv_us[i], uv_vs[i]) for i in xrange(uv_us.length())))
    h_uvs[full_path] = h
    
    # uv topology
    uv_counts = om.MIntArray()
    uv_ids = om.MIntArray()
    fn_mesh.getAssignedUVs(vtx_count, vtx_list)
    
    h = hash(frozenset(uv_counts[i] for i in xrange(uv_counts.length())))
    h_uv_counts[full_path] = h

    h = hash(frozenset(uv_ids[i] for i in xrange(uv_ids.length())))
    h_uv_ids[full_path] = h
    
# the hash of the hashes
h_total = {}

for full_path in h_pt.keys():
    
    h_total[full_path] = hash((h_pt[full_path],
                               h_vtx_counts[full_path],
                               h_vtx_ids[full_path],
                               h_uvs[full_path],
                               h_uv_counts[full_path],
                               h_uv_ids[full_path]))

path_per_h = collections.defaultdict(set)

for full_path, h in h_total.iteritems():
    
    path_per_h[h].add(full_path)

print path_per_h
mc.select(list(path_per_h[path_per_h.keys()[1]]))</code></pre>

<p>Pas de panique, voici l’explication ligne à ligne.</p>

<pre>
<code class="language-python">import maya.OpenMaya as om

sel = om.MSelectionList()

om.MGlobal.getActiveSelectionList(sel)</code></pre>

<p>Comme je n’aime pas les longs espace de nom, j’importe <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__cpp_ref_group___open_maya_html" hreflang="en">OpenMaya</a> sous l’espace de nom "<em>om</em>". <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>Ensuite, on fabrique une <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__cpp_ref_class_m_selection_list_html" hreflang="en">MSelectionList</a> qui est une sorte de «&nbsp;liste spécialement adaptée à la sélection&nbsp;». Et on appele une <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_global.html#a6d81d38246555884897fb153c93aaf42" hreflang="en">commande globale bien pratique</a> qui recupere la selection.</p>

<p>TL;DR: On fait l’équivalent de <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/CommandsPython/ls.html" hreflang="en">mc.ls()</a>. avec plus de lignes. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>

<pre>
<code class="language-python">fn_meshes = []

for i in xrange(sel.length()):
    dag_path = om.MDagPath()
    sel.getDagPath(i, dag_path)
    fn_mesh = om.MFnMesh(dag_path)
    fn_meshes.append((fn_mesh.fullPathName(), fn_mesh))</code></pre>

<p>Avec cette boucle, on va récupérer les <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_fn_mesh.html" hreflang="en">MFnMesh</a> de chacun des mesh de notre sélection. Un MFnMesh est un «&nbsp;ensemble de fonction&nbsp;» (Function set, préfixé <em>MFn</em> dans l’API Maya) qui permet de lier des fonctions sur des données (C’est un peu technique mais dans l’API Maya, les nœuds sont simplement des données compatibles avec certains ensemble de fonction).</p>

<pre>
<code class="language-python">    dag_path = om.MDagPath()
    sel.getDagPath(i, dag_path)</code></pre>

<p>On crée un <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_dag_path.html" hreflang="en">MDagPath</a> vide qu’on remplit avec l’item de la sélection («&nbsp;i&nbsp;» de la boucle). Un MDagPath est un «&nbsp;chemin vers un nœud hiérarchisé&nbsp;».</p>

<pre>
<code class="language-python">    fn_mesh = om.MFnMesh(dag_path)</code></pre>

<p>Maintenant qu’on a un chemin direct, on récupère l’ensemble de fonction.</p>

<pre>
<code class="language-python">    fn_meshes.append((fn_mesh.fullPathName(), fn_mesh))</code></pre>

<p>Enfin, on l’ajoute à la liste sous la forme un tuple de deux éléments (le chemin du nœud et l’ensemble de fonction).</p>

<p>On avance dans le script pour la seconde boucle&nbsp;:</p>

<pre>
<code class="language-python"># on aurait pu ajouter les normals, les crease edges, les colors mais osef
h_pt = {}
h_vtx_counts = {}
h_vtx_ids = {}
h_uv_counts = {}
h_uv_ids = {}
h_uvs = {}
</code></pre>

<p>Ici on prépare simplement des dictionnaires de hash. Ils sont tous préfixés d’un «&nbsp;<em>h_</em>&nbsp;» parce qu’ils contiennent des…? Hash bien-sur&nbsp;! Vous regrettez déjà de ne pas avoir fais math sup’ math spé’ je le sais. Que voulez-vous, certains réussissent et d’autres écrivent un blog. <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>Bref, la clef de chacun des dictionnaires sera le chemin complet d’un nœud, et la valeur, sa valeur de hash. Un peu comme ceci&nbsp;:</p>

<pre>
<code class="language-python">h_pt = {'|pSphere1|pSphereShape1': 1574633,
        '|pSphere2|pSphereShape2': 1574633,
        '|pSphere3|pSphereShape3': 1657615,
        ...}</code></pre>

<ul>
	<li>«&nbsp;<em>h_pt</em>&nbsp;» contiendra les hash des tableaux de la position des sommets</li>
	<li>«&nbsp;<em>h_vtx_counts</em>&nbsp;» contiendra les hash des tableaux du nombre de sommet par face</li>
	<li>«&nbsp;<em>h_vtx_ids</em>&nbsp;» contiendra les hash des tableaux des indices des sommets</li>
</ul>

<p>Et pareil pour les uvs… <img src="media/8ce9d160.sourit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sourit.gif" alt=":sourit:" class="smiley" /></p>

<blockquote>
<p>Notez que je me suis arrêté à la géométrie et aux UVs, mais on aurait pu ajouter les normales, les couleurs par sommet, etc. Simplement que comme on ne les exporte pas avec l’Alembic&nbsp;: On s’en fout&nbsp;! <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /></p>
</blockquote>

<p>C’est parti pour la boucle principale (qui est en fait compose de plusieurs blocs assez similaires.</p>

<pre>
<code class="language-python">for full_path, fn_mesh in fn_meshes:</code></pre>

<p>On déroule la boucle, pour chaque chemin complet d’un nœud on a son ensemble de fonction.</p>

<pre>
<code class="language-python">    # vertex positions
    pts = om.MPointArray()
    fn_mesh.getPoints(pts)

    h = hash(frozenset((pts[i].x, pts[i].y, pts[i].z) for i in xrange(pts.length())))
    h_pt[full_path] = h</code></pre>

<p>On fabrique un <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__cpp_ref_class_m_point_array_html" hreflang="en">MPointArray()</a> (un tableau de… <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__cpp_ref_class_m_point_html" hreflang="en">MPoint()</a>) nommé "<em>pts</em>", qu’on remplit avec les points du mesh via la méthode <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__cpp_ref_class_m_fn_mesh_html" hreflang="en">getPoints()</a> de l’ensemble de fonction "<em>fn_mesh</em>".</p>

<p>Ensuite, on déroule les valeurs de chaque point dans un itérateur qu’on déroule à son tour, comme le script précédant, dans un frozenset() dont on génère le hash.</p>

<p>La raison pour laquelle on déroule la position des points c’est qu’un MPointArray() n’est pas hashable par python. Il faut donc générer une structure en pure python sinon, dans mon cas, hash renvoi toujours la même valeur, indépendamment du contenu du MPointArray(). :slowclap:</p>

<p>Et la dernière ligne stock le hash pour le chemin complet du nœud.</p>

<p>Et le reste de la boucle c’est tout pareil&nbsp;! <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>Ne change que le type des tableaux (<a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_int_array.html" hreflang="en">MIntArray()</a> et <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_float_array.html" hreflang="en">MFloatArray()</a>) ainsi que les méthodes pour récupérer les informations (<a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_fn_mesh.html#a2f2e041f01dc1ec3648002e2524fbfbc" hreflang="en">getVertices()</a>, <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_fn_mesh.html#aa41349e47d082451f1744cff85412159" hreflang="en">getUVs()</a>, <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-SDK/cpp_ref/class_m_fn_mesh.html#abe6b4afaec85f867401eb3658c3e5459" hreflang="en">getAssignedUVs()</a>).</p>

<p>Juste un petit <em>assert</em> (que j’utilise souvent) pour expliquer que je m’attends à ce que le tableau contenant les valeurs de U et de V fassent la même taille.</p>

<p>On passe à la suite&nbsp;:</p>

<pre>
<code class="language-python"># the hash of the hashes
h_total = {}

for full_path in h_pt.keys():
    
    h_total[full_path] = hash((h_pt[full_path],
                               h_vtx_counts[full_path],
                               h_vtx_ids[full_path],
                               h_uvs[full_path],
                               h_uv_counts[full_path],
                               h_uv_ids[full_path]))</code></pre>

<p>Viens l’avant-dernière boucle qui consiste, comme le commentaire l’indique, à générer le «&nbsp;hash des hash&nbsp;». En effet, bien qu’on ait séparé les hashes par type de tableau (position des sommets, topologie, UVs), ce qui peut être très utile pour mettre le doigt sur les parties qui ne s’accommode pas aux autres, je vous propose de générer un hash final, par nœud.</p>

<p>On génère donc un itérateur avec tous les hash, qu’on envoie dans un hash.</p>

<p>Et pour finir&nbsp;:</p>

<pre>
<code class="language-python">path_per_h = collections.defaultdict(set)

for full_path, h in h_total.iteritems():
    
    path_per_h[h].add(full_path)</code></pre>

<p>On inverse notre dictionnaire avec, en guise de clef, le hash et en guise de valeur, un <em>set()</em> des chemins des nœuds avec ce hash. Ce qui nous donne un dictionnaire qui ressemble à ça&nbsp;:</p>

<pre>
<code class="language-python">h_pt = {1574633: set(['|pSphere1|pSphereShape1',
                      '|pSphere2|pSphereShape2']),
        1657615: set(['|pSphere3|pSphereShape3',
        ...}</code></pre>

<p>Et on peut sélectionner les nœuds par hash comme ça&nbsp;:</p>

<pre>
<code class="language-python">mc.select(list(path_per_h[path_per_h.keys()[1]]))</code></pre>

<p><img alt="" class="media" src="media/73b22cbc.sanity_check_modeleur_hash.jpg" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_17_instance_implicite_alembic/sanity_check_modeleur_hash.jpg" style="margin: 0px auto; display: table; width: 480px; height: 601px;" /></p>

<p>Conclusion</p>

<p>J’espère que le principe des instances implicites des fichiers Alembics est plus clair pour vous maintenant. Si vous êtes à l’aise en script, je vous invite à essayer de structurer ces informations dans une petite interface de sélection pour aider vos modeleurs. Ce n’est pas un petit boulot mais sur un projet un peu ambitieux ça peut valoir le coup.</p>

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


feed_id: urn:md5:ddcba8426cf4b66399d43e6179ae4309
title: Exécuter du Python au démarrage de Guerilla
uri: Exécuter-du-Python-au-démarrage-de-Guerilla
url: http://www.fevrierdorian.com/blog/post/2016/06/25/Executer-du-Python-au-demarrage-de-Guerilla
content:
    <p><img alt="" class="media" src="media/457ea340.guerilla.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/guerilla.png" style="float: left; margin: 0 1em 1em 0;" />Un peu comme Maya et son <em>userSetup.mel</em>, <a href="http://www.fevrierdorian.com/blog/post/2016/06/25/www.guerillarender.com/" hreflang="en">Guerilla</a> permet d’exécuter des scripts au démarrage, mais que du lua. Voici un petit truc rapide pour exécuter du Python&nbsp;:</p>

<p>Si vous allez dans le nœud <em>Preferences</em>, dans <em>LocalSettings/Directories/User Plugins</em> vous pouvez définir une liste de chemins (<em>paths</em>).</p>

<p>Sachez que tous les fichiers <a href="http://www.lua.org/" hreflang="en" title="Site web de Lua">lua</a> présents dans ces différents chemins seront exécutés au démarrage de Guerilla. Sachez aussi que le lua de Guerilla intègre <a href="http://labix.org/lunatic-python" hreflang="en">une passerelle</a> vers Python. Ainsi, si votre fichier lua contient&nbsp;:</p>

<pre>
<code class="language-javascript">require('python')
python.execute('import myModule; myModule.doit();')</code></pre>

<p>Celui-ci exécutera le code Python&nbsp;:</p>

<pre>
<code class="language-python">import myModule
myModule.doit()</code></pre>

<p>Vous savez maintenant comment exécuter du Python au démarrage de Guerilla&nbsp;! <img src="media/2e1ef912.bravo.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/bravo.gif" alt=":bravo:" class="smiley" /></p>


feed_id: urn:md5:716b6b2c0f8364f655382322b216308e
title: Des boutons appelants la même fonction avec des arguments différents grâce à functools.partial()
uri: Des-boutons-appelants-la-même-fonction-avec-des-arguments-différents
url:
http://www.fevrierdorian.com/blog/post/2017/06/18/Des-boutons-appelants-la-m%C3%AAme-fonction-avec-des-arguments-diff%C3%A9rents-gr%C3%A2ce-%C3%A0-functools.partial%28%29

content:
<p><img alt="" class="media" src="media/d254717d.bouton_partial_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/bouton_partial_tn.png" style="float: left; margin: 0 1em 1em 0;" />Un des premiers trucs qu’on souhaite faire quand on commence à scripter dans Maya ce sont les boutons pour exécuter nos scripts chéris. <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>Naturellement, vous êtes allé dans <a href="http://help.autodesk.com/view/MAYAUL/2017/ENU/" hreflang="en">la documentation</a>, section <em>Technical Documentation</em>, puis <em>Python Commands</em>, avez cherché «&nbsp;button&nbsp;» et êtes tombé <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/CommandsPython/button.html" hreflang="en">là-dessus</a>. Ensuite vous êtes allé en bas de la page, vous avez copié-collé l’exemple et avez commencez à modifier votre script. Félicitation, c’est exactement comme ça qu’il faut faire. <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>Sauf que comme nous allons le voir, on bute vite sur un problème. Aujourd’hui je vous propose un tutoriel pour pouvoir utiliser une même fonction appelée avec différents arguments suivant les boutons.</p>    <h4>Démarrage</h4>

<p>Voici une version simplifiée de l’exemple fourni par la documentation de la commande <em>button</em>&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

def toto(*args):
  print "toto", args

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Button 1', command=toto)
mc.showWindow()</code></pre>

<p>On va partir de la. Ouvrez votre <em>script editor</em> et exécutez ce magnifique script&nbsp;:</p>

<p><img alt="" class="media" src="media/d89d0c23.bouton_partial_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/bouton_partial_001.png" style="margin: 0px auto; display: table; width: 432px; height: 465px;" />Et l’explication ligne à ligne&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc</code></pre>

<p>On importe le module <em>maya.cmds</em> sous un diminutif <em>mc</em>.</p>

<pre>
<code class="language-python">def toto(*args):
  print "toto", args</code></pre>

<p>Une fonction nommée <em>toto</em> qui affiche le mot «&nbsp;toto&nbsp;» ainsi que les arguments qu’on lui a passée. Pourquoi des arguments&nbsp;? Je l’explique plus loin. <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>Et pour la suite&nbsp;:</p>

<pre>
<code class="language-python">mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Button 1', command=toto)
mc.showWindow()</code></pre>

<ul>
	<li>Une fenêtre de 150 pixels de large</li>
	<li>Un agencement en colonne ajustable</li>
	<li>Un bouton nommé «&nbsp;Button 1&nbsp;» qui exécute la fonction <em>toto</em> quand on clique dessus</li>
	<li>L’ordre d’afficher la fenêtre</li>
</ul>

<h4>L’argument de toto</h4>

<p>Vous remarquerez que la fonction <em>toto()</em> prend des arguments. C’est assez fréquent dans les <a href="https://fr.wikipedia.org/wiki/Fonction_de_rappel" hreflang="fr">fonctions de rappel</a> (<em>callbacks</em> en anglais), petit noms donné à des fonctions qui sont passées à d’autres fonctions en vu de les exécuter (ici, l’argument <em>command</em> du bouton, voir plus bas). Ne vous inquiétez pas avec ça pour le moment, sachez juste que, quand un bouton exécute la commande qu’on lui à donnée, il lui passe un argument, il faut donc que la fonction (ici <em>toto()</em>) prenne cet argument ou vous aurez un message assez clair.</p>

<p>Comme vous ne me croyez jamais ( <img src="media/1584dce3.yeoh.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/yeoh.gif" alt=":dentcasse:" class="smiley" /> ), essayez d’exécuter ça et de cliquer sur le bouton&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

def toto():
  print "toto"

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Button 1', command=toto)
mc.showWindow()</code></pre>

<p>Notez que la fonction <em>toto()</em> ne prends plus d’argument. <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>En toute logique vous aurez&nbsp;:</p>

<pre>
<code class="language-python"># Error: toto() takes no arguments (1 given)</code></pre>

<p>Le bouton a tenté de passer un argument à la fonction <em>toto()</em> qui a planté car, ici, elle ne pouvait recevoir aucun argument.</p>

<p>Bien, vous me croyez&nbsp;? On peut avancer maintenant&nbsp;? <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>

<h4>Appliquer le <em>smooth preview</em> sur toute la scène</h4>

<p>Imaginons que vous avez une fonction qui change la valeur de <em>smooth preview</em> sur toute la scène (au lieu de faire une sélection et d’appuyer sur 0 et 3 à chaque fois):</p>

<pre>
<code class="language-python">def smooth_preview(mode):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)</code></pre>

<p>Cette commande fait une boucle sur tous les nœuds de type mesh et met leur attribut <em>displaySmoothMesh</em>&nbsp;à la valeur du <em>mode</em> donné en argument.</p>

<blockquote>
<p>Notez que l’attribut en question (<em>displaySmoothMesh</em>) ne se trouve pas aussi facilement que les autres (il n’apparait pas dans le <em>script editor</em> quand on le change).</p>
</blockquote>

<p>Mais allez-y, essayez dans votre scène ou faites en une nouvelle&nbsp;:</p>

<pre>
<code class="language-python">import random

for i in range(100):
    mc.polyCube()
    mc.move(20*random.random()-10, random.random(), 20*random.random()-10)</code></pre>

<p>Je ne résiste jamais à l’envie de faire mumuse avec le module <a href="https://docs.python.org/2/library/random.html" hreflang="en">random</a>&nbsp;:</p>

<p><a class="media-link" href="media/3958e56b.bouton_partial_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/bouton_partial_002.png"><img alt="" class="media" src="media/82655fef..bouton_partial_002_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/.bouton_partial_002_m.png" style="margin: 0px auto; display: table; width: 560px; height: 296px;" /></a></p>

<p style="text-align: center;">Oui, bon, je sais c’est pas l’propos mais-reuh-n'a-fout'-c'est-mon-blog-j'fais-c'que-j'veux<sup>(tm)</sup>. <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /></p>

<p>Maintenant exécutez la fonction que nous avons créée précédemment avec différents modes, l’un après l’autre&nbsp;:</p>

<pre>
<code class="language-python">smooth_preview(2)
smooth_preview(1)
smooth_preview(0)</code></pre>

<p>Et mes cubes deviennent des sphères&nbsp;:</p>

<p><a class="media-link" href="media/b7f316ff.bouton_partial_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/bouton_partial_003.png"><img alt="" class="media" src="media/0fb321a4..bouton_partial_003_m.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/.bouton_partial_003_m.png" style="margin: 0px auto; display: table; width: 560px; height: 241px;" /></a></p>

<p>Notez que la valeur ne correspond pas à la subdivision mais à un mode de <em>preview</em>&nbsp;:</p>

<ul>
	<li>0, la touche 0 ou 1, désactive le <em>smooth preview</em>.</li>
	<li>1, la touche 2, active le <em>smooth preview</em> en mode cage.</li>
	<li>2, la touche 3, active le <em>smooth preview</em> sans les cages.</li>
</ul>

<p>Bon, c’est super, maintenant vous aimeriez que cette fonction soit appelée avec ses différentes valeurs par trois boutons. <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>Assez intuitivement, vous auriez tendance à écrire ça&nbsp;:</p>

<pre>
<code class="language-python">def smooth_preview(mode):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Smooth off', command=smooth_preview(0))
mc.button(label='Smooth cage', command=smooth_preview(1))
mc.button(label='Smooth on', command=smooth_preview(2))
mc.showWindow()</code></pre>

<p>Vous vous doutez que ça ne va pas marcher pas vrai&nbsp;? <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>Ne vous inquiétez pas, exécutez le script.</p>

<pre>
<code class="language-python"># Error: Invalid arguments for flag 'command'.  Expected string or function, got NoneType</code></pre>

<p>Bim&nbsp;! <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /></p>

<p>Alors alors, que vient-il de se passer&nbsp;? Le message dit que l’argument <em>command</em> s’attendait à une chaine de caractère ou une fonction et il a reçu un truc de type <em>NoneType</em>. Sachant qu’en Python, le seul truc de type <em>NoneType</em> c’est une variable <em>None</em>, il semble qu’on ait passé <em>None</em> à l’argument <em>command</em>.</p>

<p>Que fait exactement notre script&nbsp;? En fait, il exécute les appels aux fonctions <em>smooth_preview(0)</em> (puis 1 et 2) et donne sa valeur de retour à l’argument <em>command</em>. Mais comme la fonction ne renvoie rien (il n’y a pas de <em>return</em> dedans), c’est comme si elle renvoyait <em>None</em>…</p>

<p>En fait, si vous reprenez votre argument toto l’argument</p>

<p>Mince, mais alors comment fait-on&nbsp;?</p>

<p>C’est là que le module <a href="https://docs.python.org/2/library/functools.html" hreflang="en">functools</a> et sa commande <a href="https://docs.python.org/2/library/functools.html#functools.partial" hreflang="en">partial()</a> entre en jeu. <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /></p>

<h4>functools.partial()</h4>

<p>Pour bien comprendre ce qu’on va essayer de faire, reprenons l’exemple avec la fonction <em>toto()</em>&nbsp;:</p>

<pre>
<code class="language-python">mc.button(label='Button 1', command=toto)</code></pre>

<p>En fait, ici, on passe la fonction <em>toto()</em> à l’argument <em>command </em>sous la forme d’un «&nbsp;objet appelable&nbsp;» (<em>callable object</em> en anglais). Notez que la variable <em>toto</em> n’a pas de parenthèses. On passe donc la fonction <em>toto()</em> mais sans l’appeler. Pour imager un peu le truc&nbsp;: Quand on va cliquer sur le bouton, <em>command</em> va prendre ce qu’on lui a donné, ajouter "()" puis l’exécuter.</p>

<p>Et <em>partial()</em> là-dedans&nbsp;? Il permet tout simplement de faire des «&nbsp;objets appelables&nbsp;» à partir d’une fonction et de ses arguments. Voici un exemple d’utilisation de notre cas. Essayez de l’exécuter, puis, tout particulièrement, les trois dernières lignes, une à une&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

import functools

def smooth_preview(mode):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)

smooth_preview_0 = functools.partial(smooth_preview, 0)
smooth_preview_1 = functools.partial(smooth_preview, 1)
smooth_preview_2 = functools.partial(smooth_preview, 2)

smooth_preview_0()  # fait exactement la meme chose que smooth_preview(0)
smooth_preview_1()  # fait exactement la meme chose que smooth_preview(1)
smooth_preview_2()  # fait exactement la meme chose que smooth_preview(2)</code></pre>

<p>Comme indique dans les commentaires, les trois dernières lignes sont des fonctions créées par partial qui appel la fonction <em>smooth_preview</em> avec un argument.</p>

<p>On a donc créé des «&nbsp;objets appelables&nbsp;»…</p>

<p>La suite vous la connaissez, il suffit de passer ses objets à la commande et le tour et joue&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

import functools

def smooth_preview(mode):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)

smooth_preview_0 = functools.partial(smooth_preview, 0)
smooth_preview_1 = functools.partial(smooth_preview, 1)
smooth_preview_2 = functools.partial(smooth_preview, 2)

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Smooth off', command=smooth_preview_0)
mc.button(label='Smooth cage', command=smooth_preview_1)
mc.button(label='Smooth on', command=smooth_preview_2)
mc.showWindow()</code></pre>

<p>Pas vrai&nbsp;?</p>

<p>Non en fait. <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" /> Un dernier (je vous le promets&nbsp;!) problème subsiste. Bon, on ne va pas vous faire exécuter le code, voici le message d’erreur si vous essayez de cliquer sur un des trois boutons&nbsp;:</p>

<pre>
<code class="language-python"># Error: smooth_preview() takes exactly 1 argument (2 given)</code></pre>

<p>Ça ne vous rappel rien&nbsp;? <img src="media/990690f6.whistle2.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/whistle2.gif" alt=":jdicajdirien:" class="smiley" /> La fonction de rappel donne toujours un second argument. Il faut donc que la fonction en question (<em>smooth_preview()</em>) soit capable d’ingérer cet argument&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

import functools

def smooth_preview(mode, *args):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)

smooth_preview_0 = functools.partial(smooth_preview, 0)
smooth_preview_1 = functools.partial(smooth_preview, 1)
smooth_preview_2 = functools.partial(smooth_preview, 2)

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Smooth off', command=smooth_preview_0)
mc.button(label='Smooth cage', command=smooth_preview_1)
mc.button(label='Smooth on', command=smooth_preview_2)
mc.showWindow()</code></pre>

<p>Notez le <em>*args</em> en argument de la fonction <em>smooth_preview()</em>.</p>

<p>Ne me regardez pas comme ça, vous pouvez y aller&nbsp;! <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><img alt="" class="media" src="media/e3fdbb13.bouton_partial_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_06_26_bouton_partial/bouton_partial_004.png" style="margin: 0px auto; display: table; width: 457px; height: 303px;" /></p>

<p>Allez-y, cliquez, vous l’avez bien mérité! <img src="media/c58dc6c3.sauteJoie.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/sauteJoie.gif" alt=":sauteJoie:" class="smiley" /></p>

<h4>On nous cache des choses</h4>

<p>Peut-être parmi vous se cache certains qui ont pu remarquer, durant ce tutoriel, un indice sur une autre façon de faire. Vous vous rappelez du message d’erreur de l’argument invalide&nbsp;?</p>

<pre>
<code class="language-python"># Error: Invalid arguments for flag 'command'.  Expected string or function, got NoneType</code></pre>

<p>"<em>Expected string or function</em>"… Mhhh donc si on met des chaines de caractère (<em>string</em>) sur l’argument <em>command</em> est-ce que…&nbsp;:</p>

<pre>
<code class="language-python">import maya.cmds as mc

def smooth_preview(mode):
    for mesh_node in mc.ls(type='mesh'):
        mc.setAttr(mesh_node+'.displaySmoothMesh', mode)

mc.window(width=150)
mc.columnLayout(adjustableColumn=True)
mc.button(label='Smooth off', command="smooth_preview(0)")
mc.button(label='Smooth cage', command="smooth_preview(1)")
mc.button(label='Smooth on', command="smooth_preview(2)")
mc.showWindow()</code></pre>

<p>Fichtre ça marche aussi&nbsp;! <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>Suis-je maso&nbsp;? Méchant&nbsp;? Ou tête en l’air pour être passé à coté depuis tout ce temps&nbsp;? <img src="media/7df0b8d8.perplex.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/perplex.gif" alt=":perplex:" class="smiley" /></p>

<p>Non. En fait la commande <em>button</em> est un prétexte car&nbsp;:</p>

<ul>
	<li>Quand vous avez des fonctions éparpillées un peu partout dans vos fichiers, un appel en chaine de caractère (comme sur le dernier exemple) ne garantit pas que la fonction existe.</li>
	<li>La méthode en chaine de caractère ne fonctionne pas avec des bibliothèques d’interface plus évoluées (tel que PyQt ou PySide).</li>
	<li>D’une manière générale, functools.partial() est LA méthode servant à fabriquer un «&nbsp;objet appelable&nbsp;» depuis une fonction et ses arguments.</li>
</ul>

<p>Bref, le but était de vous montrer une fonction très utile dans un cas concret, histoire que vous sachez que ça existe et à quoi ça sert. <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>A bientôt&nbsp;!</p>

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


feed_id: urn:md5:fe96f46d7e3b6bef30e736ee3252f2a1
title: Le unités de mesure des logiciels
uri: Le-unités-de-mesure-des-logiciels
url: http://www.fevrierdorian.com/blog/post/2018/08/11/Le-unit%C3%A9s-de-mesure-des-logiciels
content:
<p><img alt="" class="media" src="media/574b12a2.houdini_unit_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2018_08_09_unite_logiciels/houdini_unit_tn.png" style="float: left; margin: 0px 1em 1em 0px; width: 150px; height: 150px;" />Un billet pour expliquer un truc assez bête mais qui fait perdre la tête&nbsp;à pas mal de gens tant il est obscur. Je vais parler de la notion d’unité de mesure dans les logiciels, ou pourquoi elle n’aurait peut-être jamais dû exister. <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>En début de production on tente souvent de se mettre d’accord sur un référentiel de mesure. La grande question est : « Quelle distance fait 1 ? », C’est-à-dire, quand un objet se déplace de 1 dans mon logiciel, à combien cela correspond-il dans le monde réel ? <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>Avant de rentrer dans le vif du sujet, voici un topo rapide des différents référentiels d’unité utilisés.</p>

<h3>1 Unité = 1 mètre</h3>

<p>Cette mesure permet de gérer de grands espaces mais fait souvent pester l’équipe <em>modeling props</em> qui, dans le cas d’un projet manipulant des dimensions de taille humaine, va se retrouver avec des 0.15, 0.47, etc pour dimensionner ses objets.</p>

<h3>1 Unité = 1 centimètre</h3>

<p>Cette mesure, pratique pour l’équipe <em>modeling</em> devient délirante lors de décors de plusieurs km. 1 km = 100 000 cm… À même pas 500 m vous risquez d’avoir des erreurs dû à la perte de précision des chiffres flottants dans les grandes valeurs (en version courte : Plus le chiffre avant la virgule est grand, moins il y a de place pour le chiffre après la virgule <img src="media/6a010deb.reflechi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/reflechi.gif" alt=":reflechi:" class="smiley" /> ).</p>

<h3>Le meilleur des deux mondes ?</h3>

<p>Un référentiel que j’ai souvent observé et qui est un bon compromis est 1 unité du logiciel = 10 cm dans le monde réel (1 dm).</p>

<p>Ça permet d’avoir un bon équilibre entre des unités proches de ce qui est manipulable par les humains, 1 mètre du monde réel correspondant à 10 unités, et des unités larges de décor.</p>

<h3>Chouette ! On va tous configurer nos logiciels !</h3>

<p>Et bim ! Dans le panneau ! <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>La chose à comprendre est que, dans de nombreux cas, les nombres sont stockés <em>sans</em> référentiel. Ainsi, si vous avez un Alembic avec un cube de 1 sur 1, il est impossible de dire s’il s’agit de mètres ou de centimètres. C’est juste un cube de 1 sur 1.</p>

<p>Alors forcement, vous me répondez : « Bah si ! J’ai dit à mes équipes que 1 unité = 1 m, donc le cube est à 1 m. »</p>

<p>Vous en êtes sur ? <img src="media/9ee7eab7.hihi.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/hihi.gif" alt=":hihi:" class="smiley" /></p>

<ul>
	<li>Ouvrez votre Maya</li>
	<li>Passez l’unité de mesure en mètre (Dans <em>Preferences</em>/<em>Settings</em>, voir image)</li>
	<li>Faites un cube de 1 sur 1</li>
	<li>Exportez-le en Alembic</li>
</ul>

<p><img alt="unite dans maya" class="media" src="media/febe6851.maya_unit_cm.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2018_08_09_unite_logiciels/maya_unit_cm.png" style="margin: 0px 1em 1em 0px; width: 589px; height: 377px;" /></p>

<p>Si vous aviez les capacités d’inspecter les valeurs à l’intérieur de votre Alembic, vous verriez… 100 sur 100.</p>

<p>« Mais pourquoi ?! <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" />  » me demandez-vous ? Après tout, vous avez créé un cube de 1 sur 1, pas de 100 sur 100, vous l’avez vu, de vos yeux vu ce « 1 ». <img src="media/6e363cce.casseTeteMur.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/casseTeteMur.gif" alt=":casseTeteMur:" class="smiley" /></p>

<p>Et bien tout simplement parce que l’unité <em>native</em> de Maya c’est le <em>centimètre</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>

<p>Si vous le réimportez dans Maya (configuré en mètre), il fera 1 sur 1, bien que les valeurs stockées soit 100 sur 100.</p>

<p>On a donc quelque chose d’assez déroutant et un peu dangereux : Si vous modifiez la mesure par defaut, <strong>les unités vues ne sont pas les unités stockées</strong>. Ainsi, si vous faites un décor de 1 000 m, vous aurez des soucis de précision, car les valeurs stockées dans l’Alembic et la géométrie seront en fait beaucoup plus importantes.</p>

<p>Vous l’aurez compris, dans Maya, 1 unité est <strong>toujours</strong> égale a 1 cm, le reste, ce n’est que de l’affichage. Dès que vous changez la mesure, vous entrez dans des prises de tête sans fin entre vos graphistes : « Mais puisque je te dis que j’ai exporté un cube de 1 sur 1 regarde ! Là dans Maya c’est 1 sur 1 ! C’est ton logiciel qui fait n’importe quoi en important un cube de 100 sur 100 ! Faut que t’appelles le support ! Moi c’est bon et toi t’as tort ! ». Vous voyez le genre. <img src="media/7df0b8d8.perplex.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/perplex.gif" alt=":perplex:" class="smiley" /></p>

<p>Quand on quitte son unité native, Maya créé aussi toutes sortes de nœuds <a href="http://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/Nodes/unitConversion.html" hreflang="en">unitConversion</a>, et bon nombre de valeurs par défaut deviennent absurdes.</p>

<h3>Ne touchez à rien !</h3>

<p>La plupart des logiciels gèrent très mal les unités de mesure qui ne sont pas les leur. Il est donc conseillé de ne <strong>jamais</strong> toucher aux unités de mesure native d’un logiciel, par contre, il faut connaître la différence de référentiel entre les logiciels car, devinez quoi ?… Il n’y a pas de standard dans l’industrie ! <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>Par exemple :</p>

<ul>
	<li>L’unité native de Maya est le <em>cm</em> (1 unité dans Maya, vaut 1 cm dans le monde réel).</li>
	<li>L’unité native de Houdini est le <em>m</em> (1 unité dans Houdini, vaut 1 m dans le monde réel).</li>
</ul>

<p>(Tu sens la prod qui va <em>très</em> bien se passer. <img src="media/94b50729.slow_clap.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/slow_clap.gif" alt=":slow_clap:" class="smiley" /> )</p>

<p>Ça implique une chose : Toujours avoir en tête à quoi correspond « 1 » quand on le voit dans les Alembics, les AOV de position, les fichiers textes de position, etc. En gros, combien vaut une distance de « 1 » dans les données que vous produisez.</p>

<p>Il vaut mieux penser les unités comme des données et non comme des mesures, chaque logiciel ayant sa propre façon de percevoir cette unité.</p>

<p>En pratique, Houdini ingurgite principalement des Alembics :</p>

<ul>
	<li>Vous mettez un nœud de <em>scale</em> <strong>après</strong> votre nœud de lecture Alembic (récupération de l’animation)</li>
	<li>Vous mettez un nœud de <em>scale</em> inversé <strong>avant</strong> votre nœud d’écriture d’Alembic (livraison des FX)</li>
</ul>

<p>Et vous êtes tranquille. <img src="media/7a81a9b4.petrus.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/petrus.gif" alt=":petrus:" class="smiley" /></p>

<p>Notez que vous pouvez gérer l’unité de mesure de Houdini dans les préférences : <em>Hip File Options</em>. Il y est précisé que seul certains paramètres des <em>DOPs</em> (<em>Dynamic OPerators</em>) semble se soucier de l’unité de mesure. <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>C’est donc souvent autour de Maya que les choses tournent. Quand vous vous dites « 1 unité = 1 trucomètre », pensez « 1 cm Maya (mesure native) = 1 trucomètre ».</p>

<p>Houdini va pouvoir se débrouiller et bien souvent le problème viendra des logiciels qui fabriquent des objets en dehors de Maya (ZBrush, etc.). Une fois dans Maya ses objets permettront de définir la différence de référentiel par rapport à Maya (et donc, la différence de référentiel par rapport à votre unité).</p>

<p>TL;PL : Laissez Maya dans son unité de mesure native et travaillez comme si 1 unité Maya = 10 cm.</p>

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


feed_id: urn:md5:78564d77086150c14424b0e24236831c
title: Récupérer le nom d’un attribut caché dans Maya
uri: Récupérer-le-nom-d-un-attribut-caché-dans-Maya
url:
http://www.fevrierdorian.com/blog/post/2018/08/14/R%C3%A9cup%C3%A9rer-le-nom-d%E2%80%99un-attribut-cach%C3%A9-dans-Maya

content:
<p><img alt="" class="media" src="media/96f184a4.attribute_name_maya_tn.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_tn.png" style="float: left; margin: 0px 1em 1em 0px; width: 150px; height: 150px;" />Il n’est pas rare, quand on script, de devoir récupérer le nom d’un attribut en vu de l’utiliser, plus tard, dans ses scripts. D’une manière générale, il suffit de modifier l’attribut, d’aller dans le <em>Script Editor</em> puis de trouver la ligne qui fait le <em>setAttr</em> sur l’attribut qui nous intéresse. <img src="media/7a81a9b4.petrus.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/petrus.gif" alt=":petrus:" class="smiley" /></p>

<p>Vous remarquerez toutefois que cette méthode ne fonctionne pas avec certains attributs. Il arrive, en effet, que la commande <em>setAttr</em> correspondante ne soit pas affichée dans le <em>Script Editor</em>. Je vous propose ici la méthode que j’utilise pour aller trouver les attributs «&nbsp;timides&nbsp;». <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>Avant de commencer, sachez qu’on ne peut pas parler de méthode à proprement parler tant il s’agit plutôt d’un bricolage. <img src="media/7df0b8d8.perplex.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/perplex.gif" alt=":perplex:" class="smiley" /></p>

<p>Première chose, trouvons un attribut qui n’affiche pas de commande <em>setAttr</em> dans le <em>Script Editor</em>. C’est le cas de l’attribut <em>Smooth Mesh Preview</em> des nœuds de type <em>mesh</em>.</p>

<p><img alt="" class="media" src="media/c6ff7ce7.attribute_name_maya_001.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_001.png" style="margin: 0px auto; display: table; width: 291px; height: 109px;" /></p>

<p><img alt="" class="media" src="media/25f63b8c.attribute_name_maya_002.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_002.png" style="margin: 0px auto; display: table; width: 337px; height: 82px;" /></p>

<p>Essayez de le modifier, rien ne s’affiche. Vous pouvez activer <em>Echo All Commands</em>, l’attribut apparait une seule fois sur les 257 lignes qui s’affichent. Difficile de le trouver. <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>Ce n’est donc pas la bonne méthode. Voici la mienne :</p>

<p>Le principe consiste à sauver deux fois la scène, une fois avec l’attribut dans un état, et l’autre fois avec l’attribut dans un autre état et de faire une différence ligne a ligne via un logiciel spécialisé. Allons-y ! <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>Laissez l’attribut non modifié puis sauvez la scène en ASCII :</p>

<p><img alt="" class="media" src="media/dcde5bb5.attribute_name_maya_003.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_003.png" style="margin: 0px auto; display: table; width: 209px; height: 121px;" /></p>

<p><img alt="" class="media" src="media/a2de1970.attribute_name_maya_004.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_004.png" style="margin: 0px auto; display: table; width: 342px; height: 132px;" /></p>

<p>Contrairement au binaire, ce mode permet de sauver sa scène sous forme d’un gros script lisible pas tout bon éditeur de texte (ouvrez la scène sauvegardée avec votre éditeur de texte favoris puis jugez) .</p>

<p>N’oubliez pas de cocher l’option <em>Use full names for attributes on nodes</em>. Comme vous le devinez, cette option affiche les noms complets des attributs. <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><img alt="" class="media" src="media/c5b213a5.attribute_name_maya_005.png" data-original-source="http://www.fevrierdorian.com/blog/public/billets/2017_07_09_attribute_name_maya/attribute_name_maya_005.png" style="margin: 0px auto; display: table; width: 534px; height: 89px;" /></p>

<p>Sauvez une scène avec l’attribut <em>Smooth Mesh Preview</em> désactivé et une autre avec l’attribut activé.</p>

<p>Ensuite, ouvrez votre outil de visualisation de différence de fichier (diff ou <a href="https://meldmerge.org/">Meld</a> sous Linux, <a href="https://winmerge.org/?lang=fr">WinMerge</a> sous Windows, FileMerge sous Mac).</p>

<p>En version ligne de commande, sous Linux, cela donne :</p>

<pre>
<code class="language-diff">$ diff /home/narann/test.ma /home/narann/test2.ma
2,3c2,3
&lt; //Name: test.ma
&lt; //Last modified: Fri, Jul 09, 2017 21:13:45 PM
---
&gt; //Name: test2.ma
&gt; //Last modified: Fri, Jul 09, 2017 21:13:57 PM
75a76
&gt;       setAttr ".displaySmoothMesh" 2;
188c189
&lt; // End of test.ma
---
&gt; // End of test2.ma
</code></pre>

<p>Si on enlève les dates en début de fichier et la dernière ligne, on obtient :</p>

<pre>
<code class="language-diff">&gt;       setAttr ".displaySmoothMesh" 2;</code></pre>

<p>L’attribut s’appelle donc « displaySmoothMesh » et n’est pas un booléen mais un entier. <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>On ne va quand même pas s’arrêter ici vous ne croyez pas ? Vous n’avez pas envi de connaitre les valeurs possibles de cet attribut ? <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>Vérifions son type :</p>

<pre>
<code class="language-python">import maya.cmds as mc

print mc.getAttr("pSphereShape1.displaySmoothMesh", type=True)
# enum</code></pre>

<p>Donc c’est un <em>enum</em>. Pour récupérer la liste des valeurs possibles via un <em>enum</em> il faut utiliser la commande <a href="http://help.autodesk.com/cloudhelp/2016/ENU/Maya-Tech-Docs/CommandsPython/attributeQuery.html#flaglistEnum">attributeQuery</a> avec l’argument <em>listEnum</em> :</p>

<pre>
<code class="language-python">print mc.attributeQuery("displaySmoothMesh", node="pSphereShape1", listEnum=True)
# [u'Base Mesh Only:Base and Smooth Mesh:Smooth Mesh Only']</code></pre>

<p>On a donc :</p>

<ul>
	<li><em>Base Mesh Only</em> (index 0)</li>
	<li><em>Base and Smooth Mesh</em> (index 1)</li>
	<li><em>Smooth Mesh Only</em> (index 2)</li>
</ul>

<p>Bon, ça c’était cadeau, histoire de pousser le truc un peu plus loin mais l’idée de base, c’est de faire une différence entre les fichiers. <img src="media/94b50729.slow_clap.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/slow_clap.gif" alt=":slow_clap:" class="smiley" /></p>

<p> </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:a7590f03534a62306e3a45057e1e6e98
title: La ferme de rendu (première partie) : Les jobs
uri: La-ferme-de-rendu-(première-partie)-Les-jobs
url: http://www.fevrierdorian.com/blog/post/2018/08/18/La-ferme-de-rendu-premi%C3%A8re-partie-Les-jobs
content:
<p>L’exécution de tâches (jobs) sur des gestionnaires de tâche (job manger, render manager, farm manager) sont courant dans énormément de secteurs liés à l’informatique. Que ce soit la compilation de code, l’exécution et le rapport de tests unitaires, le calcul financier, ça pullule. <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>Internet regorge d’informations et de <s>bonnes</s> pratiques liées à l’exécution et la gestion de tâches sur des fermes de calcul. Pourtant, beaucoup de ses informations sont trop génériques et passe à côté de certains problèmes de fond, propre à notre industrie. <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>Je voudrais, modestement et de façon totalement subjective, faire un retour d’expérience autour de l’organisation et la structure du code de ferme de calcul. Notez que je n’affirme pas avoir <em>LA</em> bonne méthode pour gérer les fermes de la façon la plus efficace qui soit, mais j’aborde et commente différentes problématiques que j’ai pu rencontrer.</p>    <p>Je vais passer en revu et commenter différentes choses. Je tenterais, dans les parties suivantes, d’établir quelques règles et guides à suivre puis je finirais sur une explication de l’organisation du code. <img src="media/48a6a7fc.banane-jaune.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/banane-jaune.gif" alt=":banaeyouhou:" class="smiley" /></p>

<h3>Terminologie</h3>

<p>Avant de commencer je dois expliciter certains termes que je vais employer. <img src="media/e9df993c.redface.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/redface.gif" alt=":redface:" class="smiley" /></p>

<h4>Job manager</h4>

<p>C’est le cerveau. Il s’agit du « serveur » :</p>

<ul>
	<li>Il stocke tous les <em>jobs</em>.</li>
	<li>Il gère les dépendances entre les jobs en les envoyant dans le bon ordre et en attendant certains jobs avant d’en exécuter d’autres.</li>
	<li>Il communique avec les <em>workers</em> en leur envoyant les <em>jobs</em>.</li>
	<li>Il met à jour les statuts (pause/en cours/erreur).</li>
	<li>Il gère les limites de licence pour s’assurer que les <em>jobs</em> ont toujours les licences qu’ils exigent.</li>
	<li>etc.</li>
</ul>

<p>Le <em>job manager</em> embarque souvent une base de donnée (PostgreSQL, MySQL, etc.) et ne doit jamais être indisponible pour les <em>workers</em>. <img src="media/67569af1.siffle.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/siffle.gif" alt=":siffle:" class="smiley" /></p>

<h4>Worker</h4>

<p>« Travailleur » en français. Il s’agit d’un petit programme qui tourne et communique avec le <em>job manager</em> pour recevoir et exécuter des <em>jobs</em>. On exécute souvent un <em>worker</em> par machine de calcul, mais il n’est pas rare d’exécuter plusieurs <em>workers</em> sur une seule machine. Parfois pour des raisons de licences liées à la machine (une machine Yeti, plusieurs exports de <em>.fur</em>), parfois pour des raisons d’équilibre de charge. Ainsi, plusieurs petits <em>jobs</em> qui demandent peu de ressources peuvent n’exécuter en parallèle sur une seule machine. Notez qu’un gestionnaire de ferme évolué permet de gérer intelligemment les ressources d’une machine et de lancer plus ou moins de <em>jobs</em> suivant les exigences du <em>job</em> (licence, mémoire, etc.).</p>

<h4>Job</h4>

<p>Bien que le terme français « tâche » existe, il fait souvent spécifiquement référence, en production, à la tâche du graphiste (traduction de « task », qu’on peut retrouver dans Shotgun). J’utilise donc le terme de « <em>job</em> » pour faire référence à ce que doit exécuter un <em>worker</em>.</p>

<h3>Exigence des jobs</h3>

<p>Parfois appelé <em>job requirement</em>. C’est un concept qui est présent sous différentes formes dans la plupart des <em>job managers</em> du marché. Le principe est que chaque job contient des informations sur ce qui est nécessaire à son exécution. Plus ces informations sont complètes, plus le job manager pourra gérer au mieux la farm. Le cas le plus courant est le type et le nombre de licences nécessaire à l’exécution du job.</p>

<p>Voici un exemple d’exigence de job :</p>

<pre>
<code class="language-python">{'requirement': {'license': {'nuke': 1},
                            {'sapphire': 1}
                 'cpu_count': '12+',
                 'memory_min’: '8GB',
                 'memory_max': '64GB'}</code></pre>

<p>Le dictionnaire suivant spécifie que le job :</p>

<ul>
	<li>Utilisera une licence Nuke et une licence Sapphire. Le job manager va donc n’assurer que ces licences sont disponibles avant le lancer le job.</li>
	<li>Utilisera tous les CPU disponibles avec un minimum de 12 CPU.</li>
	<li>Utilisera au minimum 8 GB de RAM…</li>
	<li>…mais n’utilisera jamais plus de 64 GB.</li>
</ul>

<p>L’aspect intéressant c’est que certaines informations peuvent aider le job manager à mieux organiser la soumission des jobs. Ainsi, en spécifiant <em>memory_max</em>, vous « garantissez » au job manger que le job ne fera jamais plus de 64 GB. Si, par exemple, vous avez des petits jobs qui n’utilise qu’un seul CPU vous pourriez spécifier <em>cpu_count</em> à 1 et le job manager saurait que votre job ne va utiliser qu’un seul CPU.</p>

<p>C’est une sorte de « contrat » que vous passez avec le job manager. C’est donc à double tranchant. Si vous lui dite que votre job utilisera 16 GB et qu’il monte à 64 GB, le worker aura des soucis pour l’exécuter. <img src="media/f1f7d503.nannan.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/nannan.gif" alt=":nannan:" class="smiley" /> Bien entendu, c’est celui qui génère le job à soumettre qui explicite ses exigences. Comme ce sont souvent les TD qui codent les chaînes de job, les exigences sont dans le code. <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>Job de génération des fichiers de rendu</h3>

<p>Le job de rendu est le type de job le plus courant. C’est souvent celui pour lequel vous souhaitez mettre une ferme de rendu en place. <img src="media/7f51717c.baffed.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/baffed.gif" alt=":baffed:" class="smiley" /></p>

<pre>
Scène de travail -&gt; images rendues
  .mb/.gproject  |      .exr</pre>

<p>Comme ce sont souvent les jobs les plus longs, il est préférable de séparer la génération des fichiers de rendu (<em>.rib</em>, <em>.ass</em>, etc.) et le rendu de ces derniers en deux jobs distincts :</p>

<pre>
Scène de travail -&gt; fichiers de rendu -&gt; images rendues
  .mb/.gproject  |     .rib/.ass      |      .exr</pre>

<p>La génération des fichiers de rendu consiste à ouvrir une scène (Maya/Guerilla/Katana/Poalobra) et à faire les exports des fichiers de rendu (<em>.rib</em>, <em>.ass</em>, etc.), sur un <em>range</em> d’image donné.</p>

<p>Dans le cas de Guerilla, on ouvre le <em>.gprojet</em>, on exporte un <em>range</em> d’image (paquet de 10 par exemple : 101-110, 111-120, etc.) en <em>.rib</em>.</p>

<p>Pourquoi ne pas exporter toutes les images plutôt que par petits paquets ? Tout simplement parce que le but est de garder la durée de vos jobs aussi consistante et contrôlable que possible. <img src="media/4f56089b.laClasse.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/laClasse.gif" alt=":laClasse:" class="smiley" /> Si on exportait « toutes les images », on aurait des temps très aléatoires suivant les plans du fait de la disparité de leur nombre d’images (certains plans font une trentaine d’image, d’autre plusieurs centaines). Si vous avez un bug sur la dernière image sur votre plan de 900 frames (oui parce qu’on a toujours un problème sur la PUTAIN de dernière image du plan le plus long du projet ! <img src="media/f33a81c6.injures.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/injures.gif" alt=":injures:" class="smiley" /> ), il vous faudrait tout relancer. Et si l’export dure 30 minutes, vous allez passer des heures à le déboguer. <img src="media/6e363cce.casseTeteMur.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/casseTeteMur.gif" alt=":casseTeteMur:" class="smiley" /></p>

<p>Diviser en paquet permet de rendre le temps humainement gérable.</p>

<p>Dans un monde idéal et instantané, on n’exportera qu’une seule image. Ceci permettrait d’avoir le job de rendu en dépendance directe sur le job de génération de fichier de rendu. Mais ce n’est pas possible, il y a un temps minimum nécessaire à l’ouverture de l’application et de la scène. <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>La taille des paquets dépendent de la lenteur générale de l’ouverture de la scène (Les scènes Maya peuvent être lente si elles ne sont pas « vides »). Plus la scène est lente à ouvrir, plus il est intéressant d’augmenter la taille du paquet.</p>

<p>J’utilise, en général, des paquets de 10 images pour Guerilla et 20 pour Maya. Mais c’est vraiment suivant la taille du projet. <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>Notez qu’il n’est pas toujours possible et/ou faisable d’avoir des jobs de génération de fichiers de rendu sur votre ferme de calcul. Par exemple, on peut vouloir rendre des ranges d’images directement depuis son logiciel favori (Maya à une époque et je suppose Blender, Cinema 4D, etc.). Cette méthode, plus « direct » peut se révéler chaotique dès lors que des problèmes apparaissent. Il faut être vigilant. <img src="media/398b4426.adodonicoco.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/adodonicoco.gif" alt=":papi:" class="smiley" /></p>

<h3>Job de rendu</h3>

<p>C’est sûrement le type de job le plus long de la ferme de calcul. Je conseille fortement de n’avoir qu’une image par job.</p>

<p>Les informations importantes de tels jobs se situent dans le <em>log</em>. Certains <em>job manager</em> permettent de <em>parser</em> le <em>log</em> à la volée pour remonter des informations de façon claire (temps de rendu, fichiers manquants, etc.) voir, arrêter le job, faisant ainsi gagner un temps précieux.</p>

<p>Si les temps de rendu sont importants (12 heures et plus) et si votre moteur de rendu le permet, il peut être intéressant d’avoir accès à l’image « en l’état » avant la fin du rendu (au bout de 10 minutes par exemples) ceci permet de pouvoir s’assurer qu’aucun truc grossier n’est présent/absent du rendu et d’éviter de perdre des heures inutiles. <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>La technique du pauvre consisterait à lancer deux jobs de rendu utilisant les mêmes fichiers de rendu mais avec des arguments de la ligne de commande différent :</p>

<ul>
	<li>Un avec une résolution faible et un faible nombre de samples ne dépassant pas 10 minutes.</li>
	<li>Et un autre, le vrai de plusieurs heures.</li>
</ul>

<p>Mais cela reste très imparfait, car quand le « vrai » rendu peut rarement partir dans les mêmes conditions que le premier. Il peut ainsi se retrouver sur une autre machine. Le meilleur reste donc d’utiliser l’image du rendu en cours. Si le moteur ne le permet pas, vous pouvez lancer une seule frame, au milieu du plan (ou une frame toutes les 5 frame par exemple) avec une priorité plus élevée. Vous n’attendez ainsi pas la fin complète des images pour en vérifier quelques-unes. Mais cette technique aussi est imparfaite, car vous ne voyez pas l’ensemble du plan, juste quelques images.</p>

<p>Dans les deux cas, cela vous permet de générer des vidéos de « pré-rendu », mais forcement, avec tout cela, le suivi du rendu est alourdi. <img src="media/27323fb5.mad0001.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/mad0001.gif" alt=":septic:" class="smiley" /></p>

<h3>Job d’export Alembic</h3>

<p><img alt="" class="media" src="media/f893135d.Alembic.png" data-original-source="http://www.fevrierdorian.com/blog/public/logos/Alembic.png" style="margin: 0 auto; display: table;" />C’est sûrement le second job le plus courant : L’ouverture de scène puis l’export de son contenu au format Alembic.</p>

<p>La méthode bourrine consiste à ouvrir la scène et tout exporter dans un gros fichier <em>.abc</em>.</p>

<pre>
Ouverture de la scène Maya -&gt; Export Alembic
         .mb               |       .abc</pre>

<p>C’est lourd et complètement con. <img src="media/8cb2a20b.vomit.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/vomit.gif" alt=":vomit:" class="smiley" /></p>

<p>En pratique, il est plus pertinent de séparer les exports suivant leur nature. Ainsi, s’il y a 3 personnages dans la scène, l’animation de chaque personnage est exporté dans son Alembic respectif. Il est ainsi plus rapide de réexporter l’animation d’un seul personnage lors d’une <em>retake</em>.</p>

<p>Le plus intéressant étant encore de savoir ce que contient le plan à l’avance en vu de générer un job par personnage. <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>Job d’export ATOM</h3>

<p>À l’instar du rendu, plutôt que de passer directement par un job d’export Alembic, on pourrait passer par une étape intermédiaire consistant à exporter l’ATOM des contrôleurs d’animation, puis un second job, celui exportant l’Alembic, partirait d’une scène vide, amènerait une version du rig (la dernière par exemple) appliquerait l’ATOM sur les contrôleurs d’animation puis ferait l’export.</p>

<pre>
                                     Rig
                                      |
                                      v
​Scène de travail -&gt; fichiers ATOM -&gt; Maya -&gt; Export anim
      .mb        |     .atom      |       |     .abc</pre>

<p>Mais on pourrait aller encore plus loin ! <img src="media/38d91e93.onSeFendLaPoire.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/onSeFendLaPoire.gif" alt=":onSeFendLaPoire:" class="smiley" /></p>

<p>Pourquoi ne pas en profiter pour faire un <em>preroll</em> automatique pour nos amis du <em>cloth</em> et du <em>FX</em> ?</p>

<ul>
	<li>Une clef, en <em>T-pose</em>, à l’image 1.</li>
	<li>Une clef, toujours en T-pose, mais avec le personnage place a sa position de départ à l’image 50.</li>
	<li>Un placement du personnage vers sa première position d’animation à l’image 70.</li>
	<li>L’application de l’ATOM du début du plan (101) à la fin.</li>
	<li>Export de l’Alembic.</li>
</ul>

<p>Pensez à garder les paramètres de numéro de frame modifiable afin que les départements puisse régénérer leur Alembic avec <em>preroll</em> si la version automatique n’est pas optimale.</p>

<h3>Job de génération de vidéo</h3>

<p>Ce job s’occupe de générer des vidéos, souvent <em>.mp4</em> depuis une séquence d’image (<em>.jpeg</em>, <em>.exr</em>, etc.). Ce dernier est loin d’être simple.</p>

<p>On peut utiliser Nuke pour bénéficier de tous les outils dont il dispose (texte, option d’export, etc.), mais Nuke n’est pas donné et nécessite une licence. <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>Le module Python <a href="https://pillow.readthedocs.io/en/latest/" hreflang="en">Pillow</a> est vraiment très bon. Je le recommande chaudement. <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>Pour les cartouches (bandes noir en haut et en bas, affichant des informations) je déconseille de calculer dynamiquement leur taille via un pourcentage. Gardez une taille fixe et connu et simple à retenir pour tout le monde (100 pixels, 150 pixels, 200 pixels, etc.).</p>

<pre>
+--------------------------------+
|text1        text4        text7 |
|text2        text5        text8 |
|text3        text6        text9 |
|--------------------------------|
|                                |
|                                |
|           *picture*            |
|                                |
|                                |
|--------------------------------|
|text10       text13       text16|
|text11       text14       text17|
|text12       text15       text18|
+--------------------------------+</pre>

<p>Neuf infos en haut et neuf infos en bas, soit 18 petits textes d’informations ! <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>Liste non exhaustive d’informations intéressantes à mettre dans les cartouches :</p>

<ul>
	<li>Frame : 150 (101-192).</li>
	<li>Date.</li>
	<li>Nom du graphiste.</li>
	<li>Focale.</li>
	<li>Watermark.</li>
	<li>Colorimetrie.</li>
</ul>

<p>Vous pouvez également ajouter une ou plusieurs images en début de vidéo avec plus d’informations (commentaire du graphiste, date des fichiers utilisés, mire colorimétrique, etc.).</p>

<h3>Job de synchro</h3>

<p>Que l’on travaille dans un studio multi-site ou qu’on utilise les ferme de rendu dans le cloud, les jobs de synchro sont monnaies courante. Ces jobs ne prennent quasiment aucune ressource et ne font bien souvent rien d’autre qu’attendre. En effet, ils sont rarement chargés de faire la synchro eux-mêmes mais passe par un service dédié auquel ils envoient des informations des fichiers à synchroniser. Ensuite, ils attendent que le service de synchro leur dise que les fichiers demandés ont été synchronise. D’où l’importance de s’assurer qu’aucun worker dédié à une tâche lourde (rendu, export, etc.) n’exécute un job de synchro. Ce serait une perte de temps énorme. Pour cela il peut être pratique d’avoir une machine compose de dizaines de worker qui ne font qu’exécuter des jobs de synchro (c’est-à-dire attendre… <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>Une fois ces jobs exécutés ils « débloquent » les jobs en dépendance qui peuvent s’exécuter sur leur worker avec la garantie que les fichiers nécessaires sont présents.</p>

<p>Job de nettoyage</p>

<p>Souvent appelé <em>cleanup jobs</em>, leur mécanisme est parfois pris en charge par le job manager qui ne s’exécute qu’au moment de la suppression des jobs. On ne peut donc pas directement parler de « job » mais plutôt de <em>cleanup list</em> (le job contient la liste des fichiers/dossier à supprimer) :</p>

<pre>
<code class="language-python">{'cleanup':['/path/to/file.rib',
            '/path/to/folder']}</code></pre>

<p>Mais tous ne le gèrent pas comme ça et un job dédié reste la méthode traditionnelle.</p>

<p>Ce job sert tout simplement à supprimer les fichiers qui ne sont plus nécessaires. Ça peut être les <em>.rib</em> ou des <em>.vrmesh</em> généré à la volée par la chaîne de job mais qui ne servaient qu’au calcul d’une image.</p>

<p>Il fut un temps, ces jobs supprimaient les <em>shadow map</em>, les <em>point-clouds</em>, les <em>brick maps</em>, etc. qui pesaient très lourd.</p>

<p>C’est la fin de cette première partie ! J’espère que ça vous aura intéressé. La suite, un jour… <img src="media/afbb21d6.aupoil.gif" data-original-source="http://www.fevrierdorian.com/blog/themes/blueSilenceCustom/smilies/aupoil.gif" alt=":aupoil:" class="smiley" /></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>


