CESAR SAEZhttps://www.cesarsaez.me/2019-07-01T00:00:00+10:00Presenting at "The Big Day In"2019-07-01T00:00:00+10:002019-07-01T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2019-07-01:/2019/07/bigdayin.html<p>I had the opportunity to represent Animal Logic by presenting at "The Big Day In" (UTS) sharing a
bit of what we do in the R&D department, the talk was oriented to senior secondary school and
university students interested in careers in ICT and technology.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Ff6_-NQoKkI" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
<p>Cheers!</p><p>I had the opportunity to represent Animal Logic by presenting at "The Big Day In" (UTS) sharing a
bit of what we do in the R&D department, the talk was oriented to senior secondary school and
university students interested in careers in ICT and technology.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Ff6_-NQoKkI" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
<p>Cheers!</p>Hello shadertoy2018-08-27T00:00:00+10:002018-08-27T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2018-08-27:/2018/08/hello-shadetoy.html<p>I've been always amazed by the incredible work people share at <a href="http://www.shadertoy.com">shadertoy</a>,
it's truly a privilege to be able to explore the gallery while taking a look at the source code right
there in the browser, play around changing parameters and learning different approaches.</p>
<p>So, after years looking from the …</p><p>I've been always amazed by the incredible work people share at <a href="http://www.shadertoy.com">shadertoy</a>,
it's truly a privilege to be able to explore the gallery while taking a look at the source code right
there in the browser, play around changing parameters and learning different approaches.</p>
<p>So, after years looking from the distance I decided to give it a try... and guess what? It's a
lot of fun!</p>
<div class="flex-video widescreen">
<iframe width="640" height="360" frameborder="0" src="https://www.shadertoy.com/embed/Md3cW7?gui=true&t=10&paused=false&muted=false" allowfullscreen></iframe>
</div>
<blockquote>
<p>You can even interact with it by dragging the cursor over the canvas!</p>
</blockquote>
<p>My humble <a href="https://www.shadertoy.com/user/csaez">doodles</a> are far from those impressive
<a href="https://www.shadertoy.com/playlist/week">shaders of the week</a>, but the community has proved to be
an amazing one by giving very constructive feedback and I've certainly learned a lot while bending
my mind trying to figure out how to express a certain algorithm in a parallel friendly way.</p>
<div class="flex-video widescreen">
<iframe width="640" height="360" frameborder="0" src="https://www.shadertoy.com/embed/MtXyWX?gui=true&t=10&paused=false&muted=false" allowfullscreen></iframe>
</div>
<p>Anyway, I just wanted to recommend <a href="http://www.shadertoy.com">shadertoy</a> to everyone: the barrier of entry
has never been lower (you just need a browser), the community is truly amazing and the gallery is
full of great shaders to learn from.</p>
<div class="flex-video widescreen">
<iframe width="640" height="360" frameborder="0" src="https://www.shadertoy.com/embed/XtXyzM?gui=true&t=10&paused=false&muted=false" allowfullscreen></iframe>
</div>
<p>Don't be shy and give it a try, you can thank me later ;)</p>
<p>Cheers!</p>AL_USDMaya demo2018-04-16T00:00:00+10:002018-04-16T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2018-04-16:/2018/04/usdmaya-demo.html<p>I found this demo showcasing some of the early work we did at Animal Logic regarding our
integration of USD within Autodesk Maya (aka AL_USDMaya, more
<a href="https://github.com/AnimalLogic/AL_USDMaya">here</a>).</p>
<p>It was a fantastic experience to be involved on the many iterations integrating USD in the studio,
developing an integration of the likes …</p><p>I found this demo showcasing some of the early work we did at Animal Logic regarding our
integration of USD within Autodesk Maya (aka AL_USDMaya, more
<a href="https://github.com/AnimalLogic/AL_USDMaya">here</a>).</p>
<p>It was a fantastic experience to be involved on the many iterations integrating USD in the studio,
developing an integration of the likes of <code>AL_USDMaya</code> was a huge undertaking made only
possible by the many talented developers contribuiting within the studio and in the open source
community.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/DaxLk6pHijw" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
<blockquote>
<p>Funnily enough this demo was never meant to be public, I was originatelly asked to recorded it as
an informal little demo to be shared with engineers at Autodesk working on Maya's efforts to
support USD nativelly (more <a href="https://area.autodesk.com/blogs/the-maya-blog/maya-usd/">here</a>),
It's inspiring to see all the progress made since then :)</p>
</blockquote>
<p>Cheers!</p>psystem2018-03-20T00:00:00+11:002018-03-20T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2018-03-20:/2018/03/psystem.html<p>Hi folks,</p>
<p>Some time ago I recorded this little video developing a simple particle system,
from scratch, as an exercise and I thought it would be cool to also share it in here.</p>
<p>The goal?</p>
<p>To share a straight forward approach? maybe to demythify the difficulty of getting
something like …</p><p>Hi folks,</p>
<p>Some time ago I recorded this little video developing a simple particle system,
from scratch, as an exercise and I thought it would be cool to also share it in here.</p>
<p>The goal?</p>
<p>To share a straight forward approach? maybe to demythify the difficulty of getting
something like this running? (at a prototype/toy level), to finally make something standalone
and visual on some of my screencast? yet another "code kata"? who knows! :)</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/0K0t0Mqa5wo" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
<p>As usual, code is licensed under MIT at <a href="https://github.com/csaez/psystem">github</a>.</p>
<p>Let me know what you think.</p>
<p>Cheers!</p>Naming2017-07-18T00:00:00+10:002017-07-18T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2017-07-18:/2017/07/naming.html<p>Hi folks,</p>
<p>In a new attempt to do a live coding series, I've been recording these sessions implementing a very
simple naming convention manager/thingy in python. Just like
<a href="https://www.cesarsaez.me/2015/12/dgpy.html">dgpy</a>, the idea is to keep it short and straight
forward (hopefully each series gets better, although I like to keep …</p><p>Hi folks,</p>
<p>In a new attempt to do a live coding series, I've been recording these sessions implementing a very
simple naming convention manager/thingy in python. Just like
<a href="https://www.cesarsaez.me/2015/12/dgpy.html">dgpy</a>, the idea is to keep it short and straight
forward (hopefully each series gets better, although I like to keep them kinda raw so we can share
how things evolved and not an artifial session where everything works first try).</p>
<h3>What are we trying to solve here?</h3>
<p>This comes back from when I was developing
<a href="https://www.cesarsaez.me/2014/02/riglab-preview-002.html">riglab</a> a few years ago, one of the
things I wanted to do there was to make it "pipeline friendly", so people can integrate it
seamlessly without introducing any innecessary friction into the pipeline. This meant that any
tool using metadata stored on names cannot assume anything about it and a configuration layer is
needed. This also applies to any sort of distribuitable tools.</p>
<p>Anyway, there are 11 videos at the time of this writting and the project provides enough
functionality to be useful in a real scenario.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLYcUacEjhPL-40O1ca6n1A0AAnco5CMzH" frameborder="0" allowfullscreen></iframe>
</div>
<p>One thing I particullarly like about this series is how we moved from some not-so-great code (in
order to keep things moving) to a more desirable end result with total confidence thanks to the
development process, it wasn't planned that way but it kinda happened.</p>
<p>The source code is on <a href="https://github.com/csaez/naming">github</a> (MIT license), but the value
of the project is more on the educational side of things (imho).</p>
<p>Let me know what you think :)</p>
<p>Cheers!</p>The Lego Journey2017-05-30T00:00:00+10:002017-05-30T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2017-05-30:/2017/05/the-lego-journey.html<p>Hi folks,</p>
<p>It has been a while since I was involved on the making of these films, but now that <em>Lego Batman</em> is
out and <em>Ninjago</em> is on its way I would like to share some sort of retrospective of my journey around
these projects.</p>
<p>If you are not familiar …</p><p>Hi folks,</p>
<p>It has been a while since I was involved on the making of these films, but now that <em>Lego Batman</em> is
out and <em>Ninjago</em> is on its way I would like to share some sort of retrospective of my journey around
these projects.</p>
<p>If you are not familiar with the LEGO movies here are the mandatory trailers.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/rGQUKzSDhrg?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/sZSYYiATFTI?rel=0&start=10" frameborder="0" allowfullscreen></iframe>
</div>
<p>My hope after writing this is to hopefully bring some light to people starting their careers or
maybe that haven't had the opportunity to work on these types of projects yet. I clearly remember
my young self being inspired by reading interviews of artists working on movies while living in
Chile where all this seems so out of reach. But you know what... somehow I'm here! and maybe some
of the lessons I've learned during my bumpy journey can help you too.</p>
<h2>Joining Animal Logic</h2>
<p>I still remember my first day very vividly, I was quite excited about the opportunity to work at
<em>AL</em>, I've had the chance to work on animated tv series and actually supervised an animated movie
before joining AL, but it was clearly a step up for me. On top of that there was the whole
Australian experience and living in an English speaking country for the first time... There was a
lot going on.</p>
<p>My first day I met 2 new starters for the rigging department, we had some generic induction
sessions and later on we were introduced to the team and left at our desks doing mostly paperwork
and looking around the wiki. Eventually we got a few sessions with our supervisor explaining how
things work, it was a lot to take in a few hours.</p>
<p>Later I learned first hand that training new starters is not an easy task, there's a lot built over
the years and it's easy to take things for granted after being around for some time, more on this
later.</p>
<p>Anyway, back to training, I think being a group made the experience much easier as we all
shared our notes and helped each other trying to figure out things without having to bother other
people too often. It might sound silly, but the team spirit was there since day one making the
experience a breeze.</p>
<p>This lead me to the first piece of advice:</p>
<blockquote>
<p>Make an effort to get along with your peers, have lunch together! teams are more than just
workers sharing a project. Start building a network around you as soon as you can, it's hands
down the cheapest and more effective investment you can do for your career and your well being.</p>
</blockquote>
<p>In my case I had the whole language barrier going on, it was pretty tough to even understand what
people was talking about at the table. But after a while I figured that instead of fighting this or
use it as an excuse, I could totally take advantage of it! This barrier was precisely what made me
different and interesting to people, I realized that instead of struggling with it I could use it
as a chat opener, people love to learn about different cultures, languages and anything really! we
come from different sides of the world, sometimes from very different realities, and sharing those
perspectives makes an interesting discussion, even if it implies everybody having to make an effort
to understand each other. Having great teammates helps a lot (if anyone is reading, thanks!).</p>
<h2>Looking with fresh eyes</h2>
<p>An interesting thing about working on <em>LEGO</em> movies at <em>Animal Logic</em> is that we really strive to stay
true to the medium, nothing deforms in ways that cannot be done with the real toys, actually
there's a strong correlation between the digital assets and the <em>LEGO</em> catalogue, so cheating to make
things look cool is not really an option (anim uses a ton of per-frame brick replacement).
This imposes a lot of constraints to animation and rigging, making it an interesting challenge. I
certainly wasn't expecting to work on such complex mechanical rigs and procedural face systems.</p>
<p>Pipeline/technology wise though, the first <em>LEGO</em> movie paved the way for the next ones, the pipeline
was quite stable and we didn't need to reinvent too many wheels... in theory.</p>
<p>Working with old-ish pipelines while pushing the envelope in terms of complexity/scale has its
downsides, for instance rigging for the <em>LEGO</em> movies was 100% code-based (other than adjusting
guides) and the framework in which the rigs were defined had some room for improvement. After a few
months learning the system I decided to write a few pages of feedback (+ possible solutions) and
after clear it out with some trusted peers I sent it over to my supervisor.</p>
<p>Surprisingly he was very open to my feedback and that leaded to getting involved doing very
significant changes to the way builders and components communicated with each other simplifying
asset scripts and the overall design of the system a lot. We moved from what I call <em>"class
oriented programming"</em> (I've <a href="https://www.cesarsaez.me/2015/09/stop-cop.html">written a bit about it in the
past</a>) to more generic entities reducing the amount
and complexity of code dramatically. I also develop a few key components dealing with spline-ish
elements and did a lot of work on the procedural face system (on top of in-house software, a very
unique experience).</p>
<p>And this leads us to the second piece of advice:</p>
<blockquote>
<p>Never underestimate the power of fresh eyes! A lot of times people start accepting whatever they
have as <em>the way things are (tm)</em>, that opens a huge opportunity to bring blind spots to the
table and help improving things. Your perspective is one of your best weapons!</p>
</blockquote>
<p>This is not to say that you will get there and change everything, you obviously need to learn the
current system and understand why things are the way they are (pleae don't assume the previous guy
wasn't as clever as you think you are, that's not how reality works)... But past certain point
there's the possibility that you might see some blind spot and depending on the team and production
you might get a chance to get involved doing very interesting work.</p>
<p>This could not happened without the trust of my supervisor at the time: <em>Josh Murtack</em>. He gave me
a lot of room to dig deeper into the system and discuss different ideas around how to improve the
overall design. What was even more impressive to me was his attitude towards my suggestions,
allowing me to develop prototypes even in cases where he didn't fully saw where I was trying to go
with the system (take into account the language barrier). I <em>really</em> appreciate his support during
my time working on <em>LEGO</em> movies, he's one of the best supervisors I've ever worked with.</p>
<h2>New opportunities</h2>
<p>After a year working in the rigging department, and perhaps because of my work and interest
refactoring the <em>LEGO</em> rigging system, I had the opportunity to get involved in the making of the
new rigging technology at the <em>Performance Technology Group</em> (a small group inbetween rigging and
RnD). This meant I finally made the switch to a software developer position (yay!).</p>
<p>Since then I've been working as part of <em>Raffaele Fragapane</em> team re-inventing the way we do rigging
across the facility, starting from first principles with a strong focus on performance. My work
here has been a lot more technical and I cannot go into details because of NDA, but I'm very happy
with what we have built so far and hopefully you will be able to see some of the projects making
use of this technology very soon.</p>
<p>I have no doubts I've been very lucky to even have these opportunities, but leaving the luck
factor aside, the take away here is:</p>
<blockquote>
<p>Your actions will somehow get reflected in your future, sometimes is not obvious, sometimes is very
straight forwards, but it happen. So my advice here is to focus in the present as it's your only
way to model the future, everything else will come as a consequence. Lead by example, do <em>the
right thing</em> (whatever that means to you) no matter your surroundings/circumstances and you will
increase the chances to reach your goals.</p>
</blockquote>
<p>From a more personal point of view, I've been taking some time to learn about more technical
domains, I actually took a class on <em>functional programming</em> last year and have been getting more
familiar with low level code and how hardware really works. I still do plenty of <em>python</em>
development though, but I switch to <em>C/C++</em> when I have a chance and I've been playing quite a bit
with different languages in my spare time (<em>Rust</em> ftw!... more seriously, there are a lot of great
ideas being implemented in new-ish languages).</p>
<h2>The present.</h2>
<p>I've been at <em>AL</em> for two and a half years now, it has been an incredible journey so far and I'm very
grateful for the chance to be around here. Next month I'm moving again, this time to the <em>RnD</em>
department taking on even bigger challenges under a new team.</p>
<p>I'm kinda glad to move away from rigging, it's an interesting topic but after 10 years tinkering
around it I'm pretty sure being outside of my comfort zone will push me to grow in new
directions, there will be ups and downs but I'm willing to do my best.</p>
<p>And that leads us to the end... it's a wall of text! I know, but I sincerely hope some of my stupid
advices and experience encourage newcomers to enjoy their journey and go for their goals.</p>
<p>Cheers!</p>Ditching comments2017-04-23T00:00:00+10:002017-04-23T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2017-04-23:/2017/04/ditching-comments.html<p>Hi folks,</p>
<p>I just wanted to let you know that I'm ditching Disqus (the service powering comments) from this
website in an effort to eliminate trackers. I silently <a href="https://twitter.com/csaezmargotta/status/678459610932502528">removed google
analytics</a> some time ago for the same
reason, but this time hurts a bit more because comments are the way …</p><p>Hi folks,</p>
<p>I just wanted to let you know that I'm ditching Disqus (the service powering comments) from this
website in an effort to eliminate trackers. I silently <a href="https://twitter.com/csaezmargotta/status/678459610932502528">removed google
analytics</a> some time ago for the same
reason, but this time hurts a bit more because comments are the way we have to interact with each
other and I felt like it deserves an explanation.</p>
<p>First things first: I love receiving your feedback, everytime I get a message/email from someone
because of an article or some of my open source projects it totally makes my day, even "harsh"
comments push me to do better by correcting some missconception or learning something new. As a
sef-taught I owe a lot to the community and the whole purpose of having a website is to, in some
way, pay back by sharing/helping newcomers and pushing myself by learning from your feedback. Big
thanks to all of you for your support through the years.</p>
<p>Said that, I also have strong concerns about online privacy and the status of the web, I surely
take measures to stay away from ads/trackers by using all sort of privacy oriented plugins,
extensions, VPN and whatnot; but I feel like it is totally unfair from my part to push trackers to
anyone in exchange for the ability to leave a comment on this website or to feed my ego by checking
stats.</p>
<p>There might be some of you thinking <em>what's wrong with ads/trackers? I have nothing to hide!</em></p>
<p>Well, most cloud-based services like google analytics or social widgets (facebook's likes and what
not) require the inclusion of a little script to provide the service, said script is also used to
track the visitor building an unique profile (which is a key piece to targeted ads... and who know
what else, you have no say on what that data is used for). This alone is horrifying, but you have
to consider that around 60% of the web uses google analytics and social widgets are rapidily
becoming omnipresent, allowing these companies to literally follow you from website to website
reconstructing your whole browser history without your knoledge/agreement.</p>
<p>This is wrong, we are not just talking about some script slowing down the website by adding some
extra network requests, it's about respecting your freedom! Websites are literally trading your
digital persona without your knowledge.</p>
<p>I know this website alone makes no difference to the googles and facebooks of the world, but it's
about integrity and acting according to my believes... even if it means giving up on some convenient
services along the way.</p>
<p>Cheers!</p>Python mutability, side effects and memory management.2016-12-20T00:00:00+11:002016-12-20T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2016-12-20:/2016/12/python-sideeffects.html<p>Hi folks,</p>
<p>I would like to plug a short video/rant I recorded recently on python's memory management,
mutable types and side effects.</p>
<p>I still think python have its place, this video is not about bashing python or anything like that (I
actually enjoy coding on it), but there are …</p><p>Hi folks,</p>
<p>I would like to plug a short video/rant I recorded recently on python's memory management,
mutable types and side effects.</p>
<p>I still think python have its place, this video is not about bashing python or anything like that (I
actually enjoy coding on it), but there are many instances requiring us to understand what's going
on under the hood in order to debug and workaround some flaky behaviour.</p>
<div class="flex-video widescreen">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/NB4EocagrTk" frameborder="0" allowfullscreen></iframe>
</div>
<p>Hope you enjoy and, hopefully, learn something new.</p>
<p>Cheers!</p>mscreen2016-07-02T00:00:00+10:002016-07-02T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2016-07-02:/2016/07/mscreen.html<p>Hi folks,</p>
<p>I would like to introduce a little python library I've been working on my spare
time to help TDs and TAs to draw OpenGL primitives in Maya viewport for
debugging purposes and/or non-critical tools (adding graphics as hints on tools
and what not).</p>
<p>Instead of me writing …</p><p>Hi folks,</p>
<p>I would like to introduce a little python library I've been working on my spare
time to help TDs and TAs to draw OpenGL primitives in Maya viewport for
debugging purposes and/or non-critical tools (adding graphics as hints on tools
and what not).</p>
<p>Instead of me writing a wall of text I recorded a short video showing the main
features in action.</p>
<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/172564385?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>The <a href="https://github.com/csaez/mscreen">source code of <code>mscreen</code></a> is available
on GitHub, and released under the MIT license. There's also some technical docs
at <a href="http://www.cesarsaez.me/mscreen">https://www.cesarsaez.me/mscreen</a>.</p>
<p>I hope you like it, enjoy :)</p>The future of rigging2016-06-14T00:00:00+10:002016-06-14T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2016-06-14:/2016/06/future-rigging.html<p>Hi folks,</p>
<p>I have been thinking about an interesting topic to start a discussion over here, it has been a
while since the last one, and I thought about sharing a bit of what we have been talking (and
working on) with some colleagues at work lately regarding what's going …</p><p>Hi folks,</p>
<p>I have been thinking about an interesting topic to start a discussion over here, it has been a
while since the last one, and I thought about sharing a bit of what we have been talking (and
working on) with some colleagues at work lately regarding what's going on in rigging and where are
we going as an industry, it's a very interesting topic to me and I'm very curious about your
thoughts on this, so here we go... the future of rigging!</p>
<h3>A revolution is coming... eventually</h3>
<p>If you know me, or have had a chat with me about rigging in the past, you will know that I have
been thinking about this for a long time, there's even an old entry (<a href="https://www.cesarsaez.me/2013/11/rigger-journey.html">a rigger's
journey</a>) touching on this.</p>
<p>Actually, if you take a second to read my <a href="http://www.linkedin.com/in/cesarsaez">linkedin</a> profile,
you will see that one of the first paragraphs goes like this (this text has been like this since I
created the profile, many years ago).</p>
<blockquote>
<p>I look forward to further develop my career as technical artist, I firmly believe that there is
much room for improvement on our workflow <strong>and the current paradigm in my area of
specialization</strong>, I want to be part of the change.</p>
</blockquote>
<p>And it's not about big words, I <em>really mean it!</em> I'm certain that a revolution is coming, it <em>has</em>
to happen, but I wasn't sure what the big change will look like... until now.</p>
<h3>What's going on in rigging?</h3>
<p>So rigging tech hasn't changed much in the last 10 years, we have more complex assets to work with,
less time, but the tech itself hasn't changed much (other than OSD and some proprietary/patented
tech). If anything it is more accessible thanks to the internet and online courses on the subject
(not as many as animation or modeling, but you know, there are a few).</p>
<p>So where's the revolution?</p>
<p>Well, in order to talk about the future we need to take a look at the past... if you were able to
rig an ik/fk limb 10 years ago, you were set for success, but todays standards <em>and expectations</em>
are way higher than that.</p>
<p>Right now, riggers are a mix of things, you have to be a bit technical to automate things in order
to deliver rigs in a reasonable time frame (the complexity of highend rigs demand automation, it's
not optional anymore) and artistic enough to hack your way around in order to deliver belieable and
appealing deformations.</p>
<p>Said that, riggers do not need to be engineers or sculptors, it's a weird middle ground, <em>and
that's exactly what I think is about to change</em>.</p>
<h3>Learning from the past</h3>
<p>If we take a look at what happened to other specialities, it's clear that after some period of time
were artists hacked their way around the tech to get a decent looking product out of the door,
there's an inflection point where specialized developers have to step in allowing artists to be
artists and engineers to be engineers, hacking stuff around is not enough anymore.</p>
<p>A perfect example of this is <em>shading</em>, some years ago shading artists used to program/hack shaders
together in interpreted-languages/visual-progremming and somehow eyeball surface effects until get
the desired look, as a result shading was <em>very</em> dependent on lighting conditions and it was very
difficult to have a consistent look across a variety of environments. After a while, people
realized that in order to archieve phisically plausible results we need to move to more complex
models and the entire industry moved the tech side of things to specialized developers/engineers
while leaving the artistic desitions to artists. We went from technical artists eyeballing shaders
according to each lighting condition to photorealism, and the only way to get there was thanks to
the split.</p>
<p>I firmly believe that <em>rigging has reached that inflection point</em>.</p>
<h3>But I love rigging, is it going to dissapear?</h3>
<p>It's not going to dissapear, but it will change (and we need to change). I think rigging will stop
being a mix of things and will become a bit more serious in order to advance the tech behind it...
We cannot move forward at the pace assets are moving by using constraints and linear skinning, or
having layered rigs running at 6 FPS.</p>
<p>If you take a look at rigging openings on big studios you have a clear split between studios
looking for <em>artists with some technical skills</em> (great sensibility to achieve appealing
deformations, plus some scripting abilities to survive while using proprietary tools) and the ones
looking for <em>technical minded people with some artistic sensibility</em> (basically engineers able to
create the tech enabling modelers and animators to articulate the puppets in a believable way).</p>
<p><em>The split is happening and the gap will only increase</em> until we reach the point where the artistic
input can be done directly by modelers/animators (there will be an intermediate time where riggers
basically assemble rigs from libraries and deal with tech annoyances, wait... that's now! :) )</p>
<h3>Where to go from here? how to survive?</h3>
<p>If you are all about deformations and appealing, I highly recommend to move towards modeling
(specifically sculpting), that's really the area where those skills shine (and will keep shining
for a while)... Also being familiar with rigging requirements in terms of topology is a big plus!</p>
<p>On the other hand, if you are into technology, I think rigging will become way more close to
software dev and knowing 4 things about for loops and variables will not be enough anymore, after
all coding is the new literacy and knowing the alphabet will be considered the baseline for most
areas sooner than later.</p>
<p>In order to really make this happen, we will need to step up big time and become a
developer/engineer (I'm not talking about the degree, but the mindset), have a clear understanding
of the main programming paradigms (OOP, pure functional), being able to design reasonable apis,
understand data, being able to develop fast code by understanding the hardware (especially GPUs,
parallel computing is already a big deal when it comes to deformations).</p>
<p>In short, not cut corners and do the work towards those topics (not dogmas, the real stuff), learn
all the lessons we can from software development in order to not make the same mistakes.</p>
<hr>
<p>There you go, that's my armageddon right there... Of course it will not be black or white, there's
a lot of room for all kind of skills on studios of all sizes, but if you really want to have an
impact I think the changes are right there around the corner and now is the best time to start
shaping your career towards what really moves you.</p>
<p>What do you think? Am I crazy? Please let me know in the comments below :)</p>
<p>Cheers!</p>Testing as a medium2016-01-14T00:00:00+11:002016-01-14T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2016-01-14:/2016/01/testing-as-a-medium.html<p>Hi folks,</p>
<p>Today I gave my first "brain swap" presentation at Animal Logic... and guess
what was the topic: testing, of course :)</p>
<p>Why testing? because I think there's a misunderstanding and lack of focus on
testing between technical artists/technical directors in our industry, and
every effort in terms of …</p><p>Hi folks,</p>
<p>Today I gave my first "brain swap" presentation at Animal Logic... and guess
what was the topic: testing, of course :)</p>
<p>Why testing? because I think there's a misunderstanding and lack of focus on
testing between technical artists/technical directors in our industry, and
every effort in terms of spread what testing is about helps.</p>
<p>Said that, it's tough to introduce an entire area of specialization in less
than an hour, the more you know the more specialized everything gets and I
didn't wanted to go there and confuse people. So I ended up focusing in
fundamental concepts instead, drawing some parallels between the classic
paradigm and the scientific method, and looking for ways to integrate testing
in the development process in a way that it presents short-terms benefits to
developers.</p>
<p>Unfortunately I can't share a recording of the presentation, and it's a shame
because it was quite interactive! with people bringing very interesting
questions/thoughts to the table.... but I can share the
<a href="http://cesarsaez.me/slides_testing">slides</a>!</p>
<p>There you go, that was my first "brain swap" as a presenter... I hope this
helps to spread some testing love between TAs/TDs out there, give it a try on
your next project ;)</p>
<p>Cheers!</p>dgpy2015-12-20T00:00:00+11:002015-12-20T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2015-12-20:/2015/12/dgpy.html<p>Hi folks,</p>
<p>I've been recording this 10 minutes sessions implementing a very simple
dependancy graph in python. It's a bit embarrasing to put yourself out there
like this but what the heck: life is too short :)</p>
<div class="flex-video">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLYcUacEjhPL-nSolgfdIJ_GqBakUp790z" frameborder="0" allowfullscreen></iframe>
</div>
<p>The motivation behind this has to do with developing a deeper understanding of
how …</p><p>Hi folks,</p>
<p>I've been recording this 10 minutes sessions implementing a very simple
dependancy graph in python. It's a bit embarrasing to put yourself out there
like this but what the heck: life is too short :)</p>
<div class="flex-video">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLYcUacEjhPL-nSolgfdIJ_GqBakUp790z" frameborder="0" allowfullscreen></iframe>
</div>
<p>The motivation behind this has to do with developing a deeper understanding of
how graphs work and how to use them to model problems we face everyday as
TDs/TAs, and also to help to demythify testing as part of the development
process.</p>
<p>I've seen so many talented technical artists starting to implement this kind of
projects without much focus/structure and the outcome always lead to not
getting much done (I've been there too, working in the GUI side of things
before give any thought to the backend and stuff like that). I hope this series
help to spread a somehow different approach, where we solve one problem at a
time, without going crazy in terms of complexity/overthinking, leaving tests of
every feature as we go so the code can actually be refactored when needed.</p>
<p>At the moment there's support for arbitrary nodes, persistent connections, and
a push/pull evaluation model. I'm currently starting to work on the
serialization of the graph and whatever comes next depends on you :)</p>
<p>So, if any of this seems interesting to you, please feel free to follow along!
Any feedback is much appreciated.</p>
<p>Oh! I almost forgot, the code is <a href="https://github.com/csaez/dgpy">available at
github</a>, but I honestly do not recommend to use
it without following the videos as most of the value of this project comes from
the process.</p>
<p>Cheers!</p>Stop class oriented programming2015-09-23T00:00:00+10:002015-09-23T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2015-09-23:/2015/09/stop-cop.html<p>Hi folks,</p>
<p>It has been a long time without writing anything here, so I thought it was
about time say hi by sharing my views on something I've been "fighting with"
lately.</p>
<p>This article is about a very dangerous but common "pattern" I've seen many times
around TAs/TDs using …</p><p>Hi folks,</p>
<p>It has been a long time without writing anything here, so I thought it was
about time say hi by sharing my views on something I've been "fighting with"
lately.</p>
<p>This article is about a very dangerous but common "pattern" I've seen many times
around TAs/TDs using classes as containers/namespaces for the code at hand (why
not functions? I have no idea). So instead of have handy classes defining
behavior, you can see plenty of code implementing the entire thing directly on
an uniquely instanced class, prefixing everything with <code>self</code> without even
noticing what are we pushing to the next guy consuming our code.</p>
<p>Let's be clear about this, the whole idea behind Object Oriented programming
(like it or not) is based on <em>the state (a.k.a. data) belonging to the instance
while the behaviour (a.k.a. methods) being defined in the class</em>.</p>
<p>That's object oriented in a nutshell, you define a <em>type</em> implementing certain
behaviour (like a builtin <code>str</code> or <code>list</code> does!) and then create <em>multiple</em>
instances storing different states. You rarelly save the state at a class level
unless you really have a good reason to do it (yeah... there are plenty of valid
reasons to do it, but you know what I mean).</p>
<h4>But Cesar, everybody knows that...</h4>
<p>Are you sure?</p>
<p>Take an honest look at your GUI code (qt, anyone?)... if you are like the
average TD out there, I bet you are subclassing a mainWindow/dialog to add
widgets <em>AND set its state</em> inside the class instead of creating "templates" to
be used outside your "container".</p>
<p>What about your rigging system? anim tools? (or whatever you develop in your
field).</p>
<h4>Fair enough... but what's wrong about using classes as containers?</h4>
<p>There's absolutely nothing wrong with it <em>as long as you know what you're
doing</em>!</p>
<p>Think about what happen to the next guy trying to reuse your code, are there
ways to redefine simple things without subclassing?</p>
<p>Do you imagine if the only way to create a <code>str</code> were via subclassing?</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="nb">str</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">"Hello world!"</span>
<span class="k">print</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">())</span>
<span class="c1"># oh, do you want to change it? sure!</span>
<span class="k">class</span> <span class="nc">HelloCesar</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">"Hello Cesar!"</span>
<span class="k">print</span><span class="p">(</span><span class="n">HelloCesar</span><span class="p">())</span>
<span class="c1"># I would rather prefer this version</span>
<span class="k">print</span><span class="p">(</span><span class="s2">"Hello world!"</span><span class="p">)</span>
</pre></div>
<p>That's exactly what happens when we create classes as containers without
providing proper interfaces or thinking much about making it generic!</p>
<p>If anything, I think it's fair to say it's not a good default as it leads to
extremelly specific classes and lack of a proper interfaces to consume your
code. It also leads to tons of boiler plate, as the keyword <code>class</code> somehow
loss its value and people stop thinking about being generic, at the end of the
day you force everyone wanting to reuse your code to sublclass and
overload/extend most of the methods.</p>
<p>I'm not saying you shouldn't be using classes, classes are a powerful tool, but
be aware that each time you type <code>class</code> you're defining a new <em>type</em>! it's a
very powerful tool that need to be used wisely.</p>
<h4>So, what about you?</h4>
<p>Have you seen this kinda code before? (unittest!?) What do you think about it?
Am I the only one seeing it as a problem?</p>
<p>I would love to read your thoughts on the comments below... don't be shy! :)</p>
<p>Cesar</p>I got a new job!2015-05-28T00:00:00+10:002015-05-28T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2015-05-28:/2015/05/animal-logic.html<p>Hi folks,</p>
<p>Most people I interact with (in real life and social media) might already know
this, but I've moved to Sydney and have been working at <a href="http://www.animallogic.com">Animal
Logic</a> on the upcoming Batman and Ninjago LEGO
movies for the past 4 months.</p>
<p>Moving to Sydney has been a big change …</p><p>Hi folks,</p>
<p>Most people I interact with (in real life and social media) might already know
this, but I've moved to Sydney and have been working at <a href="http://www.animallogic.com">Animal
Logic</a> on the upcoming Batman and Ninjago LEGO
movies for the past 4 months.</p>
<p>Moving to Sydney has been a big change for me and I have defenitely felt
outside of my comfort zone many many times (which is a good thing). I'm having
a great time adapting to the city, meeting new people and even speaking a new
language.</p>
<p>Then there's AL itself, which obviously represent is a big step on my career.
Get up to speed with all the proprietary stuff has been tough but interesting
at the same time, I'm learning a lot while working in very challeging problems
and adding value to the great rigging team we have over here.</p>
<h4>So... good for you, right?</h4>
<p>Well, yeah! but I got here after a very bumpy trip and I thought that sharing
this experience could be a more interesting topic for people reading this.</p>
<p>People often focus on the bright side of things, attributing success to
excellence and all sort of personal greatness, which is somewhat true, but
that's not the whole story.</p>
<p>There's a lot to be said about perseverance, compromises, frustration, hard
decisions that have to be made in order to shape your own path... and even
worse, there's a very considerable amount of luck, of having the right contacts
and being in the right place at the right moment (which implies you have to be
in the right place at the wrong moment many many times).</p>
<p>For instance I got very good feedback with my latest demo reel (it was
instantly featured in <a href="http://www.itsartmag.com/features/cesar-saez-rigging-reel">it's art
magazine</a>), many
recommendations in <a href="http://linkedin.com/in/cesarsaez">linkedin</a> and stuff...
But between the moment I published my reel and the contract with AL were
something like 250 emails applying to job offers, 20 rejection letters (most of
the time because of the lack of an EU/USA work permit), 3 failed interviews
with big studios, an offer cancelled by a chinese studio after 3 months of
paperwork and an "almost there" by a canadian studio.</p>
<p>So, if you are still reading this and things are not going in the direction
you want, this is the best piece of advice I can give you:</p>
<blockquote>
<p>Keep trying, find out what's missing, fix it and try again... and again,
and again.</p>
</blockquote>
<p>There's no easy path, people tend to not share publicly the stuff going on
under the hood but it's going to be hard for you as it's for everybody else,
just keep going, keep pushing, stay hungry, stay awesome.</p>
<p>Cheers!</p>Yet another 'dorito' tutorial2015-03-24T00:00:00+11:002015-03-24T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2015-03-24:/2015/03/doritos-maya.html<p>Hi folks,</p>
<p>Last night I captured this short video on how to recreate the <a href="http://www.softimageblog.com/archives/209">famous
'dorito' setup</a> in Autodesk Maya.</p>
<p>In case you are not familiar with the term (it's mainly a Softimage lingo), it
simply refers to a way of spliting the skinning deformation into different
layers, where each …</p><p>Hi folks,</p>
<p>Last night I captured this short video on how to recreate the <a href="http://www.softimageblog.com/archives/209">famous
'dorito' setup</a> in Autodesk Maya.</p>
<p>In case you are not familiar with the term (it's mainly a Softimage lingo), it
simply refers to a way of spliting the skinning deformation into different
layers, where each layer rides on top of the previous one avoiding double
transformations.</p>
<p>The technique itself is nothing new and there are
<a href="https://vimeo.com/91005555">several</a> <a href="https://vimeo.com/87722342">videos</a>
<a href="https://vimeo.com/88615637">explaining</a> how to do it in different softwares,
but looks like the Maya approach is a bit convoluted and I wanted to share a
straight forward way to do it without any rants on how good or bad Maya
workflow is.</p>
<div class="flex-video widescreen">
<iframe src="https://player.vimeo.com/video/123069799" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hope you like it,</p>
<p>Cheers!</p>Switching to VIM2015-02-09T00:00:00+11:002015-02-09T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2015-02-09:/2015/02/switching-to-vim.html<p>Hi folks,</p>
<p>If you follow me on twitter you've probably noticed the tweets on my switch
from <a href="http://www.sublimetext.com">sublime</a> to <a href="http://www.vim.org">vim</a>.</p>
<p>I would like to share my experiences during the switching, the reasons behind
it and some of the advantages I see in my new daily workflow. </p>
<h3>First things first</h3>
<p><a href="http://www.sublimetext.com">Sublime …</a></p><p>Hi folks,</p>
<p>If you follow me on twitter you've probably noticed the tweets on my switch
from <a href="http://www.sublimetext.com">sublime</a> to <a href="http://www.vim.org">vim</a>.</p>
<p>I would like to share my experiences during the switching, the reasons behind
it and some of the advantages I see in my new daily workflow. </p>
<h3>First things first</h3>
<p><a href="http://www.sublimetext.com">Sublime Text</a> is a great code editor! I used it for the past 3~4
years without issues. I love its <code>ctrl+shift+p</code> where all options are
accessible from the keyboard, I became addict to use multiple cursors and was
an early adopter of <a href="https://packagecontrol.io/">package control</a>.</p>
<p>I also wrote my own snippets, build systems and all the things that you would
expect from a power user.</p>
<p>So, before get into why I switched and all that jazz, I would like to say that
<a href="http://www.sublimetext.com">sublime</a> is a great code editor and you should definitely give it a try.</p>
<p>That said, let's talk about <a href="http://www.vim.org">vim</a>...</p>
<h3>Why switching?</h3>
<p>All started by watching a <a href="https://www.youtube.com/watch?v=YhqsjUUHj6g">video on youtube</a>, I never considered switching
or anything, it was plain and simple curiosity about this old, clunky and weird
editor.</p>
<p>I learned that it shouldn't look as ugly as with the default settings, modes
actually made sense (no more keyboard/mouse switching, yey!), there's an an
active community writing plugins and, most importantly, it's free and open
source.</p>
<p>"Interesting! but I won't switch just because of that" I thought... yeah,
right.</p>
<p>Since that day on, every time I had to grab the mouse to select or move around
some text, something inside me yells: <em>you are doing it wrong!</em>... and I
don't know you, but I used to grab the mouse to move around a lot!</p>
<p>So, a couple of weeks later I decided to give it a try.</p>
<h3>First impresions</h3>
<p>In two words: <em>NO WAY</em></p>
<p>There's <em>no way</em> I could use this thing to develop anything on it. It's too
old, weird and ugly for me (yep, call me superficial, but the look is important
when you stare at it all day long).</p>
<p>So, what you do when this happen?</p>
<h3>Let's the tweaking begin!</h3>
<p>I started by tweaking my <code>.vimrc</code> file adding syntax highlighting, a better
color scheme and all sort of small enhacements I probably stealed from the
internet.</p>
<p>Then I learned about plugins, so I installed <a href="https://github.com/tpope/vim-pathogen">pathogen</a> to manage them and then
went to <a href="https://github.com/kien/ctrlp.vim">ctrlp</a>, <a href="https://github.com/itchyny/lightline.vim">lightline</a>, <a href="https://github.com/klen/python-mode">python-mode</a>, <a href="https://github.com/garbas/vim-snipmate">snipmate</a> and <a href="https://github.com/tpope/vim-surround">vim-surround</a>.</p>
<p>And that was it...</p>
<blockquote>
<p>You can grab <a href="https://github.com/csaez/dotfiles/blob/master/.vimrc">my <code>.vimrc</code> from
here</a>, it's fully
commented and targeted to python development.</p>
</blockquote>
<h3>Time to do some work</h3>
<p>First days were a pain... forget about cool features, just moving around using
<em>hjkl</em> keys instead of my beloved mouse/arrows-keys and switching between modes
was a challenge, not to talk about registers and the whole copy/paste thing.</p>
<p>But hey, after the initial shock things began to settle, I learned that hjkl
are not the most efficient moves to getting around text and the whole "command
nightmare" became a sort of continuous dialog with the editor (I'm not being
poetic here, commands work like verbs and can be combined in interesting
ways... you'll see).</p>
<p>To summarize: <em>indeed, I was doing it wrong</em>.</p>
<p>By the way, <a href="http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/">this article</a> has helped me a lot.</p>
<h3>To this day...</h3>
<p>I'm not an expert by any means, but I'm enjoying of some <a href="http://www.vim.org">vim</a> "super powers"
when coding... in fact, I would miss many features if I were forced to use
another editor.</p>
<p>I love the ability to run my code directly from vim (or any <code>bash</code> command),
<code>virtualenv</code> support is now essential to my workflow, I love not being forced
to jump between the keyboard and mouse to getting around text efficiently,
macros are great and I like the general approach to commands... even the look
and feel is nice once you tweak it!</p>
<p>And, of course, I'm very happy to be using open and free software.</p>
<h2>tl;dr</h2>
<p>I switched to <a href="http://www.vim.org">vim</a> and I'm very happy with it (from a philosophical and
functional point of view).</p>
<p>Why should you consider it?</p>
<ul>
<li>It is free and open source software.</li>
<li>Cross-platform, it's everywhere!</li>
<li>Highly customizable.</li>
<li>Efficient workflow.</li>
<li>Config truly portable (1 file + plugins, no admin privileges needed).</li>
<li>It's fun, you'll learn something new every day!</li>
</ul>Amaranth v1.0 is out!2015-01-30T00:00:00+11:002015-01-30T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2015-01-30:/2015/01/amaranth_v1_out.html<p>Hi folks!</p>
<p>Last year was all about open source for me, I finally removed my Windows
partition and went full Linux (btw, gotta love <a href="https://www.archlinux.org/">arch linux</a>), also
decided to develop and share my projects under open source licenses (check out
my <a href="https://github.com/csaez">github profile</a>) and have been contributing to open source …</p><p>Hi folks!</p>
<p>Last year was all about open source for me, I finally removed my Windows
partition and went full Linux (btw, gotta love <a href="https://www.archlinux.org/">arch linux</a>), also
decided to develop and share my projects under open source licenses (check out
my <a href="https://github.com/csaez">github profile</a>) and have been contributing to open source projects in
hopes of giving back to the community. This post is about the latter.</p>
<p>I just wanted to share that there's a new release of <a href="http://pablovazquez.org/amaranth/">Amaranth</a>: a
productivity addon for <a href="http://www.blender.org">Blender</a> by <a href="http://pablovazquez.org">Pablo Vazquez</a> (a.k.a. venomgfx).</p>
<p>I had always wanted to dive a bit deeper into <a href="http://www.blender.org">Blender</a> and this project
seemed to be the perfect excuse to do it, so I gave it a try and decided to
<a href="https://github.com/venomgfx/amaranth/pull/5">contribute</a> by doing a much needed refactoring of the code base.</p>
<p>The project is now completely modular, so it is much easier to maintain and add
new features, each module registers/unregisters itself as long as it's imported
into the main file and everything just works.</p>
<p>So, that's it... if you're interested in <a href="http://www.blender.org">Blender</a> please visit
<a href="http://pablovazquez.org/amaranth/">Amaranth</a>'s website and give it a try. I honestly think it's worth it :)</p>
<p>Cheers!</p>Hello Houdini2014-12-05T00:00:00+11:002014-12-05T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-12-05:/2014/12/hello-houdini.html<p>Hi guys,</p>
<p>I've been giving Houdini another try and I have to say: it's a lot of fun!</p>
<p>I've always enjoyed building small procedural systems using ICE and felt like I might enjoy Houdini, but I've had never the need for it as it's not widelly used for rigging purposes …</p><p>Hi guys,</p>
<p>I've been giving Houdini another try and I have to say: it's a lot of fun!</p>
<p>I've always enjoyed building small procedural systems using ICE and felt like I might enjoy Houdini, but I've had never the need for it as it's not widelly used for rigging purposes. But you know what, who cares! I'm having a great time playing with it.</p>
<p>So, how to get started? well, my strategy here was jump ahead doing some quick exercises on my own (I did the same thing with ICE back in the day), it might not be the canonical approach but it motivates me much more than following long tutorials while learning to press buttons.</p>
<h2>Pin Table</h2>
<p>The first excercise that came into my mind was a pin-table, I think of it as the "Hello world!" excersice for Houdini and was actually pretty easy to solve.</p>
<p><img alt="Pin Table" src="https://www.cesarsaez.me/images/hello-houdini.jpg" title="Pin table"></p>
<p>I haven't done a breakdown video yet but there's not much to say, I just copied a pin on a displaced grid of points (using the luminance of a video as displacement map) and that's it, done!</p>
<h2>DNA Buildup</h2>
<p>This second exercise was a bit more involved, I wanted to recreate a
<a href="https://www.cesarsaez.me/2013/12/dna-buildup.html">similar effect</a> I did some
time ago using Softimge ICE.</p>
<p>You can watch a breakdown of my approach in the following video:</p>
<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/111258575" width="640" height="360" frameborder="0" allowfullscreen></iframe>
</div>
<h2>What's next?</h2>
<p>I would like to try something involving attribute transfer between objects in different contexts (ie interaction between particles and geometry), I have no idea how to tackle this at the moment but I'm pretty sure I will figure it out :)</p>
<h2>tl;dr</h2>
<p>I'm trying Houdini just for fun and so far so good, if you love the procedural nature of ICE you should totally give it a try!</p>Notes on python testing2014-09-10T00:00:00+10:002014-09-10T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2014-09-10:/2014/09/python-testing.html<p>Hi guys,</p>
<p>I've been rediscovering unit testing in python lately and wanted to share some notes about this, I hope you find them useful.</p>
<p>There we go!</p>
<h2>Why use an unit testing framework?</h2>
<p>One word: Convenience</p>
<p>You can always run your tests manually, but the harder to run tests, the …</p><p>Hi guys,</p>
<p>I've been rediscovering unit testing in python lately and wanted to share some notes about this, I hope you find them useful.</p>
<p>There we go!</p>
<h2>Why use an unit testing framework?</h2>
<p>One word: Convenience</p>
<p>You can always run your tests manually, but the harder to run tests, the less
likely you run them.</p>
<p>A piece of advice: be lazy, automate all the things! or even better: pick an
existing framework and stick with it.</p>
<h2>Nose</h2>
<p><a href="http://nose.readthedocs.org/en/latest/">Nose</a> is a testing framework for python, it's not included in the standard library but that's ok for me (otherwise look for <code>unittest</code>).</p>
<h2>Why <code>nose</code> over <code>unittest</code>?</h2>
<ul>
<li>Autodiscovering: put test functions in a module called <code>something_tests.py</code> and nose will find and run them for you.</li>
<li>No boiler plate: write your test as a simple function and call it
<code>test_ something</code>, there's no need of inheritance from base classes or
decoration of your functions.</li>
<li>Coverage: testing without coverage == no fun, more on this later.</li>
<li>Plugins: nose provides a nice plugin architecture, as a consecuence there
are many useful extensions out there (<code>nose-watch</code> seems specially handy, check
out the project <a href="https://github.com/lukaszb/nose-watch">here</a>)... and of
course you might be able to extend it creating your own plugins.</li>
<li>Things to come...</li>
</ul>
<h3>Cool, how do I install <code>nose</code>?</h3>
<div class="highlight"><pre><span></span>pip install nose
</pre></div>
<p>Once installed run <code>nosetests</code> in a terminal (from the root of your project) to run the tests.</p>
<blockquote>
<p>Do yourself a favor and install your dependencies in a <code>virtualenv</code>.</p>
</blockquote>
<h3>Wait... virtual-what?</h3>
<p>Ok, <code>virtualenv</code> creates an isolated python environment for your project... think of it as a custom <code>site-packages</code> per project.</p>
<p>You should check out the <a href="https://virtualenv.pypa.io/en/latest/index.html">documentation</a>, but in a nutshell:</p>
<div class="highlight"><pre><span></span><span class="c1"># Install virtualenv</span>
pip install virtualenv
<span class="c1"># Create a clean virtual environment at my_env/</span>
<span class="c1"># there's no need of --no-site-packages as it's deprecated.</span>
virtualenv my_env/
<span class="c1"># Activate my_env</span>
<span class="nb">source</span> my_env/bin/activate
<span class="c1"># Deactivate current environment</span>
deactivate
</pre></div>
<h4>Too much typing?</h4>
<p>There's <code>virtualenvwrapper</code> to make things easier, or you can create a bunch
of aliases and go with that... Just keep it simple and don't waste too much
time on this.</p>
<p>Here's what I'm using to activate an existing environment in my system (put
this in your <code>~/.bashrc</code>):</p>
<div class="highlight"><pre><span></span><span class="c1"># activate a virtualenv</span>
<span class="c1"># usage: activate my_env/</span>
<span class="k">function</span> activate<span class="o">()</span> <span class="o">{</span> <span class="nb">source</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>bin/activate <span class="p">;</span><span class="o">}</span>
</pre></div>
<h2>Back to testing: What testing looks like?</h2>
<p>Assuming a project structure like this:</p>
<div class="highlight"><pre><span></span>* my_proj
* tests
* __init__.py
* rocket_science_tests.py
* __init__.py
* rocket_science.py
</pre></div>
<p>... where <code>rocket_science.py</code>:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">add_integers</span><span class="p">(</span><span class="o">*</span><span class="n">arg</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">all</span><span class="p">([</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">]):</span>
<span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"(</span><span class="si">%s</span><span class="s2">) not an integer."</span> <span class="o">%</span> <span class="s2">","</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
</pre></div>
<p>then <code>rocket_science_tests.py</code> should look something like this:</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">my_proj.rocket_science</span> <span class="kn">as</span> <span class="nn">rs</span>
<span class="k">def</span> <span class="nf">test_add_integers</span><span class="p">():</span>
<span class="k">assert</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">assert</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">5</span>
<span class="k">assert</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span>
<span class="k">assert</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">3</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">rs</span><span class="o">.</span><span class="n">add_integers</span><span class="p">(</span><span class="mf">3.14159</span><span class="p">,</span> <span class="mf">1.61803</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="k">assert</span> <span class="nb">type</span><span class="p">(</span><span class="n">err</span><span class="p">)</span> <span class="o">==</span> <span class="ne">TypeError</span> <span class="c1"># too much awesomeness?!</span>
</pre></div>
<h2>What about coverage?</h2>
<p>Coverage basically tells you how much of your code is covered by your tests, so 100% coverage means every line of code is tested at least once.</p>
<p>But there's more, it not only tells you the percentage but also the lines of code not covered (per module), so you can check this information and write more tests until reach the 100%.</p>
<h2>How can I check my coverage?</h2>
<p>First...</p>
<div class="highlight"><pre><span></span>pip install coverage
</pre></div>
<p>and then add a couple of flags to <code>nosetests</code>:</p>
<div class="highlight"><pre><span></span>nosetests --with-coverage
</pre></div>
<p>... but it's taking into acount external modules! How to fix it?</p>
<div class="highlight"><pre><span></span>nosetests --with-coverage --cover-package<span class="o">=</span>my_proj
</pre></div>
<h4>Too much typing?</h4>
<p>Again, here's what I'm using at the moment (put this in your <code>~/.bashrc</code>):</p>
<div class="highlight"><pre><span></span><span class="c1"># run nosetest with coverage</span>
<span class="c1"># usage: testme (from the root of your project)</span>
<span class="k">function</span> testme<span class="o">()</span> <span class="o">{</span> nosetests --with-coverage --cover-package<span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">PWD</span><span class="p">##*/</span><span class="si">}</span><span class="s2">"</span> <span class="p">;</span><span class="o">}</span>
</pre></div>
<h2>That's nice, but what about DCC code?</h2>
<p>DCC code usually have strong dependencies on dynamic libraries initialized by
the DCC at runtime, this means we can only run our code within the DCC.</p>
<blockquote>
<p>Autodesk Maya has the ability to run in standalone mode, allowing us to
execute our code without the overhead of a fully fledged app, but this is a
quite unique feature compared to other DCCs.</p>
<p>There are interesting projects to automate testing for Maya-like apps
(<a href="https://github.com/rgalanakis/dccautomation">dccautomation</a> by Rob
Galanakis looks promising).</p>
</blockquote>
<h3><code>mock</code> to the rescue!</h3>
<p><code>mock</code> is a library for testing in Python. It allows you to replace parts of
your system under test with mock objects and make assertions about how they
have been used.
Check out the docs <a href="http://www.voidspace.org.uk/python/mock/index.html">here</a>.</p>
<h3>How to intall mock?</h3>
<div class="highlight"><pre><span></span>pip install mock
</pre></div>
<blockquote>
<p><code>mock</code> is part of the standard library from python 3.3 onwards.</p>
</blockquote>
<h3>... and now what?</h3>
<p>Let's say you want to test a snippet like this (standard Maya code):</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">maya</span> <span class="kn">import</span> <span class="n">cmds</span>
<span class="k">def</span> <span class="nf">get_bbox</span><span class="p">(</span><span class="n">obj_list</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Returns the bounding box of a list of objects. The values returned</span>
<span class="sd"> are in the following order: xmin ymin zmin xmax ymax zmax.</span>
<span class="sd"> """</span>
<span class="n">bbs</span> <span class="o">=</span> <span class="p">[</span><span class="n">cmds</span><span class="o">.</span><span class="n">xform</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">q</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">bb</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">obj_list</span><span class="p">]</span>
<span class="k">return</span> <span class="nb">tuple</span><span class="p">([(</span><span class="nb">min</span><span class="p">,</span> <span class="nb">max</span><span class="p">)[</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">>=</span> <span class="mi">3</span><span class="p">)](</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">bbs</span><span class="p">))])</span>
<span class="c1"># test function intended to be executed within Maya</span>
<span class="k">def</span> <span class="nf">test_get_bbox</span><span class="p">():</span>
<span class="n">locs</span> <span class="o">=</span> <span class="n">cmds</span><span class="o">.</span><span class="n">spaceLocator</span><span class="p">(</span><span class="n">p</span><span class="o">=</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">))</span>
<span class="n">locs</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">cmds</span><span class="o">.</span><span class="n">spaceLocator</span><span class="p">(</span><span class="n">p</span><span class="o">=</span><span class="p">(</span><span class="o">-</span><span class="mf">0.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">)))</span>
<span class="k">assert</span> <span class="n">get_bbox</span><span class="p">(</span><span class="n">locs</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">)</span>
<span class="n">cmds</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="n">locs</span><span class="p">)</span>
<span class="n">test_get_bbox</span><span class="p">()</span>
</pre></div>
<p>Ok, what do we really need to test here?</p>
<p>In my opinion we must test the algorithm, make sure that we are considering all objects in the <code>obj_list</code> and making the right choices between bounding boxes... we can assume <code>cmds.xform</code> is working fine, there's no need to test Maya commands (they have their own testsuite, I guess).</p>
<p>So, in order to run this test on system python the first thing to do is skip
the <code>ImportError</code> and then refactor the test function patching <code>cmds.xform</code>
through the <code>mock</code> library.</p>
<p>The following code runs perfectly in system python. Note that, except for the
test function, everything else is the same as before:</p>
<div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span> <span class="kn">from</span> <span class="nn">maya</span> <span class="kn">import</span> <span class="n">cmds</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="k">pass</span>
<span class="kn">import</span> <span class="nn">mock</span>
<span class="k">def</span> <span class="nf">get_bbox</span><span class="p">(</span><span class="n">obj_list</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Returns the bounding box of a list of objects. The values returned</span>
<span class="sd"> are in the following order: xmin ymin zmin xmax ymax zmax.</span>
<span class="sd"> """</span>
<span class="n">bbs</span> <span class="o">=</span> <span class="p">[</span><span class="n">cmds</span><span class="o">.</span><span class="n">xform</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">q</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">bb</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">obj_list</span><span class="p">]</span>
<span class="k">return</span> <span class="nb">tuple</span><span class="p">([(</span><span class="nb">min</span><span class="p">,</span> <span class="nb">max</span><span class="p">)[</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">>=</span> <span class="mi">3</span><span class="p">)](</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">bbs</span><span class="p">))])</span>
<span class="nd">@mock.patch</span><span class="p">(</span><span class="s2">"__main__.cmds"</span><span class="p">,</span> <span class="n">create</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_get_bbox</span><span class="p">(</span><span class="n">cmds</span><span class="p">):</span>
<span class="n">return_values</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"loc1"</span><span class="p">:</span> <span class="p">(</span><span class="o">-</span><span class="mf">0.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span>
<span class="s2">"loc2"</span><span class="p">:</span> <span class="p">(</span><span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">)}</span>
<span class="n">cmds</span><span class="o">.</span><span class="n">xform</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">k</span><span class="p">:</span> <span class="n">return_values</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">assert</span> <span class="n">get_bbox</span><span class="p">([</span><span class="s2">"loc1"</span><span class="p">,</span> <span class="s2">"loc2"</span><span class="p">])</span> <span class="o">==</span> <span class="p">(</span><span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">)</span>
<span class="n">test_get_bbox</span><span class="p">()</span>
</pre></div>
<h2>Cool! but what's the point?</h2>
<p>Being able to test our code from system python instead of the DCC makes a
<strong>HUGE</strong> difference during testing! Run a test like this takes milliseconds
and we can automate the process through a testing framework like <code>nose</code>, so in
practical terms we can run tests everytime a file is saved without thinking too
much about it (take a look at <code>nose-watch</code>).</p>
<p>In contrast, be forced to open the DCC to run the testsuite, restart the
application to cleanup its global state and then repeat takes forever, making
the process a much less enjoyable experience.</p>
<p>At the end, testing is a powerful development tool, let's take advantage of it
to develop amazing tools!</p>
<p>Regards,
Cesar.</p>QuickLauncher v2.02014-09-04T00:00:00+10:002014-09-04T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2014-09-04:/2014/09/quicklauncher-v2.html<p>Hi folks,</p>
<p>I just wanted to let you know that I've updated <a href="https://github.com/csaez/quicklauncher/releases/tag/v2.0">quicklauncher to v2.0</a>.</p>
<p>A brief summary of the changes:</p>
<ul>
<li>This version is maya-only, you can still download the previous version from <a href="https://github.com/csaez/quicklauncher/releases/tag/v1.0">here</a> though.</li>
<li>There are no dependencies for general use (requires PySide but it's included with Maya …</li></ul><p>Hi folks,</p>
<p>I just wanted to let you know that I've updated <a href="https://github.com/csaez/quicklauncher/releases/tag/v2.0">quicklauncher to v2.0</a>.</p>
<p>A brief summary of the changes:</p>
<ul>
<li>This version is maya-only, you can still download the previous version from <a href="https://github.com/csaez/quicklauncher/releases/tag/v1.0">here</a> though.</li>
<li>There are no dependencies for general use (requires PySide but it's included with Maya >= 2014).</li>
<li>The menu behaves like maya tab menu (node editor) but lists commands and user scripts instead of nodes.</li>
<li>The auto-complete is based on QCompleter instead of me filtering QAction as in previous versions (cleaner, more stable, better).</li>
<li>Settings are managed through QSettings instead of custom json files.</li>
<li>There's a testsuite (92% coverage at the moment), so I will not break everything in each update.</li>
<li>MIT license.</li>
</ul>
<p>You can get <code>quicklauncher</code> from the <a href="https://github.com/csaez/quicklauncher">github repo</a> as usual. Please be sure to read the readme, I did my best to explain everything you need to know before use it or contribute to the project.</p>
<p>Hope you like it,</p>
<p>Enjoy!</p>Going TDD: first steps...2014-08-15T00:00:00+10:002014-08-15T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2014-08-15:/2014/08/going-tdd.html<p>Hi folks,</p>
<p>I have a confession to make: I've always looked at test driven development
with envy and admiration, but I had never really tried it due to the strong
dependencies of the code I usually write... but it's even worse, I had never
put a fair amount of effort …</p><p>Hi folks,</p>
<p>I have a confession to make: I've always looked at test driven development
with envy and admiration, but I had never really tried it due to the strong
dependencies of the code I usually write... but it's even worse, I had never
put a fair amount of effort on testing due to the same reason (I know, shame
on me).</p>
<p>Until one day I finally swallowed my excuses and decided to go TDD on a
proper project (<code>mauto</code>, more on this in a future post)... and you know what?
it worked great!</p>
<p>I'm taking my first steps on this and I have no authority to 'teach' TDD, but
I'm sure there are many TDs/technical-artists with the same preconceptions on
testing and hopefully some of my humble findings could be useful for them.</p>
<hr>
<h2>Why testing? I know it's a good practice but...</h2>
<p>That was exactly my thought for a long time: "this code is not a core
library so it doesn't matter", "I have so many dependencies, I can't test this", "it would be nice but maybe later", "write tests sucks"
and so on.</p>
<p>The thruth is: writing tests leads you to <em>write better code</em> and
<em>enables you to refactor</em> your stuff without breaking everything as
you do it. Think of it as a tool to back you up as you progressively refine
the project.</p>
<p>Whithout tests you can't really work this way, your first take has to be
the good one (which is never the case) and any later modification comes with
a huge penalty, breaking existing code is inevitable.</p>
<h3>What about dependencies?</h3>
<p>Most tools I write are meant to be executed within a DCC (maya, softimage,
whatever) and there's a strong dependency on their APIs... So, how
to test this stuff?</p>
<p>Encapsulate your dependencies! <em>write testable code is up to you.</em></p>
<p>The first change I noticed on myself was the need to think about
dependencies in order to test my code, I started to
encapsulate stuff instead of call <em>expensive resources</em> all over the
place (i.e. writing all calls to the filesystem in a particular module,
DCC calls on other and so on).</p>
<p>I'm not saying you have to write a complex software-agnostic wrapper or
anything like that, just do your best to keep things thight in order to know
where your dependencies are, otherwise you won't be able to <em>replace</em>
them when testing your code.</p>
<blockquote>
<p>Forcing yourself to be aware of dependencies seems to be a win/win situation
as it enforces a clear separation of concerns on your code
(even if you are not going to write any test).</p>
</blockquote>
<hr>
<h2>Sounds good, where to start?</h2>
<h3>Structure:</h3>
<p>We need to define a structure for our project! <em>I highly recommend</em> stick to
the standard structure for python projects/packages, here's a
<a href="http://guide.python-distribute.org/quickstart.html">quickstart guide</a>.</p>
<blockquote>
<p>You can also create your base structure using something like
<a href="https://github.com/audreyr/cookiecutter">coockiecutter</a> or similar tools,
most IDEs set a base project for you.</p>
</blockquote>
<h3>Testing frameworks:</h3>
<p>In order to rely on your tests to develop is extremely important have a
mechanism to systematicaly run the test suite, it sounds obvious
but it's not.</p>
<p>Python include several ways to write/run tests, for <em>really</em> simple use cases
you can go with <a href="https://docs.python.org/2/library/doctest.html">doctest</a>,
but most of the time you will be better of writing your test in a separate
module using somthing like <a href="https://docs.python.org/2/library/unittest.html">unittest</a>.</p>
<p>These modules works fine, but I personally feel more confortable using a
boilerplate-free alternative as <a href="https://nose.readthedocs.org">nose</a> or
<a href="https://pytest.org">pytest</a>. Just choose your weapon and stick with it!</p>
<h3>Mock:</h3>
<p>Other important aspect of testing has to do with replacing the
<em>expensive resources</em> during testing, this way you can run them faster and
without affecting production assets in case something goes wrong (databases
and what not).</p>
<p>For this situations there's a python library called
<a href="https://pypi.python.org/pypi/mock">mock</a>. I won't cover how to use it, but it
provides a nice placeholder that you can use to monkeypatch your dependencies
during your tests. For further information refer to its
<a href="http://www.voidspace.org.uk/python/mock/">documentation</a>.</p>
<hr>
<h2>Everything is set, now what?</h2>
<p>Short answer: <em>start with the readme file!</em></p>
<p>This is not TDD per-se, but write down a high level snippet about how to use
your code is really useful and gives you a nice starting point.</p>
<p>Let's say we want to develop a pose library (this comes from the top of my
head, please do not take this example too seriously):</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pose_lib</span>
<span class="c1"># init rig from the scene</span>
<span class="n">ROOT_NODE</span> <span class="o">=</span> <span class="s2">"C_John_root_C_GRP"</span> <span class="c1"># node name</span>
<span class="n">rig</span> <span class="o">=</span> <span class="n">pose_lib</span><span class="o">.</span><span class="n">Rig</span><span class="p">(</span><span class="n">ROOT_NODE</span><span class="p">)</span>
<span class="c1"># list john compatible poses</span>
<span class="n">pose_lib</span><span class="o">.</span><span class="n">list_poses</span><span class="p">(</span><span class="s1">'John'</span><span class="p">)</span>
<span class="c1"># apply a pose to John's rig</span>
<span class="n">pose</span> <span class="o">=</span> <span class="n">pose_lib</span><span class="o">.</span><span class="n">get_pose</span><span class="p">(</span><span class="s1">'John'</span><span class="p">,</span> <span class="s1">'stand'</span><span class="p">)</span>
<span class="n">rig</span><span class="o">.</span><span class="n">set_pose</span><span class="p">(</span><span class="n">pose</span><span class="p">)</span>
<span class="c1"># add John's current pose to the library</span>
<span class="n">pose</span> <span class="o">=</span> <span class="n">rig</span><span class="o">.</span><span class="n">current_pose</span><span class="p">()</span>
<span class="n">pose_lib</span><span class="o">.</span><span class="n">add_pose</span><span class="p">(</span><span class="s1">'John'</span><span class="p">,</span> <span class="s1">'my_pose'</span><span class="p">,</span> <span class="n">pose</span><span class="p">)</span>
<span class="c1"># and so on...</span>
</pre></div>
<p>Boom! We have just decided to interface with maya nodes through a class
called Rig and access the library through a couple of functions (there's
probably another class managing json-files/sqllite/any-kind-of-storage under
the hood).</p>
<p>Just think how you would like interact with your finished project and write
it down (wait a minute, we are also documenting!).</p>
<h3>Let's write some code!</h3>
<p>First, let's assume this structure for our project:</p>
<ul>
<li>pose_lib/<ul>
<li>pose_lib/<ul>
<li>tests/<ul>
<li>__init__.py</li>
</ul>
</li>
<li>__init__.py</li>
</ul>
</li>
<li>LICENSE.txt</li>
<li>README.txt</li>
<li>setup.py</li>
</ul>
</li>
</ul>
<p>The first test is the hardest! that's why the readme is so important.</p>
<p>1- Reading the readme snippet I would go writting a test as follow:</p>
<div class="highlight"><pre><span></span><span class="c1"># file: pose_lib/pose_lib/tests/test_library.py</span>
<span class="kn">from</span> <span class="nn">nose</span> <span class="kn">import</span> <span class="n">test_with</span>
<span class="kn">import</span> <span class="nn">pose_lib</span>
<span class="k">def</span> <span class="nf">setup</span><span class="p">():</span>
<span class="n">pose_lib</span><span class="o">.</span><span class="n">add_set</span><span class="p">(</span><span class="s1">'test'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">tear_down</span><span class="p">():</span>
<span class="n">pose_lib</span><span class="o">.</span><span class="n">remove_set</span><span class="p">(</span><span class="s1">'test'</span><span class="p">)</span>
<span class="nd">@test_with</span><span class="p">(</span><span class="n">setup</span><span class="p">,</span> <span class="n">tear_down</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_list_poses</span><span class="p">()</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">pose_lib</span><span class="o">.</span><span class="n">list_poses</span><span class="p">(</span><span class="s1">'test'</span><span class="p">),</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">))</span>
</pre></div>
<blockquote>
<p><code>setup</code> and <code>teardown</code> functions are executed before and after the test
function (the decorated function), other testing frameworks (this one is
<code>nose</code> specific) should provide a similar way to do this.</p>
</blockquote>
<p>2- ... which lead us to write this:</p>
<div class="highlight"><pre><span></span><span class="c1"># file: pose_lib/pose_lib/__init__.py</span>
<span class="k">def</span> <span class="nf">add_set</span><span class="p">(</span><span class="n">set_name</span><span class="p">)</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">remove_set</span><span class="p">(</span><span class="n">set_name</span><span class="p">)</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">list_poses</span><span class="p">(</span><span class="n">set_name</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
<p>3- ... and run the tests (from the root directory in a terminal):</p>
<div class="highlight"><pre><span></span>python setup.py nosetests
</pre></div>
<blockquote>
<p>Most IDEs and code editors have a built in function to run the test suite for
you, if you're using an editor like sublime text you can take advantage of
the build system to run the tests.</p>
</blockquote>
<p>4- ... and refactor the code until all tests pass...</p>
<p>5- ... and write new tests...</p>
<p>6- ... and repeat until the project is completed.</p>
<hr>
<h2>Do you see where we're going with this?</h2>
<p>Is that simple! of course there will be some work to do in modules with
dependencies (take a look at mock's <a href="http://www.voidspace.org.uk/python/mock/">docs</a>;
there are ways to patch objects, simulate return values and so on).
With not-so-much effort you should be able to run your tests outside
maya/softimage/whatever as any other python developer (that means you can go
faster and lighter on early stages of the project and hopefully write better
code).</p>
<p>There's much more to say about testing and TDD, things like coverage
and what not... but I think this is enough for a first contact.</p>
<p>Is it doable on the project you are working on?
Do you have any experience working like this?
Anything to share?</p>
<p>Would love to hear what you think about this, please leave me your
comments below.</p>
<p>Cheers!</p>Hard Reloader for Maya2014-08-05T00:00:00+10:002014-08-05T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2014-08-05:/2014/08/hard-reloader.html<p>Hi folks,</p>
<p>Do you remember <a href="http://cesarsaez.me/2013/10/hard_reload.html">this handy trick to quickly reload a python package</a>?</p>
<p>Well, <strong>I use it all the time!</strong> so I made this little GUI helper. It's
really simple, but makes my life much easier when it comes to test WIP
code within Maya.</p>
<p><img alt="HardReloader for Maya" src="https://www.cesarsaez.me/images/hard_reloader.gif" title="HardReloader for Maya"></p>
<h3>Installation:</h3>
<p>Save the code …</p><p>Hi folks,</p>
<p>Do you remember <a href="http://cesarsaez.me/2013/10/hard_reload.html">this handy trick to quickly reload a python package</a>?</p>
<p>Well, <strong>I use it all the time!</strong> so I made this little GUI helper. It's
really simple, but makes my life much easier when it comes to test WIP
code within Maya.</p>
<p><img alt="HardReloader for Maya" src="https://www.cesarsaez.me/images/hard_reloader.gif" title="HardReloader for Maya"></p>
<h3>Installation:</h3>
<p>Save the code below as <code>hard_reloader.py</code> into your Maya script directory
(or somewhere else in your PYTHONPATH).</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">PySide</span> <span class="kn">import</span> <span class="n">QtGui</span><span class="p">,</span> <span class="n">QtCore</span>
<span class="kn">from</span> <span class="nn">shiboken</span> <span class="kn">import</span> <span class="n">wrapInstance</span>
<span class="kn">from</span> <span class="nn">maya</span> <span class="kn">import</span> <span class="n">OpenMayaUI</span>
<span class="k">class</span> <span class="nc">HardReloader</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QDialog</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">):</span>
<span class="nb">super</span><span class="p">(</span><span class="n">HardReloader</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">setWindowTitle</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">setAttribute</span><span class="p">(</span><span class="n">QtCore</span><span class="o">.</span><span class="n">Qt</span><span class="o">.</span><span class="n">WA_DeleteOnClose</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">initUI</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">initUI</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ui_lineEdit</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="n">ui_completer</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QCompleter</span><span class="p">(</span>
<span class="p">[</span><span class="n">i</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">keys</span><span class="p">()],</span> <span class="bp">self</span><span class="p">)</span>
<span class="n">ui_completer</span><span class="o">.</span><span class="n">setCompletionMode</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QCompleter</span><span class="o">.</span><span class="n">InlineCompletion</span><span class="p">)</span>
<span class="n">ui_completer</span><span class="o">.</span><span class="n">setCaseSensitivity</span><span class="p">(</span><span class="n">QtCore</span><span class="o">.</span><span class="n">Qt</span><span class="o">.</span><span class="n">CaseInsensitive</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ui_lineEdit</span><span class="o">.</span><span class="n">setCompleter</span><span class="p">(</span><span class="n">ui_completer</span><span class="p">)</span>
<span class="n">hbox</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QHBoxLayout</span><span class="p">()</span>
<span class="n">hbox</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ui_lineEdit</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">setLayout</span><span class="p">(</span><span class="n">hbox</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ui_lineEdit</span><span class="o">.</span><span class="n">returnPressed</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">accept</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">module</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ui_lineEdit</span><span class="o">.</span><span class="n">text</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">module</span><span class="p">):</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
<span class="k">if</span> <span class="n">k</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">module</span><span class="p">):</span>
<span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_parent</span><span class="p">():</span>
<span class="n">ptr</span> <span class="o">=</span> <span class="n">OpenMayaUI</span><span class="o">.</span><span class="n">MQtUtil</span><span class="o">.</span><span class="n">mainWindow</span><span class="p">()</span>
<span class="k">return</span> <span class="n">wrapInstance</span><span class="p">(</span><span class="nb">long</span><span class="p">(</span><span class="n">ptr</span><span class="p">),</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QMainWindow</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">show</span><span class="p">():</span>
<span class="n">HardReloader</span><span class="p">(</span><span class="n">get_parent</span><span class="p">())</span><span class="o">.</span><span class="n">exec_</span><span class="p">()</span>
</pre></div>
<blockquote>
<p>As you can see, hard_reloader has a dependency on PySide (shipped with
Maya >= 2014). If PySide is not your favourite flavor, you can easily switch
imports to PyQt (<code>PySide</code>-><code>PyQt4</code> and <code>shiboken</code>-><code>sip</code>).</p>
</blockquote>
<h3>Ussage:</h3>
<p>Just import it and call its <code>show</code> function (put this in a shelf or assign a hotkey).</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">hard_reloader</span>
<span class="n">hard_reloader</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
</pre></div>
<p>That's it, happy coding! ;-)</p>Developing a Character Picker for Maya2014-07-05T00:00:00+10:002014-07-05T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2014-07-05:/2014/07/picker-talk.html<p>Hi folks,</p>
<p>I just wanted to post a link to the slide deck and sample code from my talk: <a href="http://www.animum3d.com/paginas/ez-cesar-saez-general">"How to create a character picker for Autodesk Maya"</a>.</p>
<p>In the talk we explored the technology behind different kinds of character pickers, there is working code of a picker built using …</p><p>Hi folks,</p>
<p>I just wanted to post a link to the slide deck and sample code from my talk: <a href="http://www.animum3d.com/paginas/ez-cesar-saez-general">"How to create a character picker for Autodesk Maya"</a>.</p>
<p>In the talk we explored the technology behind different kinds of character pickers, there is working code of a picker built using maya commands, a qt version and a proposal for a canvas based one (using the qt graphic scene framework).</p>
<p>I don't know if <a href="http://www.animum3d.com">Animum</a> will publish a recording of the talk (or when they are going to do it), but here is a link to the slide deck and sample code (spanish only, sorry).</p>
<p><a href="http://csaez.github.io/slides_picker">SLIDES</a> / <a href="http://github.com/csaez/slides_picker/tree/master/picker">REPO</a></p>
<p>Cheers!</p>Softimage EOL2014-03-25T00:00:00+11:002014-03-25T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-03-25:/2014/03/softimage-eol.html<p>Hi folks,</p>
<p>As you might know Autodesk <a href="http://www.autodesk.com/products/autodesk-softimage/overview">announced</a> Softimage's EOL (end of life) a couple of weeks ago, since then forums/mailing-lists have gone crazy and that's why I've been waiting a bit to write about this.</p>
<p>I understand that for some people Softimage may look like legacy software and …</p><p>Hi folks,</p>
<p>As you might know Autodesk <a href="http://www.autodesk.com/products/autodesk-softimage/overview">announced</a> Softimage's EOL (end of life) a couple of weeks ago, since then forums/mailing-lists have gone crazy and that's why I've been waiting a bit to write about this.</p>
<p>I understand that for some people Softimage may look like legacy software and the whole EOL thing seems reasonable, but it is not! and perhaps the only reason to perceive it that way is because of the lack of active marketing from Autodesk. I think the decision has nothing to do with the software itself, it is about Autodesk's planning and it's sad that they don't consider Softimage as part of their future.</p>
<p>I know, Maya is a great software and we should just move on, but Maya lack on some areas where Softimage shines, like those depending on non-linear workflow or the entire ICE framework. I have no doubts that Autodesk is working hard to address those rough corners, but they will need some time and that's exactly why I don't fully understand why they are killing Softimage now.</p>
<p>If you want to read more about Softimage's EOL, here is an <a href="http://cice.es/noticia/entrevista-softimage-desaparece-sus-usuarios-hablan">nice interview</a> by Miguel Gomez to a group of Softimage users (<em>Jordi Bares</em>, <em>Miquel Campos</em>, <em>Xuan Prada</em>, <em>David Bastidas</em>, <em>Manuel Huertas</em>... and me! :D ), spanish only.</p>
<p>What's next? Well, move on.</p>
<p>I've been trying to refresh my maya-fu over the past couple of weeks, and I'll probably take another look at Houdini once I feel comfortable working with Maya again. Unfortunately it is not about the software I like but the one which allows me to be employable again.</p>
<p>That's it, no more Softimage rants from me.</p>
<p>Cheers!</p>Rigging Reel 20132014-03-02T00:00:00+11:002014-03-02T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-03-02:/2014/03/rigging-reel13.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/88004455" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>I just updated my reel (unfortunatelly had to cut a lot of stuff) and
I'm now actively looking for a job opportunity as Character TD/Technical
Artist (preferably full-time, I'm ok with relocation). I'd really appreciate
if you could pass this around.</p>
<p>Here's also a <a href="http://cesarsaez.me/pages/resume.html">link to my …</a></p><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/88004455" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>I just updated my reel (unfortunatelly had to cut a lot of stuff) and
I'm now actively looking for a job opportunity as Character TD/Technical
Artist (preferably full-time, I'm ok with relocation). I'd really appreciate
if you could pass this around.</p>
<p>Here's also a <a href="http://cesarsaez.me/pages/resume.html">link to my resume</a>, just in case ;-)</p>
<p>Thank you!</p>QuickLauncher met Maya2014-03-01T00:00:00+11:002014-03-01T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-03-01:/2014/03/quicklauncher-met-maya.html<p>Hey folks,</p>
<p>I'm coming out of the Softimage bubble and trying to port some of my open
source projects to maya.</p>
<p>It's funny, of all of them QuickLauncher is the simplest but one of the
most useful at the same time (I cannot live without it) , so I decided to …</p><p>Hey folks,</p>
<p>I'm coming out of the Softimage bubble and trying to port some of my open
source projects to maya.</p>
<p>It's funny, of all of them QuickLauncher is the simplest but one of the
most useful at the same time (I cannot live without it) , so I decided to
give it a try and there's a maya version in the <a href="https://github.com/csaez/quicklauncher">repo</a>
now :D</p>
<p><img alt="QuickLauncher for Maya" src="https://www.cesarsaez.me/images/quicklauncher_maya.gif" title="QuickLauncher for Maya"></p>
<p>I'm still struggling with the maya plugin system, so the installation process
is not as straight forward as in softimage, but I'll get there.</p>
<p>Thanks to <em>David Martinez</em> and <em>David Moulder</em> for their support.</p>
<p>Cheers!</p>flASCII bird2014-02-10T00:00:00+11:002014-02-10T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-02-10:/2014/02/flASCII-bird.html<p>Hi folks,</p>
<p>In the past few days has been a lot of buzz around <a href="https://en.wikipedia.org/wiki/Flappy_Bird">Flappy Bird</a>.
I'm not a gamer, but I couldn't resist the temptation and did this terminal-based
tribute... and I won't take it down ;D</p>
<p><a href="http://www.github.com/csaez/flascii_bird">Repository</a></p>
<p><img src="https://www.cesarsaez.me/images/flascii_bird.png" style="width:100%; height:auto;"/></p>
<p>Have fun!</p><p>Hi folks,</p>
<p>In the past few days has been a lot of buzz around <a href="https://en.wikipedia.org/wiki/Flappy_Bird">Flappy Bird</a>.
I'm not a gamer, but I couldn't resist the temptation and did this terminal-based
tribute... and I won't take it down ;D</p>
<p><a href="http://www.github.com/csaez/flascii_bird">Repository</a></p>
<p><img src="https://www.cesarsaez.me/images/flascii_bird.png" style="width:100%; height:auto;"/></p>
<p>Have fun!</p>RigLab: Preview #0022014-02-05T00:00:00+11:002014-02-05T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-02-05:/2014/02/riglab-preview-002.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/85901976" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>Today I want to share a new preview of the rigging framework I've been
working on, it's not production ready yet but I think there's enough
features to make it interesting and somehow different from the usual
rigging tools out there.</p>
<ul>
<li>00:00 - Intro</li>
<li>01:00 - Rig overview …</li></ul><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/85901976" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>Today I want to share a new preview of the rigging framework I've been
working on, it's not production ready yet but I think there's enough
features to make it interesting and somehow different from the usual
rigging tools out there.</p>
<ul>
<li>00:00 - Intro</li>
<li>01:00 - Rig overview</li>
<li>03:00 - Init</li>
<li>05:22 - Multipose setup</li>
<li>09:05 - Main setup</li>
<li>10:30 - Spine setup</li>
<li>12:35 - Head setup</li>
<li>15:00 - Left leg setup</li>
<li>22:55 - Right leg (via template)</li>
<li>25:35 - Left arm setup</li>
<li>31:25 - Right arm (via template)</li>
<li>33:50 - Closing</li>
</ul>
<p>Let me know what you think :)</p>
<p>Cheers!</p>RigLab: Metadata2014-02-01T00:00:00+11:002014-02-01T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2014-02-01:/2014/02/riglab-metadata.html<p>Hi folks,</p>
<p>This entry will be a bit techy, but not too much... stay with me! :)</p>
<h2>First, what is metadata?</h2>
<p>Metadata is "data about data", it describes information about the contents of the
item itself or its components... it's a note for our selves, so we don't
have to figure …</p><p>Hi folks,</p>
<p>This entry will be a bit techy, but not too much... stay with me! :)</p>
<h2>First, what is metadata?</h2>
<p>Metadata is "data about data", it describes information about the contents of the
item itself or its components... it's a note for our selves, so we don't
have to figure out that information from scratch the next time.</p>
<p><em>Metadata by example:</em>
Let's say we have an asset composed by several meshes and
we need to collect all of them by scripting on export.</p>
<ul>
<li>
<p>We can ask the user for the meshes (via selection or something) and that's it,
but that means we will need an user input on EVERY export... no batch processing,
bummer!</p>
</li>
<li>
<p>We can try to filter the meshes looping through the hierarchy + some logic
(conditionals + naming convention stuff) until collect all of them, it might work,
but there is a risk of the validation logic not always being true.</p>
</li>
</ul>
<p>Or...</p>
<ul>
<li><strong>We can use metadata!</strong> saving a 'note' with the meshes' name each time the
user export them, so we have an user defined fallback for batch processing!</li>
</ul>
<h2>Cool, but how?</h2>
<p>Metadata can be stored anywhere, it could be embeded on an attribute/custom-parameter,
written on an external file (so we can read it outside the DCC), stored
in a database and so on...</p>
<p>Whatever you choose, it is important to define an unified system to do it
because your code will become quite messy with all those extra metadata calls.</p>
<h2>Here comes the magic!</h2>
<p>Are you familiar with <a href="http://www.rafekettler.com/magicmethods.html">python's magic methods</a>?
Did you know they can be extended?</p>
<p>I did just that and it works great!</p>
<p>I created a base class for containers (I mean, things that group things together),
its instances serialize whatever you pass as an attribute thanks to python's magic
methods.</p>
<p>So each time I write something like this:</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">wishlib.si</span> <span class="kn">import</span> <span class="n">SIWrapper</span> <span class="c1"># the base class I was talking about</span>
<span class="n">selected_obj</span> <span class="o">=</span> <span class="n">Application</span><span class="o">.</span><span class="n">Selection</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">SIWrapper</span><span class="p">(</span><span class="n">selected_obj</span><span class="p">)</span>
<span class="n">foo</span><span class="o">.</span><span class="n">bar</span> <span class="o">=</span> <span class="s1">'baz'</span>
</pre></div>
<p>On <code>foo.bar = 'baz'</code>, <code>__setattr__</code> is called, <code>baz</code> is serialized
and stored as string in a custom parameter (Softimage's version of maya attributes).</p>
<p>Let's say I restart Softimage (fresh session) and type something like this:</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">wishlib.si</span> <span class="kn">import</span> <span class="n">SIWrapper</span>
<span class="n">selected_obj</span> <span class="o">=</span> <span class="n">Application</span><span class="o">.</span><span class="n">Selection</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># same selection</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">SIWrapper</span><span class="p">(</span><span class="n">selected_obj</span><span class="p">)</span>
<span class="k">print</span> <span class="n">foo</span><span class="o">.</span><span class="n">bar</span> <span class="c1"># 'baz'</span>
</pre></div>
<p>When <code>foo</code> is instanciated its <code>__init__</code> method is called, reading the metadata
from the custom parameters and initializing its members, so when we call <code>foo.bar</code>
it's a valid member and returns the expected data.</p>
<p>I don't want to bother you with the <a href="https://github.com/csaez/wishlib/blob/master/wishlib/si/siwrapper.py">implementation details</a> (take it with a grain of salt),
but I think it is a really cool way to serialize stuff without add too much overhead
to existing code.</p>
<p>There's a catch though, mutable data types mutates itself changing its own data, so
your extended <code>__setattr__</code> method will never be called unless you explicitly
update the entire thing.</p>
<p>I would love to know how you guys solve this kind of stuff :)</p>
<p>Cheers!</p>QuickLauncher v0.1.32013-12-18T00:00:00+11:002013-12-18T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-12-18:/2013/12/quicklauncher-v013.html<p>Hi guys,</p>
<p>Just wanted to let you know that <a href="https://github.com/csaez/quicklauncher">QuickLauncher</a> has been updated adding
support for script packages, I uploaded <a href="https://github.com/csaez/quicklauncher_packages">my own scripts to github</a> in case
anyone needs some samples to get started.</p>
<p>There is also a quick demo on vimeo... I know, my english is not very
good …</p><p>Hi guys,</p>
<p>Just wanted to let you know that <a href="https://github.com/csaez/quicklauncher">QuickLauncher</a> has been updated adding
support for script packages, I uploaded <a href="https://github.com/csaez/quicklauncher_packages">my own scripts to github</a> in case
anyone needs some samples to get started.</p>
<p>There is also a quick demo on vimeo... I know, my english is not very
good, but I'm doing my best :)</p>
<p>Cheers!</p>
<div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/82227469?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>DNA buildup test2013-12-03T00:00:00+11:002013-12-03T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-12-03:/2013/12/dna-buildup.html<p>Hi guys,
I just wanted to share some quick excercises I did for an activity at
<a href="http://www.xsiforum.com/forum/index.php/topic,9386.msg93307.html">xsiforum</a>.</p>
<h2>First attemp: Particles</h2>
<p><div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/80919082?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
Scene file and timelapse <a href="https://www.dropbox.com/sh/3v3xra2rssm3d9s/u8YJpAbqiL">here</a>.</p>
<h2>Second attemp: Strands</h2>
<p><div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/81076013?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
ICETrees <a href="https://www.dropbox.com/sh/3v3xra2rssm3d9s/PG5x3nXPDP/strands_version">here</a>.</p>
<p>Back to rigging...</p>
<p>Cheers!</p><p>Hi guys,
I just wanted to share some quick excercises I did for an activity at
<a href="http://www.xsiforum.com/forum/index.php/topic,9386.msg93307.html">xsiforum</a>.</p>
<h2>First attemp: Particles</h2>
<p><div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/80919082?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
Scene file and timelapse <a href="https://www.dropbox.com/sh/3v3xra2rssm3d9s/u8YJpAbqiL">here</a>.</p>
<h2>Second attemp: Strands</h2>
<p><div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/81076013?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
ICETrees <a href="https://www.dropbox.com/sh/3v3xra2rssm3d9s/PG5x3nXPDP/strands_version">here</a>.</p>
<p>Back to rigging...</p>
<p>Cheers!</p>Justin's R&D2013-12-01T00:00:00+11:002013-12-01T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-12-01:/2013/12/justin-rnd.html<div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/80699674?title=0&byline=0&portrait=0" width="900" height="675" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
<p>Hi guys,</p>
<p>Yesterday I found some early R&D work I did for
<a href="http://justinandtheknightsofvalour.com">Justin</a> before joining the team
in Spain (april 2009).</p>
<p>These videos are from the early days and we ended up redesigning almost
everything, but it's interesting see the progression and initial goals.</p>
<p>It is also interesting see …</p><div class="flex-video widescreen"><iframe src="//player.vimeo.com/video/80699674?title=0&byline=0&portrait=0" width="900" height="675" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>
<p>Hi guys,</p>
<p>Yesterday I found some early R&D work I did for
<a href="http://justinandtheknightsofvalour.com">Justin</a> before joining the team
in Spain (april 2009).</p>
<p>These videos are from the early days and we ended up redesigning almost
everything, but it's interesting see the progression and initial goals.</p>
<p>It is also interesting see how naive I was at the time, jumping right into it
without thinking too much in terms of a system (unified guide? really?)...
good old days :)</p>
<p>More videos <a href="http://vimeo.com/album/2630777">here</a>.</p>
<p>Hope you enjoy,
Cheers!</p>A rigger's journey2013-11-13T00:00:00+11:002013-11-13T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-11-13:/2013/11/rigger-journey.html<p>Today I was thinking about how I have shifted my focus as my career
moves forward and I realized that I'm not that special, actually a bunch
of friends have been following the same pattern on their careers.</p>
<p>So, why not write about it?</p>
<h3>First steps</h3>
<p>Exciting times ahead!</p>
<p>Everything …</p><p>Today I was thinking about how I have shifted my focus as my career
moves forward and I realized that I'm not that special, actually a bunch
of friends have been following the same pattern on their careers.</p>
<p>So, why not write about it?</p>
<h3>First steps</h3>
<p>Exciting times ahead!</p>
<p>Everything is new and each successful setup is a victory, I remember myself
learning new things every night before going to sleep and feeling like a
boss. At this stage you should be learning the basics, nothing fancy, but
it's like when you learn a magic trick, you can't stop showing/talking
about it.</p>
<p>This is the time to decide if you really want to be a rigger or simply
hate it as does the rest of humanity.</p>
<h3>Rigger monkey</h3>
<p>Yep, as you move forward and watch every rigging reel on the planet, it
seems natural try to copy the cool stuff out there, I remember when I did
a ribbon setup for the first time, oh boy, I felt so clever.</p>
<p>Sometimes you don't even understand why things work the way they do, but
who cares? it's working!</p>
<h3>Non-flipping madness</h3>
<p>It's time to pursuit those 360º and reinvent the wheel, it doesn't matter
if your animators don't need to twist that much (or whatever you're trying
to implement), the point is that you begin to be able to find solutions
to problems while learning about 'weird things' like quaternions or
transformation matrices... animation requirements? I don't need those,
I can fly! :)</p>
<h3>Meeting scripting</h3>
<p>Do you remember the first steps? well, this is similar, scripting opens
a whole new world of possibilities and you finally are able to implement
those crazy setups in the real world via automation (and also discover
the KISS meaning).</p>
<p>But even better, here's is when you learn how things work under the hood
and how handy were those math classes about linear algebra, trigonometry
and so on.</p>
<p>Here is also when you reimplement all your rigging tools... reinventing
the wheel over and over again.</p>
<h3>'Serious' programming</h3>
<p>At this point you probably know a bit about programming, but I bet you
can't 'live' outside your DCC.</p>
<p>It's time to learn more about programming languages (the language itself),
design patterns and realize that programming is not just about automation
but resource management and fata transformation.</p>
<p>Modular auto-rigger? animation tools? perhaps some standalone application?
Has anyone seen this before?</p>
<h3>Back to the basics</h3>
<p>I'm at this point now, I've coded alot and I love it, but I'm not sure I
always remember why I'm doing it (e.g. I often find myself working on
pipeline-ish stuff).</p>
<p>Now, when I face a new character, I try to focus just on deformation, I don't
care too much about rigging behavior or fancy animation features, just joint
placement and references (a lot of them) until it looks ok and met the
anim requirements (or time's up :P)... then I go and add the fancy stuff
(which is probably automated at this point).</p>
<p>This sort of inverted workflow helps me to quickly iterate on the deformation
side without much overhead and facilitates try new things.</p>
<p><strong>Iteration is key!</strong> don't fool yourself into thinking you have it right
on the first try, nobody does.</p>
<h2>What about you?</h2>
<p>That has been my journey so far, but what about yours?</p>
<p>Was it too different for you?
What stage are you in now?
What's next?</p>
<p>Tell me what you think, cheers! :)</p>Working with pointcloud datasets2013-11-07T00:00:00+11:002013-11-07T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-11-07:/2013/11/scan-files.html<p>Nowadays it's not that unusual having to work with scanned files (point
clouds), but most DCCs don't provide native support for those file formats
and we ended up whether using external converters or parsing ASCII files.</p>
<p>This entry is about the latter.</p>
<p>There's the quick and dirty approach, where we …</p><p>Nowadays it's not that unusual having to work with scanned files (point
clouds), but most DCCs don't provide native support for those file formats
and we ended up whether using external converters or parsing ASCII files.</p>
<p>This entry is about the latter.</p>
<p>There's the quick and dirty approach, where we simply read the file and
create points (nulls, spheres, cubes, whatever) using those coordinates
via scripting, it works (sort of) in very simple scenarios, but it's not
reliable when dealing with large point clouds (and that's usually the case).</p>
<h3>Plan B: recreating a native icecache file!</h3>
<p>Cache files <a href="http://softimage.wiki.softimage.com/index.php?title=Icecache_File_Format#Example_Cache_Writer_Python_Script">can be created using python</a>... but it's a bit
low-level and write such code kinda sucks!</p>
<p>Fortunatelly there's a not-so-known <a href="http://softimage.wiki.softimage.com/support/icecache.rar">python module</a> by Bradley Gabe
that provides a higher level API and free us from dealing with bytes,
data blocks, gzip and other boring stuff.</p>
<p><img alt="Standford Bunny" src="https://www.cesarsaez.me/images/stanford_bunny.jpg" title="Standford Bunny"></p>
<p>So, parsing a xyz file (like <a href="http://coindesigner.sourceforge.net/data/bunny.991.xyz">this</a> stanford bunny) and write an
icecache file to disk should look like this:</p>
<div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
<span class="c1"># -*- coding: utf-8 -*-</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">icecache</span> <span class="c1"># Brad's API</span>
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">xyz_file</span><span class="p">):</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">xyz_file</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">coords</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s2">r"(-?[0-9\.]+)[\s\t\n]+"</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">pos</span> <span class="o">=</span> <span class="p">[[</span><span class="nb">float</span><span class="p">(</span><span class="n">coords</span><span class="p">[</span><span class="n">i</span><span class="p">]),</span> <span class="nb">float</span><span class="p">(</span><span class="n">coords</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]),</span> <span class="nb">float</span><span class="p">(</span><span class="n">coords</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">])]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">coords</span><span class="p">))[::</span><span class="mi">3</span><span class="p">]]</span>
<span class="n">ic</span> <span class="o">=</span> <span class="n">icecache</span><span class="o">.</span><span class="n">icecache</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">pos</span><span class="p">))</span>
<span class="n">ic</span><span class="o">.</span><span class="n">addPointPosition</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="n">ic</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"{}.icecache"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">xyz_file</span><span class="p">)[</span><span class="mi">0</span><span class="p">]))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">".xyz"</span><span class="p">):</span>
<span class="n">parse</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">"Invalid file type"</span><span class="p">)</span>
</pre></div>
<p>Now, how cool is that? a simple regex plus 3 calls to Brad's API and
we're done.</p>
<p>Cheers!</p>Speaking Maxscript2013-10-31T00:00:00+11:002013-10-31T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-10-31:/2013/10/speaking-maxscript.html<p>Hi guys,</p>
<p>Today a friend asked for a quick way to create independent copies/instances
of an object at each vertex position of another mesh in 3dsmax.</p>
<p>I haven't worked with 3dsmax for a long time, but it seemed to be a job
for maxscript and she knows nothing about …</p><p>Hi guys,</p>
<p>Today a friend asked for a quick way to create independent copies/instances
of an object at each vertex position of another mesh in 3dsmax.</p>
<p>I haven't worked with 3dsmax for a long time, but it seemed to be a job
for maxscript and she knows nothing about scripting, so I took a deep
breath and gave it a shot.</p>
<div class="highlight"><pre><span></span>for v in $[1].mesh.verts do (instance $[2]).pos = v.pos * $[1].transform
</pre></div>
<p>Here's the thing: maxscript turned out to be surprisingly straight forward,
I mean, this kind of stuff could be done in any DCC, but things like operator
overloading or grouping by parentheses really help to lower the
barrier and keep things simple.</p>
<p>Maxscript has some annoying parts for sure, but I have to admit it's a
lot simpler/easy-to-use than I remembered.</p>
<p>Cheers!</p>Hard Reload2013-10-25T00:00:00+11:002013-10-25T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-10-25:/2013/10/hard_reload.html<p>Hi folks,</p>
<p>If you're a python developer this shouldn't be new for you, but I struggled
a lot with this back in the day and thought it might be helpful share
some of the lessons learned.</p>
<p>Each time you import a python module in a session it get cached in …</p><p>Hi folks,</p>
<p>If you're a python developer this shouldn't be new for you, but I struggled
a lot with this back in the day and thought it might be helpful share
some of the lessons learned.</p>
<p>Each time you import a python module in a session it get cached in a global
dictionary called <code>sys.modules</code>, this helps to speedup things and allow a better
memory management. If you really need to refresh that cache for a specific module
(because of a code change or whatever) python provides a nice function
called <code>reload()</code>.</p>
<p>So far so good, it works great! The only 'problem' is that you must
explicitly call it, I mean, you must call it after each import.</p>
<h3>What about packages?</h3>
<p>I often write my stuff as a package, and having to explicitly reload each
module could be cumbersome, not to mention having to remove those calls in
production code... I'm too lazy for that.</p>
<p>Fortunatelly there is a workaround!</p>
<p>As sys.modules is just a standard dictionary it's possible manipulate the
raw data by yourself. This can cause some side effects because you would
be messing with python's global state, but to be honest it has saved my
ass a couple of times.</p>
<p>USE AT YOUR OWN RISK.</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="k">def</span> <span class="nf">hard_reload</span><span class="p">(</span><span class="n">package_name</span><span class="p">):</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
<span class="k">if</span> <span class="n">k</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">package_name</span><span class="p">):</span>
<span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
<span class="n">hard_reload</span><span class="p">(</span><span class="s2">"my_super_package"</span><span class="p">)</span>
</pre></div>
<p>By the way, kudos to <a href="http://agedito.com">Ángel Pavón</a> for the tip!</p>
<p>Cheers</p>Moving to pelican2013-10-22T00:00:00+11:002013-10-22T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-10-22:/2013/10/moving_to_pelican.html<p>I did it! I finally switched to a 'static' site :)</p>
<h2>Why?</h2>
<p>To be honest I was bored of the 'blogging platforms' overhead.</p>
<p>For simple use cases there's the good ol' <a href="http://www.blogger.com">blogger</a>, it works fine
and it's quite secure but has some serious limitations on the customization
side and its templates …</p><p>I did it! I finally switched to a 'static' site :)</p>
<h2>Why?</h2>
<p>To be honest I was bored of the 'blogging platforms' overhead.</p>
<p>For simple use cases there's the good ol' <a href="http://www.blogger.com">blogger</a>, it works fine
and it's quite secure but has some serious limitations on the customization
side and its templates are extremely messy (all in one big xml file).</p>
<p>So, if you want to go custom the obvious choice seems to be <a href="http://www.wordpress.org">wordpress</a>,
I've used it for a while and it works well, but it requires a hell of
maintenance in order to stay away of security problems... I thought 'nobody
would like to hack a personal blog' and there you go, I was hacked twice.
I think there are so many sites running on top of wordpress that it's not
that improbable get randomly hacked because of a new vulnerability.</p>
<p>At the end I just wanted a simple blogging platform (no need for e-commerce
or any fancy feature, just blogging), secure and easy to use... it seems a
perfect use case for a static site generator :)</p>
<h3>How does it works?</h3>
<p>You write your posts as text files using a simple markup lenguague
(markdown, ReST, YAML) and the generator parse the content and rebuild
the entire site for you.</p>
<p>The output is static site but as you can rebuild the entire thing in no
time it works perfectly on personal sites like this one.</p>
<h3>What about comments?</h3>
<p>Yep, comments are dynamic by nature so the only way to implement them on
a static sites is via external services + some javascript.</p>
<p>I was using google+ comments on <a href="http://www.blogger.com">blogger</a> and I could implement them
here too, but they are too attached to google plus and I prefered use a
less intrusive service like <a href="http://disqus.com/">disqus</a>.</p>
<h3>What about publishing?</h3>
<p>Upload the entire site each time I write or edit something could be
annoying, but <em>there is the cloud!</em></p>
<p>There are many cloud services that could be handy on this one, a quick
search lead us to people hosting their sites via <a href="http://www.dropbox.com">dropbox</a>,
<a href="http://www.github.com">github</a>, <a href="http://www.heroku.com">heroku</a> and many many others.</p>
<p>Since I'm already using <a href="http://www.git-scm.com">git</a> and <a href="http://www.github.com">github</a> for my open source
projects I decided to add this site too, perhaps it's not the
best solution from a CEO point of view but I really don't care too much
about that and <a href="http://pages.github.com/">github pages</a> makes it almost
efortless, I just push the generated output to a specific branch and
github serves the latest version.</p>
<h3>Why pelican?</h3>
<p>I was really tempted by <a href="http://www.jekyllrb.com">jekyll</a> but it's written in <a href="http://www.ruby-lang.org">ruby</a>
and I'm not familiar with the language, so I ended up looking for a
<a href="http://www.python.org">python</a> based one and <a href="http://pelican.readthedocs.org">pelican</a> seemed to be quite popular
(<a href="http://www.getnikola.com">nikola</a> looked promising too).</p>
<h2>Migrating</h2>
<p>Migrate implied export the blog posts to markdown and tweak the templates,
it tooks some time but wasn't that difficult.</p>
<h4>Posts to markdown:</h4>
<p>I love the idea of start using <a href="http://daringfireball.net/projects/markdown/">markdown</a> as writing formating for my
posts, it's easy to the eyes and fits nicely with the 'separation of
conserns' filosophy.</p>
<p>Pelican offers some automatic migration tools, I tried converting the rss
feed to markdown and it 'worked' but just as a base, I ended up tweaking
all markdown files by hand. Fortunatelly (?) I didn't have much articles
on blogger (remember those wordpress hack attacks? yep...) and wasn't that
painfull.</p>
<h4>Templates:</h4>
<p>Pelican uses <a href="http://jinja.pocoo.org">jinja2</a> as template engine, the templates are a bit low
level compared with Jekyll's ones but they are much more powerfull and, as
jinja is python based, you can pass all kind of metadata between
pages/articles/config files.</p>
<p>I also wanted to redesign the site and somehow update my 'webdev skills',
last time I built a website was using macromedia dreamweaver 10 years ago
(you know, hardcoded tables everywhere and all kind of webdev atrocities).</p>
<h3>tl;dr</h3>
<p>I finally migrated to a static site that can be customized, it is secure,
open source and that I understand (no black boxes here).</p>
<p>I honestly don't think this is the right move for everyone, but if you are
somewhat technical it's well worth it.</p>Why python?2013-09-26T00:00:00+10:002013-09-26T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-09-26:/2013/09/why-python.html<p>Hey guys,</p>
<p>Yesterday night my brother (who is a 'real programmer') asked me 'why
someone would use python?' and I didn't know how to answer.</p>
<p>I think python is awesome, an object-oriented programming language with
'batteries included', open source, great for prototyping (no boiler
plate, mostly crossplatform, with a lot …</p><p>Hey guys,</p>
<p>Yesterday night my brother (who is a 'real programmer') asked me 'why
someone would use python?' and I didn't know how to answer.</p>
<p>I think python is awesome, an object-oriented programming language with
'batteries included', open source, great for prototyping (no boiler
plate, mostly crossplatform, with a lot of convenient features and
clever built-in types).... But in a broader context, well, it's a tough
question.</p>
<p>Perhaps python's best feature is its <a href="http://www.python.org/dev/peps/pep-0020/">Zen</a>, it's the glue that holds
it all together.</p>
<ol>
<li>Beautiful is better than ugly.</li>
<li>Explicit is better than implicit.</li>
<li>Simple is better than complex.</li>
<li>Complex is better than complicated.</li>
<li>Flat is better than nested.</li>
<li>Sparse is better than dense.</li>
<li>Readability counts.</li>
<li>Special cases aren’t special enough to break the rules.</li>
<li>Although practicality beats purity.</li>
<li>Errors should never pass silently.</li>
<li>Unless explicitly silenced.</li>
<li>In the face of ambiguity, refuse the temptation to guess.</li>
<li>There should be one– and preferably only one –obvious way to do it.</li>
<li>Although that way may not be obvious at first unless you’re Dutch.</li>
<li>Now is better than never.</li>
<li>Although never is often better than right now.</li>
<li>If the implementation is hard to explain, it’s a bad idea.</li>
<li>If the implementation is easy to explain, it may be a good idea.</li>
<li>NameSpaces are one honking great idea — let’s do more of those!</li>
</ol>
<p>What do you think? What makes python so awesome?</p>
<p>Cheers!</p>Animation is organization2013-09-10T00:00:00+10:002013-09-10T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-09-10:/2013/09/anim-concentration-slides.html<p>Hi guys,</p>
<p>I'll be giving a lecture this weekend at San Luis Digital (San Luis,
Argentina). I'll talk about how we use agile software development
methodology on the rigging department during my adventures at <a href="http://www.kandorgraphics.com/en">Kandor
Graphics</a> and some basics of pipeline in animated films.</p>
<p>Here is a link to the …</p><p>Hi guys,</p>
<p>I'll be giving a lecture this weekend at San Luis Digital (San Luis,
Argentina). I'll talk about how we use agile software development
methodology on the rigging department during my adventures at <a href="http://www.kandorgraphics.com/en">Kandor
Graphics</a> and some basics of pipeline in animated films.</p>
<p>Here is a link to the slide deck (spanish only), there're plenty of
animated gifs, memes and graphics so I don't think that language is such
a big deal on this one.</p>
<ul>
<li><a href="http://csaez.github.io/slides_anim">LIVE (heavy on images, might take a while)</a></li>
<li><a href="http://www.github.com/csaez/slides_anim">Repo</a></li>
</ul>
<p>So, if you're going to be in San Luis this weekend please join us at
SLD, it'll be fun :-)</p>
<p>Cheers!</p>
<p>By the way, reveal.js rocks!</p>Softimage.tv2013-09-09T00:00:00+10:002013-09-09T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-09-09:/2013/09/softimagetv.html<p>Hi folks,</p>
<p>Some time ago <a href="http://www.linkedin.com/in/cgcris">Cristobal</a> told me about his idea of a website
showcasing the best work created with Softimage, I liked it and we
started working on it until last week when we launched <a href="http://softimage.tv/">softimage.tv</a></p>
<p>There're a lot of amazing works done with Softimage but they are …</p><p>Hi folks,</p>
<p>Some time ago <a href="http://www.linkedin.com/in/cgcris">Cristobal</a> told me about his idea of a website
showcasing the best work created with Softimage, I liked it and we
started working on it until last week when we launched <a href="http://softimage.tv/">softimage.tv</a></p>
<p>There're a lot of amazing works done with Softimage but they are
scattered all over the place, we want to fix this through a
community-driven website showcasing the best works out there and making
things easier for newcomers (not to mention producers, agencies and
decision makers).</p>
<p>The community response has been HUGE (thanks guys), we have a lot of
ideas to improve the site and add new stuff, but we still need your
help.</p>
<p>If you ever created a tutorial for softimage, uploaded a test, done an
amazing tool, have a showreel to show off, finished a good looking job,
please help us by submitting it.</p>
<p>We would love to know what you guys think about it, and how we can move
things forward.</p>
<p>Cheers!</p>Git For Softimage2013-07-19T00:00:00+10:002013-07-19T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-07-19:/2013/07/git-for-softimage.html<p>Hi folks,</p>
<p>I've been using <a href="http://www.git-scm.com">Git</a> as version control system on my
developments for a while and thought it might be useful add some version
control abilities to my softimage projects too.</p>
<p><a href="https://github.com/csaez/gitforsoftimage">https://github.com/csaez/gitforsoftimage</a></p>
<p><img alt="Git for Softimage" src="https://www.cesarsaez.me/images/git-softimage.png" title="Git for Softimage"></p>
<p>It implements:</p>
<ul>
<li>Commit history</li>
<li>Branching</li>
<li>Remotes</li>
</ul>
<p>If you don't want to continue the …</p><p>Hi folks,</p>
<p>I've been using <a href="http://www.git-scm.com">Git</a> as version control system on my
developments for a while and thought it might be useful add some version
control abilities to my softimage projects too.</p>
<p><a href="https://github.com/csaez/gitforsoftimage">https://github.com/csaez/gitforsoftimage</a></p>
<p><img alt="Git for Softimage" src="https://www.cesarsaez.me/images/git-softimage.png" title="Git for Softimage"></p>
<p>It implements:</p>
<ul>
<li>Commit history</li>
<li>Branching</li>
<li>Remotes</li>
</ul>
<p>If you don't want to continue the 'incremental save' madness, or if you
are looking for an easy way to collaborate with others in small
projects, give it a try, it's free and open!</p>
<p>Let me know what you think,</p>
<p>Cheers.</p>
<p>By the way, if you're not familiar with distributed version control
systems there are a few key concepts that must be considered, don't
forget to check the <a href="http://github.com/csaez/gitforsoftimage/wiki">documentation</a>.</p>QuickLauncher2013-06-30T00:00:00+10:002013-06-30T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-06-30:/2013/06/quicklauncher.html<p>Hey folks,</p>
<p>Today I want to share a tool I've been using for a while, it's a simple
menu to search and launch softimage commnads and scripts (you can set
the script directory on the preferences).</p>
<p><img alt="QuickLauncher Demo" src="https://www.cesarsaez.me/images/quicklauncher.gif" title="QuickLauncher Demo"></p>
<p>In order to make it fast I'm caching the commands and script paths (just …</p><p>Hey folks,</p>
<p>Today I want to share a tool I've been using for a while, it's a simple
menu to search and launch softimage commnads and scripts (you can set
the script directory on the preferences).</p>
<p><img alt="QuickLauncher Demo" src="https://www.cesarsaez.me/images/quicklauncher.gif" title="QuickLauncher Demo"></p>
<p>In order to make it fast I'm caching the commands and script paths (just
the paths, the script itself is loaded on runtime), so if you add a new
script file or connect/disconnect workgroups please make sure that the
cache is reloaded (there's a command just for that) and everything
should be fine.</p>
<p>The menu requires <a href="http://github.com/caron/PyQtForSoftimage">PyQtForSoftimage</a> and it's available <a href="http://github.com/csaez/quicklauncher">here</a>.</p>
<p>Give it a try and let me know what you think :-)</p>
<p>Cheers!</p>RigIcon goes open source2013-06-25T00:00:00+10:002013-06-25T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-06-25:/2013/06/rigicon-opensource.html<p>Hi folks,</p>
<p>Do you remember <a href="http://csaez.blogspot.com/2013/01/wip-csrigicon.html">rigicon</a>? well, now you can get it from <a href="https://github.com/csaez/rigicon">github</a>!</p>
<p><img alt="RigIcon" src="https://www.cesarsaez.me/images/rigicon.png" title="RigIcon"></p>
<p>There's also a brief <a href="https://github.com/csaez/rigicon/wiki">documentation</a> and a <a href="http://goo.gl/XRtKA">pre-packed xsiaddon</a> in
case you don't want to mess with the source code, dependencies and so
on... if you have no idea what I'm talking about take a look …</p><p>Hi folks,</p>
<p>Do you remember <a href="http://csaez.blogspot.com/2013/01/wip-csrigicon.html">rigicon</a>? well, now you can get it from <a href="https://github.com/csaez/rigicon">github</a>!</p>
<p><img alt="RigIcon" src="https://www.cesarsaez.me/images/rigicon.png" title="RigIcon"></p>
<p>There's also a brief <a href="https://github.com/csaez/rigicon/wiki">documentation</a> and a <a href="http://goo.gl/XRtKA">pre-packed xsiaddon</a> in
case you don't want to mess with the source code, dependencies and so
on... if you have no idea what I'm talking about take a look at the <a href="https://vimeo.com/56682095">old
preview</a>.</p>
<p>You will need <a href="https://github.com/caron/PyQtForSoftimage">PyQtForSoftimage</a> installed in your system, other than
that everything should work fine OOTB.</p>
<p>Cheers!</p>Justin - Theatrical Trailer2013-05-23T00:00:00+10:002013-05-23T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-05-23:/2013/05/justin-trailer.html<div class="flex-video widescreen">
<iframe width="853" height="480" src="//www.youtube-nocookie.com/embed/nJPlEoXdfVw?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p>Hi folks,</p>
<p>There's a new trailer for Justin and the Knights of Valor, a Kandor
Graphics film where I had the pleasure of working as Rigging
Supervisor.</p>
<p>Working on this project was an AMAZING experience, I was able to jump
into the project from the beginning and participate in the …</p><div class="flex-video widescreen">
<iframe width="853" height="480" src="//www.youtube-nocookie.com/embed/nJPlEoXdfVw?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p>Hi folks,</p>
<p>There's a new trailer for Justin and the Knights of Valor, a Kandor
Graphics film where I had the pleasure of working as Rigging
Supervisor.</p>
<p>Working on this project was an AMAZING experience, I was able to jump
into the project from the beginning and participate in the design of
almost everything rigging related, help shaping the character pipeline
and work with some of the most talented/clever guys I've ever met (well
done guys, you rock!).</p>
<p>I can't wait to see it in theaters... and don't forget to watch the
trailer in HD ;)</p>
<p>Cheers!</p>Time to move on2013-05-07T00:00:00+10:002013-05-07T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2013-05-07:/2013/05/time-to-move-on.html<p>Hey folks,</p>
<p>Just wanted to say hello, been a long time without news here :(</p>
<p>Well... where to start... I came back to my hometown (Santiago, Chile) a
month ago or so, my time living in Spain was AWESOME but <a href="http://www.justinandtheknightsofvalour.com/">the project</a>
is over and it's time to start moving again …</p><p>Hey folks,</p>
<p>Just wanted to say hello, been a long time without news here :(</p>
<p>Well... where to start... I came back to my hometown (Santiago, Chile) a
month ago or so, my time living in Spain was AWESOME but <a href="http://www.justinandtheknightsofvalour.com/">the project</a>
is over and it's time to start moving again.</p>
<p>In the meantime, my father passed away a couple of weeks ago. I don't
wanna talk too much about it here, but it was a hard news to swallow.</p>
<p>Anyway... I have to move on and start doing things again!</p>
<p>I have a lot of unfinished personal projects waiting for a spark of
motivation and a demo reel to make in order to start a job hunting. </p>
<p>Let me press the reset button and I'll get back to you with better news
soon.</p>
<p>Cheers!</p>RigLab: Preview #0012013-02-11T00:00:00+11:002013-02-11T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-02-11:/2013/02/riglab-preview-001.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/59434478?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>Today I wanna share an early preview of the rigging framework I've been
working on, there's still a lot of work to do but I think the core
concepts are there.</p>
<p>Let me know what you think about it :)</p>
<p>Cheers!</p><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/59434478?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hi guys,</p>
<p>Today I wanna share an early preview of the rigging framework I've been
working on, there's still a lot of work to do but I think the core
concepts are there.</p>
<p>Let me know what you think about it :)</p>
<p>Cheers!</p>RigLab: Naming Convention2013-01-10T00:00:00+11:002013-01-10T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-01-10:/2013/01/riglab-naming-convention.html<p>Hey folks,</p>
<p>I've been working on the naming convention side of the rigging framework
and I wanna share my take on this problem.</p>
<p>I know, this isn't the hotest subject to talk about, but as it's a so
general problem I thought could be interesting for you too.</p>
<h3>First of …</h3><p>Hey folks,</p>
<p>I've been working on the naming convention side of the rigging framework
and I wanna share my take on this problem.</p>
<p>I know, this isn't the hotest subject to talk about, but as it's a so
general problem I thought could be interesting for you too.</p>
<h3>First of all: a disclaimer...</h3>
<p>A lot of things I'm developing for this project are influenced by the
way I'm used to work. I'm not trying to steal ideas from anyone, it's
inevitable carry with me some concepts that I found interesting and make
them mine.</p>
<p>Thanks to all who shared their thoughts on pipeline/coding with me along
the years. Lots of inspiration comes from those talks!</p>
<h2>What's a naming convention?</h2>
<p><img alt="naming Convention" src="https://www.cesarsaez.me/images/riglab_namingconvention.jpg" title="Naming Convention"></p>
<p>As you may know, a naming convention is just an agreement about the
information and the format we will be using to define a name.</p>
<h3>So, what's the big deal?</h3>
<p>Well, let me break things up a little bit...</p>
<p><em>On the user side</em> it's just a convention and we are clever
enough to remember it, so it's completely up to the user assign names
properly. Some studios provide sophisticated tools to help them on the
task, but in my experience a simple renamer tool (string operations)
with some batch capabilities is enough in most cases.</p>
<p><em>On the code side</em> it's a completely different story,
code/software is not smart enough to figure out a naming convention so
we have to be very explicit about it.</p>
<p>One way to tackle the problem is just hardcoding names, we all have been
there at some point. It just works, but turns out to be a really bad
idea in the long run.</p>
<p>The conventions usually evolve/change between projects/clients, if you
hardcode things then all your tools become useless unless you revisit
the code and change everything name related.</p>
<p>The other way is create a layer to solve the names using the conventions
and work with those names on your code, this way you have a centralized
place where set the new naming requirements and all your tools becomes
name independent.</p>
<p>I obviously recommend the second approach.</p>
<h3>What has been done in the framework?</h3>
<p>If we go back to the <a href="http://csaez.blogspot.com/2012/11/csriglab-overview.html">project goals</a>, there is a specific one about
naming convention, let me quote it.</p>
<blockquote>
<p>The system will be based on metadata rather than any specific naming
convention. The naming convention will be based on a config file in
order to integrate the system on any pipeline (the same is true with
colours, animation controls and all the standard rigging conventions).</p>
</blockquote>
<p>At first I worked in a metadata API to store everything, but as the
project progresses, I realized that access metadata is not user-friendly
at all and it would be very difficult to trust the data if it's not
updated by the user... and the system must assign a name to new objects
anyway!</p>
<p>So in an unexpected turns of events, I still use metadata to store
specific things but I also worked on a system that allows me use the
data stored in the naming convention (which are much more likely to be
updated by the user).</p>
<p>A cool thing about the new manager is that ended up being software
agnostic, so it can be used in mixed pipelines too.</p>
<p>You can see how it works in the video below.</p>
<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/57161770?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<h3>API Design</h3>
<p>When it comes to naming convention is really dificult design an
easy-to-use API, it's difficult because we have to specify every 'token'
value but at the same time we shouldn't be typing any longer than the
name itself.</p>
<p>In my experience if you're working with a too intricated API, the
temptation to hardcode names tend to be too high (especially in
scripting) and the whole system becomes meaningless.</p>
<p>Here are a couple of simple concepts that helped me to create an easy to
use design.</p>
<h4>Manager:</h4>
<p><em>If you don't want to be too explicit you are probably looking for a way
to share 'global' information, in my case I decided to work with a
manager as a layer for the 'naming resolution' stuff instead of just at
a module level, this way I can work with some 'global' values instead of
specified them each time.</em></p>
<h4>Active Rule:</h4>
<p><em>The manager expect an active rule to work with, you can set/get the
active rule at anytime. Using this way to deal with rules allow us be a
lot less explicit on each name solving and let the manager do some
clever stuff to figure out how to arrange the name using the incoming
arguments.</em></p>
<h4>Override:</h4>
<p><em>We can override default values at a manager level at any time, this
becomes really handy when you're working on the same context and don't
want to be explicit about every token on every name.</em></p>
<p>I hope this make sense,</p>
<p>Cheers!</p>RigLab: RigIcon2013-01-03T00:00:00+11:002013-01-03T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2013-01-03:/2013/01/riglab-rigicon.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/56682095?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hey folks,</p>
<p>This time I wanna share a preview of some rigging tools I'm working on.
They're highly inspired by Softimage null's implementation but with some
advantages that you can see in the video below (sorry for my english
:P).</p>
<p>The csRigIconEditor GUI was a really nice exercise, it's a …</p><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/56682095?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Hey folks,</p>
<p>This time I wanna share a preview of some rigging tools I'm working on.
They're highly inspired by Softimage null's implementation but with some
advantages that you can see in the video below (sorry for my english
:P).</p>
<p>The csRigIconEditor GUI was a really nice exercise, it's a simple UI but
as Softimage has no native PyQt implementation we have to handle the
sincronization with the selection by ourselves. At the end was a lot of
fun and I learned a couple of new tricks :)</p>
<p>I will be sharing this and all my tools with the first public version of
the <a href="http://csaez.blogspot.com.es/2012/11/csriglab-overview.html">rigging framework</a>, so they should be available soon.</p>
<p>Cheers!</p>Justin - Official Teaser Trailer2012-11-23T00:00:00+11:002012-11-23T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-11-23:/2012/11/justin-teaser.html<div class="flex-video widescreen">
<iframe width="853" height="480" src="//www.youtube-nocookie.com/embed/7v1owpEEdwA?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p>Here it is... check out the first teaser trailer for the film in which
I've been working on, has been a blast! :)</p>
<p>More at <a href="http://justinandtheknightsofvalour.com/">http://justinandtheknightsofvalour.com</a></p><div class="flex-video widescreen">
<iframe width="853" height="480" src="//www.youtube-nocookie.com/embed/7v1owpEEdwA?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p>Here it is... check out the first teaser trailer for the film in which
I've been working on, has been a blast! :)</p>
<p>More at <a href="http://justinandtheknightsofvalour.com/">http://justinandtheknightsofvalour.com</a></p>RigLab: overview2012-11-13T00:00:00+11:002012-11-13T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-11-13:/2012/11/riglab-overview.html<p>I'm finally working on my rigging framework, I've been thinking about it
for a long time and I finally have a clear picture of what I want as end
result... and even more important, why I want it that way!</p>
<p>There will be plenty of new problems to be sorted …</p><p>I'm finally working on my rigging framework, I've been thinking about it
for a long time and I finally have a clear picture of what I want as end
result... and even more important, why I want it that way!</p>
<p>There will be plenty of new problems to be sorted out as I go with the
development, but the overall design and workflows are clear on my mind
now.</p>
<h3>So, why a framework?</h3>
<p>I've already written 3 autorigs for different productions, 2 of them for
3dsmax (advertising projects and a TV series) and the latest one for
softimage (feature film)... The "autorig philosophy" allow us to work
faster and helps to standarize things, but at the end it's not enough.</p>
<p>If you limit yourself to make a rig-builder/autorig, at some point it
will be obvious that you're leaving a lot behind, the solution tend to
be specific to the nature of the asset (bipeds, quadrupeds and so on)
and sometimes it's difficult to update/expand it without refactoring the
system. So we end up creating new autorigs to cover unexpected
requirements (props, vehicles, environments, facial rigs, whatever)
rather than unify and keep them under the same roof.</p>
<p>A framework lives in a much more general level and represents that roof,
describes the way you manage/work-with rigs. The autorigs (I call them
solvers) are built on top, so you always have control over your rigs no
matter how they were built (including by hand).</p>
<h3>Goals</h3>
<p>In order to get this done in a reasonable time frame I've to set some
goals for the project, the following list represent the main ones (in
arbitrary order).</p>
<h4>Metadata:</h4>
<p>The system will be based on metadata rather than any specific naming
convention. The naming convention will be based on a config file in
order to integrate the system on any pipeline (the same is true with
colours, animation controls and all the standard rigging conventions).</p>
<h4>Multipose support:</h4>
<p>The framework should allow us to define a rigging pose (by default will
be the same as the binding pose). This is important because the binding
pose isn't always the best for rigging/animation purposes (nonorthogonal
limbs and stuff like that).</p>
<h4>Macro support for solvers' creation:</h4>
<p>This is HUGE! When you're on production and there's a need for a new
kind of rigging solution, code it and update the rigging system isn't
the fastest solution (sometimes it's not even possible). Support a sort
of macro to facilitate the solver's creation will help to keep the
rigging system alive and updated.</p>
<h4>Non-linear workflow:</h4>
<p>The rigging process is an iterative one, the system should allow us go
back to the creation state for editing/updating. A rig is never really
finished and we need a bidirectional way to work with them.</p>
<h4>Robust API (application programming interface):</h4>
<p>From my point of view the system has 2 clients: the gui (graphic user
interface) and another programs/tools, the system should be able to work
with both (this include batch processing).</p>
<h3>Current status</h3>
<p>The overall design and the workflow are finished (I'm still documenting,
but I have a clear picture of how everything should work). Right now I'm
working on the metadata manager and starting the multipose part.</p>
<p>There're a lot of work to do in order to get it up and running, but this
time I really want to materialize these ideas into something useful, I
will be working actively in the coming months to complete the project as
soon as possible.</p>
<p>Hope to have something interesting to show in the next post, we'll see
;-)</p>
<p>Cheers!</p>DevManager: yet another plugin manager2012-10-29T00:00:00+11:002012-10-29T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-10-29:/2012/10/devmanager.html<p>Hi folks,</p>
<p>I've been working on a manager for my developments, something like
softimage's plugin manager but better suited for my workflow (python
modules for the logic and pyQT for GUIs).</p>
<p>When I was working at <a href="http://www.kandorgraphics.com/en">Kandor Graphics</a> we had some similar tools
(much more robust and sophisticated, of course …</p><p>Hi folks,</p>
<p>I've been working on a manager for my developments, something like
softimage's plugin manager but better suited for my workflow (python
modules for the logic and pyQT for GUIs).</p>
<p>When I was working at <a href="http://www.kandorgraphics.com/en">Kandor Graphics</a> we had some similar tools
(much more robust and sophisticated, of course), was one of the firsst
things they tackled and turned out to be an excellent decision on the
long run.</p>
<h3>Let's see some features...</h3>
<p><code>csDevManager</code> has 2 modes, the basic one works like a launcher for all my
custom commands, nothing too exciting here.</p>
<p><img alt="csDevManager" src="https://www.cesarsaez.me/images/csDevManager.jpg" title="csDevManager"></p>
<p>The developer mode is where it gets interesting, in this mode you can
see all the Addons/Developments and their plugins (including properties,
events and almost everything you can register on softimage).</p>
<p>Through the context menu you can access the reload function, this allow
you reload all python modules used in the addon, recompile the QT stuff
and reload the softimage's plugin in one click (big time saver).</p>
<p>You can also edit UI files (using QT Designer), explore directories,
create new addons, plugins and remove existing ones.</p>
<p>Another nice addition is a new sdk wizard with updated templates, this
makes really easy create new plugins.</p>
<p>And at last but not less, you have access to an API that allows you do
"everything" related to your addons, every you see in the GUI is doable
via API in a OOP way.</p>
<p>I've to do some clean up in order to make it completely generic, I'll
make a github repository with all my tools and share them as open source
ASAP.</p>
<p>Next step: work on my rigging framework using all I've learned in the
past years :)</p>
<p>Cheers!</p>Thoughts on editing2012-10-05T00:00:00+10:002012-10-05T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-10-05:/2012/10/thoughts-on-editing.html<p>Just a quick tip...</p>
<blockquote>
<p>When you make a tool, don't think about it as a 1-time procedure,
editing will take most of the time and you should provide support for
it.</p>
</blockquote>
<p>I see this a lot!</p>
<p>Almost every autorig out there do not offer any control over the setups
already …</p><p>Just a quick tip...</p>
<blockquote>
<p>When you make a tool, don't think about it as a 1-time procedure,
editing will take most of the time and you should provide support for
it.</p>
</blockquote>
<p>I see this a lot!</p>
<p>Almost every autorig out there do not offer any control over the setups
already created and rebuild is the only provided solution (which is not
realistic in many cases).</p>
<p>So, think about it and make your next tool much more useful!</p>
<p>Cheers.</p>Convex Approximation2012-09-24T00:00:00+10:002012-09-24T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-09-24:/2012/09/convex-approximation.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/50052145?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Back to the basics!</p>
<p>I've been thinking about how to use a convex approximation to improve
"volume preservation" on enveloped meshes and I finally had time to do a
proof of concept.</p>
<p>There's a lot to do in order to make it usable in a production
environment but seems to …</p><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/50052145?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>Back to the basics!</p>
<p>I've been thinking about how to use a convex approximation to improve
"volume preservation" on enveloped meshes and I finally had time to do a
proof of concept.</p>
<p>There's a lot to do in order to make it usable in a production
environment but seems to work!</p>
<p>More to come...</p>
<p>Cheers!</p>Holymonks' face rig2012-09-18T00:00:00+10:002012-09-18T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-09-18:/2012/09/holymonks-face-rig.html<p>Hey guys,</p>
<p>I did this one <strong>a while ago</strong> but I never share it here, it's a custom
tool designed to quickly wire up facial rig for an <a href="http://www.holymonks.com/">animated tv
series</a>.</p>
<p>The rig itself has nothing special but it worked fine for their
needs/schedule constraints, so everyone happy :-)</p>
<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/10910710?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div><p>Hey guys,</p>
<p>I did this one <strong>a while ago</strong> but I never share it here, it's a custom
tool designed to quickly wire up facial rig for an <a href="http://www.holymonks.com/">animated tv
series</a>.</p>
<p>The rig itself has nothing special but it worked fine for their
needs/schedule constraints, so everyone happy :-)</p>
<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/10910710?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>fStretch-like deformations2012-09-17T00:00:00+10:002012-09-17T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-09-17:/2012/09/fstretch.html<p>Some time ago <a href="http://www.si-community.com/community/viewtopic.php?f=15&t=2549&p=20551#p20551">someone asked in si-community.com</a> about how to
replicate some deformations seen in <a href="https://vimeo.com/45473465">a nice demo from Clovis Gay</a> (who
is also inspired by the <a href="http://www.cgaddict.com/product-overview.html">fStretch plugin for Maya</a>) so I decided give
it a shot.</p>
<p><img alt="fStretch demo" src="https://www.cesarsaez.me/images/fstretch_movie.gif" title="fStretch Demo"></p>
<p>I'm solving it in 2 steps; the first ICETree stores a …</p><p>Some time ago <a href="http://www.si-community.com/community/viewtopic.php?f=15&t=2549&p=20551#p20551">someone asked in si-community.com</a> about how to
replicate some deformations seen in <a href="https://vimeo.com/45473465">a nice demo from Clovis Gay</a> (who
is also inspired by the <a href="http://www.cgaddict.com/product-overview.html">fStretch plugin for Maya</a>) so I decided give
it a shot.</p>
<p><img alt="fStretch demo" src="https://www.cesarsaez.me/images/fstretch_movie.gif" title="fStretch Demo"></p>
<p>I'm solving it in 2 steps; the first ICETree stores a tension/stress map
<em>before</em> any deformation, the second does the same <em>after</em> the deformations
and compares the results. The delta between both states is used to drive
a push operator (sort of).</p>
<p>There's nothing faster than ICE for this kind of prototypes, love it! :)</p>
<p><img alt="fStretch ICETree" src="https://www.cesarsaez.me/images/fstretch_ICETree.jpg" title="fStretch ICETree"></p>
<p>As a side note, I'm working on some personal projects mostly for
Softimage but I'm also giving a closer look at pyMel (not as bad as I
remembered). Still early but seems possible make them cross-platform,
imply some extra work but seems like a nice oportunity to learn a lot
about Maya, we'll see...</p>
<p>More updates soon, stay tunned</p>
<p>Cheers!</p>Back to work2012-08-26T00:00:00+10:002012-08-26T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-08-26:/2012/08/back-to-work.html<p>I think I have enough sun and beach this summer and it's time to get
back to work!</p>
<p>Unfortunatelly I can't show anything from <a href="http://www.kandorgraphics.com/en/">kandor graphics</a> (my last 4
years of work are "production locked" until next year), so the plan is
start to work on a RnD reel since …</p><p>I think I have enough sun and beach this summer and it's time to get
back to work!</p>
<p>Unfortunatelly I can't show anything from <a href="http://www.kandorgraphics.com/en/">kandor graphics</a> (my last 4
years of work are "production locked" until next year), so the plan is
start to work on a RnD reel since September until the end of this year.</p>
<p>But it isn't a bad thing at all, it's a great oportunity to develop some
ideas and tools I have in mind since long time ago, when you're in
production it's really difficult try new things and now I really wanna
take that oportunity. I have a good feeling about this :)</p>
<p>So I hope start posting again here and on my vimeo channel like in the
good old days.</p>
<p>RnD, there I go!</p>Honda Oddysey2012-08-16T00:00:00+10:002012-08-16T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-08-16:/2012/08/honda-oddysey.html<div class="flex-video vimeo">
<iframe src="//player.vimeo.com/video/18025830?title=0&byline=0&portrait=0" width="900" height="608" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>I just found a TV commercial in which I've worked long time ago, I did
the generic character rig and the jellyfishes.</p>
<p>It was a remote work for <a href="http://www.gizmosite.tv/">Gizmo</a>, good job guys!</p><div class="flex-video vimeo">
<iframe src="//player.vimeo.com/video/18025830?title=0&byline=0&portrait=0" width="900" height="608" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>I just found a TV commercial in which I've worked long time ago, I did
the generic character rig and the jellyfishes.</p>
<p>It was a remote work for <a href="http://www.gizmosite.tv/">Gizmo</a>, good job guys!</p>Closing cycles2012-06-20T00:00:00+10:002012-06-20T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2012-06-20:/2012/06/closing-cycles.html<p>Hi folks,</p>
<p>Long time without any update, sorry about that :-(</p>
<p>As you may know i was working on <a href="http://www.kandorgraphics.com/en/justin-and-knights-of-valour/">Kandor's next feature film</a>... and
yes, 'I was working' because I decided to take a break on my carrer, at
least for a few months, and try to find myself again.</p>
<p>In …</p><p>Hi folks,</p>
<p>Long time without any update, sorry about that :-(</p>
<p>As you may know i was working on <a href="http://www.kandorgraphics.com/en/justin-and-knights-of-valour/">Kandor's next feature film</a>... and
yes, 'I was working' because I decided to take a break on my carrer, at
least for a few months, and try to find myself again.</p>
<p>In the last years I learn a lot as rigging supervisor, my role changed
from be working on technical stuff to work with people's motivations and
manage crisis on a production environment... the downside is I'm not
sure if be 'a manager' is what makes me happy. I really miss the old
days being the 'smart guy', looking for clever solutions to some rigging
related thing or whatever... I don't know, lately I wasn't having fun
with my job anymore and I felt lost.</p>
<p>Anyway... it's too early to make any conclusions, the only thing sure is
that the last 3-4 years at <a href="http://www.kandorgraphics.com/en/">Kandor</a> have been awesome and I'm really
thankful to everyone for that!</p>
<p>I'll miss you guys :-)</p>
<p>Plans for the future?</p>
<p>I don't know, right now I just wanna rest and take some time to think
about all this... maybe in the next entry.</p>
<p>Cheers!</p>RollUp Prototype2012-02-13T00:00:00+11:002012-02-13T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-02-13:/2012/02/rollup-prototype.html<p><img alt="rollup prototype" src="https://www.cesarsaez.me/images/rollup_ICE.png" title="Rollup prototype"></p>
<p>Gotta love ICE!</p>
<p>It's so fast/easy prototype a custom deformer (or whatever)
in it, it's so powerfull... I think just because of that Softimage is one of
the best 3D softwares in the market... a true life saver.</p>
<p>I can't wait to start working on the rigging framework/pipeline …</p><p><img alt="rollup prototype" src="https://www.cesarsaez.me/images/rollup_ICE.png" title="Rollup prototype"></p>
<p>Gotta love ICE!</p>
<p>It's so fast/easy prototype a custom deformer (or whatever)
in it, it's so powerfull... I think just because of that Softimage is one of
the best 3D softwares in the market... a true life saver.</p>
<p>I can't wait to start working on the rigging framework/pipeline for our
next project at Kandor Graphics, ICE Kinematics will be our rock star for sure! :)</p>When was the last time...2012-02-06T00:00:00+11:002012-02-06T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-02-06:/2012/02/when-was-the-last-time.html<p>Last week we had a very interesting talk on this issue. Seems like when
you're working on a project for so long, sometimes it's easy to feel
lost and this question comes to the surface quite often...</p>
<h3>So, when was the last time you felt proud of your work?</h3>
<p>At …</p><p>Last week we had a very interesting talk on this issue. Seems like when
you're working on a project for so long, sometimes it's easy to feel
lost and this question comes to the surface quite often...</p>
<h3>So, when was the last time you felt proud of your work?</h3>
<p>At the end, we all agreed it's all about <em>'can't see the forest for the
trees'.</em></p>
<p>You have to get out of the forest to see it, because while you are in
the forest, you only see the trees that comprise it; but you can't see
the forest as a whole.</p>
<p>Yes, I know what are you thinking... really basic, right?</p>
<p>And I agree with you, but sometimes is good to know we're not alone and
if we continue doing our best, tomorrow we'll be proud of today's work
:-)</p>
<p>Cheers!</p>Rigging lecture at UGR2012-01-29T00:00:00+11:002012-01-29T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2012-01-29:/2012/01/rigging-lecture-ugr.html<p>Hey folks,</p>
<p>The last weekend I gave a <a href="http://www.masterkandor.com/">lecture on rigging at UGR (Granada University)</a>, it was a nice
experience although prepare the program and class material was not as easy as I thought, but in the
end everything went fine and everyone learned something new :)</p>
<p>You can grab the …</p><p>Hey folks,</p>
<p>The last weekend I gave a <a href="http://www.masterkandor.com/">lecture on rigging at UGR (Granada University)</a>, it was a nice
experience although prepare the program and class material was not as easy as I thought, but in the
end everything went fine and everyone learned something new :)</p>
<p>You can grab the slides <a href="https://speakerdeck.com/csaez/intro-rigging-1-spanish">here</a> and
<a href="https://speakerdeck.com/csaez/intro-rigging-2-spanish">here</a> (spanish only).</p>
<p>In other news, I've been really busy at Kandor lately (crunch time) and finding time/energy to do
CG related projects on my spare time is getting harder than ever... but I'm trying and maybe this
week I finally finish/release a little tool for Softimage I've been working on.</p>
<p>Nobody said this was going to be easy, right?</p>
<p>Cheers!</p>OneUndo decorator2011-11-03T00:00:00+11:002011-11-03T00:00:00+11:00Cesar Saeztag:www.cesarsaez.me,2011-11-03:/2011/11/oneundo-decorator.html<p>Hi folks,</p>
<p>I'm posting another entry from my old blog, this time it's a decorator
for Softimage that help us to wrap all the calls inside a function in an
unique undo.</p>
<p>The decorator itself should look something like this...</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">wraps</span>
<span class="k">def</span> <span class="nf">OneUndo</span><span class="p">(</span><span class="n">function</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">function</span><span class="p">)</span>
<span class="k">def …</span></pre></div><p>Hi folks,</p>
<p>I'm posting another entry from my old blog, this time it's a decorator
for Softimage that help us to wrap all the calls inside a function in an
unique undo.</p>
<p>The decorator itself should look something like this...</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">wraps</span>
<span class="k">def</span> <span class="nf">OneUndo</span><span class="p">(</span><span class="n">function</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">function</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_decorated</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">Application</span><span class="o">.</span><span class="n">BeginUndo</span><span class="p">()</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">Application</span><span class="o">.</span><span class="n">EndUndo</span><span class="p">()</span>
<span class="k">return</span> <span class="n">f</span>
<span class="k">return</span> <span class="n">_decorated</span>
</pre></div>
<p>And a basic example...</p>
<div class="highlight"><pre><span></span>@OneUndo
def CreateNulls(size=100):
return [Application.ActiveSceneRoot.AddNull()
for i in range(size)]
CreateNulls()
</pre></div>
<p>Have Fun!</p>Demo Reel 20082011-10-01T00:00:00+10:002011-10-01T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2011-10-01:/2011/10/reel-2008.html<div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/2288568?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>My old demo reel ... there are some things I would do differently but this comes from the me of 2008 ;-)</p><div class="flex-video widescreen">
<iframe src="//player.vimeo.com/video/2288568?title=0&byline=0&portrait=0" width="900" height="506" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<p>My old demo reel ... there are some things I would do differently but this comes from the me of 2008 ;-)</p>Me and myself2011-09-30T00:00:00+10:002011-09-30T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2011-09-30:/2011/09/me-and-myself.html<p>Me me me... and myself.</p>
<p>Just kidding.... I'm rescuing old posts (you know, restarting the site once again) and I found this interview from the guys at <a href="http://www.eje-zeta.com">eje-zeta</a> in which I talked about my experience as self-taught CG artist.</p>
<p>By the way, spanish only...</p>
<p><a href="http://www.eje-zeta.com/2010/03/17/entrevista-con-cesar-saez-de-kandorgraphics">LINK</a></p><p>Me me me... and myself.</p>
<p>Just kidding.... I'm rescuing old posts (you know, restarting the site once again) and I found this interview from the guys at <a href="http://www.eje-zeta.com">eje-zeta</a> in which I talked about my experience as self-taught CG artist.</p>
<p>By the way, spanish only...</p>
<p><a href="http://www.eje-zeta.com/2010/03/17/entrevista-con-cesar-saez-de-kandorgraphics">LINK</a></p>Blog hacked again...2010-09-29T00:00:00+10:002010-09-29T00:00:00+10:00Cesar Saeztag:www.cesarsaez.me,2010-09-29:/2010/09/blog-hacked.html<p>Yes, it happened again and I still don't get it :(</p>
<p>It doesn't matter... all I can say is that I'm going back to Blogger for the safety of my post, right now I'm not so motivated to write my thoughts anywhere but who knows, maybe things will change...</p>
<p>Cheers!</p><p>Yes, it happened again and I still don't get it :(</p>
<p>It doesn't matter... all I can say is that I'm going back to Blogger for the safety of my post, right now I'm not so motivated to write my thoughts anywhere but who knows, maybe things will change...</p>
<p>Cheers!</p>