Stuff by other people

I fixed a bug in Blender!

Summary: I found a bug in one of Blender’s Grease Pencil modifiers. In the process of prepping The Best Bug Report Ever, I fixed the bug instead with help and encouragement from Grease Pencil’s module owners. Read on if you’re interested in how Grease Pencil makes its lines thick and thin, how Grease Pencil’s Thickness modifier does the thing, and how my fix works (in Plain English). Big thanks to Antonio Vazquez and Mathias Mendiola for their patience, encouragement and guidance!

I wanted to test Blender’s Grease Pencil system out as an inking tool, because it allows me to go back and edit my lines a bit after I’ve drawn them. If a line is a bit wobbly or it doesn’t curve nicely or the width doesn’t taper properly, I can sculpt it and fix it after I put the line down, even going point by point if need be.

It was while I was wrestling with ways to adjust particularly lumpy stroke width with the Thickness modifier that I discovered a bug.

The bug and its habitat

The Thickness modifier for Blender’s Grease Pencil adjusts the thickness of Grease Pencil strokes. The Thickness modifier has a Normalize mode which sets the entire stroke to an even width.

Under the hood, “thickness” is a property of the strokes themselves. The strokes are made up of a series of points, and each point has a “pressure” value – the pressure of the graphics tablet for that point. Stroke thickness times point pressure determines the width of the stroke at that point.

Normalize works by setting the thickness for the stroke to whatever the modifier says it should be, then it sets the pressure for all its points to 1.0 – exactly the same pressure on each point means the width of the line becomes even. You can select a particular Vertex Group or Grease Pencil Layer in Normalize mode to target particular strokes and points for evening up while leaving the rest alone… or at least, that’s how it should have worked.

The bug was that the modifier was changing the width of all the strokes whether they had points in that vertex group or not. The effects of a modifier are not meant to leak like that.

I found Grease Pencil expert user Mathias Mendiola on blender.chat – he created the Grease Pencil Fundamentals course on Blender Cloud. He asked me to report a bug.

The best bug report ever

Now, reporting a bug to a fellow developer is not something I take lightly and I wanted to do it properly as a courtesy.

A good bug report should do the following:

  • reports a bug which hasn’t already been reported (let alone fixed), saving coders more administrative work
  • describes the problem clearly, concisely and precisely (less room for misinterpretation)
  • describes the environment and context the problem occurs in (which version of the software, e.g. stable or build hash on splash screen; which operating system, CPU and graphics card, etc)
  • describes expectations of what should happen (maybe the user’s expectations are not what developers expect them to be)
  • gives explicit instructions on how to replicate the bug with as few steps as possible, or alternatively provides data which shows the bug occurring

That last bit – how to replicate the bug – is super important. If the coder can’t replicate the bug, it’s much more difficult to fix it. If the coder is obliged to fix the bug anyway, they may have to spend a significant amount of time devising their own replication which may or may not be the same as what the user does when they trigger the bug, and even if it’s the same thing the user is doing it’s still time the coder has to spend pinpointing the source of the bug. Reproducing information which a user already knows (but hasn’t passed on) is not a good use of a coder’s time.

Since I’m a programmer myself and I build Blender from source, I wanted my bug report to go further than just instructions on how to replicate the bug – although I’d do that too. Once a coder confirms the bug is there and accepts it, the next step involves finding the bit of code that’s going wrong. I decided to find that bit of code as an exercise and to be extra helpful – one less thing for the coder to do.

Tracking down the bug

I poked around Visual Studio and eventually found the code inside source/blender/bf_gpencil_modifiers/MOD_gpencilthick.c. The function which contains the procedure for the Thickness modifier to modify thickness is called deformStroke.

By now, I wanted to pry even further and figure out what deformStroke was doing wrong so that I could even quote a particular line number in the bug report – again, one less thing for the coder to do. After hours of squinting, I figured out that even with Vertex Groups switched on, deformStroke was changing the thickness of the strokes whether they had points in the vertex group or not. That was fine if the whole stroke was getting normalised, but not if the stroke had some but not all points in the vertex group, or no points at all.. hmm..

Since I was on holidays and had no obligation to be awake and ready for work the next day, and I had Visual Studio open anyway, I decided to have a crack at fixing it myself – without any expectations of success or failure. If I couldn’t fix it, at least I put what I’d already tried in the bug report. Yet again, one less thing for the coder to do.

Failing to report the bug

After a few more hours of tinkering, headscratching, reading code, compiling, swearing and recompiling, I didn’t have a bug report – I had a fix for the bug. It was only a partial fix – for cases where a stroke has a mixture of affected and unaffected points, my original patch left that stroke alone – but in Normalize mode, the modifier had stopped affecting points and strokes outside the Vertex Group and that’s what I wanted it to do.

The fix

My change was to make the function scan over each point in the stroke. When it finds a point within the vertex group, it changes a variable called gps_has_affected_points from FALSE to TRUE. (gps stands for “Grease Pencil stroke”.) When it finds a point outside the vertex group, it sets another variable called gps_has_unaffected_points from FALSE to TRUE. Once both of these are set to TRUE, it stops scanning – neither of them can go back to being false.

What comes next depends on whether one or both of those variables are TRUE or FALSE.

If the stroke doesn’t have any unaffected points (
gps_has_affected_points is TRUE and
gps_has_unaffected_points remains FALSE), it’s safe to normalise the stroke by changing its the width and set all the points to 1.0. If it had both affected and unaffected points (both variables TRUE), originally I skipped handling it. (I tried to experimentally iterate a formula but then gave up and coded around it.) I left the code factored in such a way so that if need be, someone who knew the Grease Pencil system better than me could add the unhandled case in with the right maths. Something an expert coder could do in a second, probably.

I submitted patch D5483 at developer.blender.org at around 2:00am my time. Then I went to bed.

Getting the fix accepted

Now, submitting a patch doesn’t mean there was nothing for the coders to do, only that they had a code submission which fixes a bug. But was it readable code? Was it efficient code? Did it follow the appropriate formatting standards? Did the code change cover everything it needed to cover without introducing any regressions? For a module owner to accept code, it means they accept responsibility for what the code does and how it does it.

The next day, Grease Pencil module owner Antonio Vazquez had reviewed my patch. He thanked me for the code and encouraged me to handle the partially affected stroke case. I agreed it shouldn’t be left half done and did not make excuses that I was too tired to want to finish it all in one hit, and that it would be better for users if it didn’t just ignore certain cases (which were too hard for me to work out at two o’clock in the morning).

I spent a couple of extra hours on Friday reading other bits of Grease Pencil code to figure out the maths to convert stroke thickness to point pressure given a particular stroke thickness. After having no luck tracing through the code with Visual Studio for an answer, I did a brute force text search for where “thickness” and “pressure” occurred on the same line. It turned out to be simple algebra – target stroke thickness (from the modifier) divided by current stroke thickness results in the right pressure value.

Easy maths, right? Kind of.

Fun with numbers, C style

I knew enough about C to know it’s quite particular about the way it represents particular kinds of number. For instance, point pressure is a floating point (fractional) number and stroke thickness is an integer (whole number). If you divide two integers in C, you don’t get the remainder back. So if you want the remainder (which I did), you need to cast (convert) the integers to a floating point number instead. Then you can divide them to get a point pressure. (This converting may seem like a massive pain in the arse, and friendlier higher-level languages are happy to do those conversions under the hood, but the trade-off is that C runs at speeds which leave higher-level languages in the dust by comparison.)

I got the partial stroke normalisation case working on Friday evening and submitted an updated patch.

Antonio’s follow-up review on Saturday noted that Blender doesn’t do same-line comments, but that he was OK with the code of the patch. He added an extra line to clamp the width to a safe minimum – something an expert coder would know to do – and committed my updated patch to Blender’s master branch as a bugfix on Saturday.

My first Blender commit

The commit hash for my fix is a477c2e0e079 and I’m listed as the contributor. It’s not the first commit I’ve been named in (I helped fix a build bug a little while ago) but it’s the first commit where I’ve written actual code to fix something and been identified as a contributor. Yay!

Fixing that bug took me about six and a half hours, give or take. Much of that time was spent reading through unfamiliar code in a language I haven’t used before. And even if it was a small obscure bug, something very few people would notice or care about that much, it’s fun to see my name come up in Blender’s commit logs and nice to know I helped Blender work a little better than it did before.



I was a spider!

I recently did some voice acting work for animator Jeannot Landry (Blender Pirate). He wanted an Australian male voice for Roby, a cute peacock spider in his short “The Last Dance?”

In addition to voicing the character, I rewrote and extended Jeannot’s script to push the comedy some more and make the dialogue feel more authentically Aussie as requested. I was also a second set of eyes during animation blocking.

Hope you enjoy it! (A note to arachnophobes and people who are uneasy about spiders: Roby is a relatively naturalistic jumping spider in terms of the way he looks and moves. He also gets pretty close to the POV by the end of the movie. Hopefully the cute factor helps!)

Check out the Blender Pirate’s YouTube channel for more of Jeannot’s work!

Analysis: The Wacky Wabbit

https://www.youtube.com/watch?v=-Dl47PIP6h4
Embed broken? Click here.

Tonight’s short under the microscope was the Bugs and Elmer short The Wacky Wabbit, a 1942 cartoon (complete with war bonds ad) by Bob Clampett. I sat down and wrote out 291 short descriptions of what was going on on-screen at any given time, trying to summarise the cartoon from action to action.

What awes me is that the summary notes make me laugh. Even dissected on a table like a pinned rat, this material is still funny. Pretty amazing. I hope I can write something that funny one day.

Again, spoilers follow. Watch it first.

Plotwise, there’s not much to write about - Elmer is introduced as a gold-seeking, ill-tempered buffoon and Bugs is introduced as a cocky, nonchalant troublemaker. It should be noted that this is a Bob Clampett’s cartoon, so Bugs doesn’t need Elmer to cross him before he starts making mischief. Bob’s Bugs is happy to just entertain himself at the expense of fools. (Buckaroo Bunny is a more extreme example where Bugs is an actual outlaw.) You might also not recognise Elmer because they were trialling a different model of him.

So. The analysis.

Like Bad Luck Blackie yesterday, I spotted riffs in this. There’s a character riff set up early on with Elmer where he’ll see something, realise what it is, then respond - except very slowly. Sometimes between seeing and realising, he’ll act completely incongruously with how you’d expect someone to act under the circumstances, which makes the ensuing overreaction (either anger or terror) even funnier.

There’s also progressive escalation - Bugs starts out pretty cocky but he just gets sillier and sillier - by the end of the short he’s dancing and singing to himself, completely secure in the knowledge he’s got Elmer licked - until, in a twist of events, he hasn’t. Elmer’s stupidity by contrast stays about constant.

Bad Luck Blackie more or less winds up its premise and sets it going at a rapid-fire pace; Wacky Wabbit works with longer cycles of set-ups, anticipations and pay-offs. It’s more patient. It milks the audience’s anticipation much more because its main comedy hook is a dim-witted character, and dimwits by their nature take their time to pay off. There is another instance of a rhythm being established, then being played over and over again, faster and faster, until it stops midway through - only to be concluded after a pause. (That would be the scene with the dynamite, where Bugs himself supplies the BLAM noise.)

Elmer is sublimely stupid in this short. He politely greets a talking skull as he walks past. He sings a duet with Bugs without realising it until Bugs showboats one last time before disappearing. He braces himself against a spiny cactus while waiting for dynamite to go off. He rips out his own gold tooth at the end of the short and considers his quest for gold a rousing success.

Aside from the characters’ own personalities, the comedy in the short plays off subverted expectations (dynamite goes pffrt), exaggeration (Elmer and Bugs doing gravity-defying wild takes), misplacedness (witness the electric elevator that brings Bugs to the surface), unexpected symmetry (Elmer dives into the ground and Bugs is pushed up out of it), allegory (Elmer diving into a rabbit hole like a swimming pool), sudden surprises (Bugs suddenly snogging Elmer out of nowhere), sarcasm (Bugs says to the audience about Elmer: “Smart boy!”) and general contrariness/absurdity (while holding a stick of dynamite that’s about to go off, Bugs puts a finger in the ear furthest from the hand holding the dynamite). Elmer gets humiliated with kissing, having his clothes cut off at a vulnerable moment, being wolf whistled at and other unkind behaviour from Bugs.

It’s got me thinking mostly about what it is that allows a character to be so productively funny. WIth Elmer in this short, his slowness to catch on finds itself in the presence of someone who has no trouble outwitting him. Part of this comes from Elmer’s own personal character riff.

Bugs didn’t seem to have a riff in the analysis - Bugs feels more like a reagent. Some have referred to him as a mischievous pixie. That description seems to work here - at least until he gets the crap beaten out of him. Pixies don’t cop that sort of abuse usually.

Bugs still prevails in the end after all hope seems lost for him, so I guess that makes this a weird cartoon which kind of starts with Elmer and finishes with Bugs - Elmer becomes too aggro to fit the role of the protagonist. In one possible reading, the antagonist and protagonist roles almost switch midway through the story.

Warner Brothers animation fans will know that Elmer’s stupidify became so vexing for Friz Freleng that Yosemite Sam was born to give Bugs a bit more of a challenge - and fair enough too.

Anyway. It’s interesting to see comedic principles at play in different ways between different directors. I’m looking forward to doing more analyses and I hope someone out there is getting something out of them, even though I don’t claim for a second to really know much about what I’m talking about.

Analysis: Bad Luck Blackie

Editor's note: Bad Luck Blackie has evidently disappeared from the interwebs. So. Bad Luck Blackie. Directed by Tex Avery at MGM in 1949. Voted the fifteenth greatest cartoon of all time. Inspired by the advice of Bob Camp, I sat down to analyse how it works as a series of events by writing down what happens and when - even down to the individual frame numbers when the gags get really intense during the final payoff. It took half a day but it was totally worth it. If you haven’t seen Bad Luck Blackie before and you have seven minutes, watch it before reading on. This analysis may spoil some of the gags. Bad Luck Blackie works with “event riffs” (events happening in a particular sequence) mixed in with both subversion of expectations (both of reality and in the riffs) and ever-escalating gags. The riff in the opening sequence is pretty simple - cat gets away from dog, dog outwits and cruelly humiliates cat (eating him, letting him fall onto the floor, trapping his tongue in a mouse trap, squishing him into a book). This riff isn’t really broken until the cat escapes from the dog. As the riff plays out, we learn that this is a cartoon world (major subversion of normality where the cat runs over the tongue staircase from dog to.. er.. dog), the dog is a horrible cruel simpering bastard, and the little cat is defenceless. We get four repetitions of this sequence of events, plus a fifth aborted one when the cat escapes. The riff in the middle sequences starts off as “Blackie walks in front of the dog, something hits the dog on the head” - this causality is even verbally explained by Blackie himself. “Just whistle,” he says, adding another element to the front: whistle, Blackie, wham. This then becomes the slightly longer “dog accosts cat, cat sees dog, cat blows alert whistle, Blackie crosses the dog’s path, something hits the dog on the head, cat escapes”. A fragile normality is established - the whistle and hence Blackie keep the cat safe from the dog. (Naturally one wonders what happens if the cat loses the whistle - of course he loses it.) What hits the dog on the head gets more and more absurd and unlikely (flowerpots - believable because they’re near a building; a trunk - not quite as believable; a piano - now you’re being silly; a bomb; a cash register; a horseshoe.. followed by three more horseshoes and a horse). The ways in which Blackie crosses the dog’s path become more absurd and unlikely (appearing from a nook, appearing from behind a barrel, appearing from a tiny tin can and disappearing into another; floating by on a balloon, appearing out of a drainpipe - on a unicycle.) The sight gags for Blackie’s appearance and the dog’s comeuppance escalate into lunacy and subvert everyone’s expectations - especially the dog’s. There’s secondary associative gags at the end of a couple of the riffs as well: the dog gets hit with a piano, its teeth turn into keys which the cat plays; the dog gets hit with a cash register, the cat escapes its mouth from a cash drawer; the dog accidentally clobbers itself with a single horseshoe, only for three other horseshoes and an entire horse to clobber him immediately afterwards. Another note is soon added to a variation on second riff after a fade to black - cat is wandering along happily, cat sees dog, cat blows whistle, Blackie crosses the dog’s path, dog gets clobbered. But the dog is starting to get wise. The riff gets altered by the dog clamping a hand over the cat’s mouth, stopping the cat from blowing the whistle - until a fly ruins everything. Whistle blown, Blackie trots into shot, fire hydrant drops on dog’s head. Next, the riff appears to start again with the cat wandering along happily, but a jack-in-the-box derails it. The whistle is dropped (as anticipated earlier) and the dog steals it, thinking he’s outsmarted the cat and Blackie. A part of the riff is now under the control of the villainous dog who wants his revenge on Blackie. It’s as if the riff has gone from major to diminished - what happens now that the villain has control of one of the very elements of the riff? If he blows the whistle, will Blackie still appear? Expectations all around would indicate yes. Accordingly, the dog hoists a safe up on a rope, draws an X on the ground where the safe will drop, then blows the whistle. Blackie appears, sees what’s going on, nonchalantly kicks the X across to underneath the dog and about a second later the dog cops his own safe. This establishes a shorter variation of the riff - “dog gets ready to take down Blackie, dog blows whistle, Blackie appears, something falls on the dog”. So even when you think the riff can’t happen, through a surprising gag it finds a way. This riff variant is repeated - dog gets ready to hit Blackie with a plank of wood, dog blows whistle, Blackie appears (walking across a plank upside-down with suckers on his feet), dog is hit with a ton of nearby bricks. The new variant is played one last time - the third time. Comedy comes in threes, they say. This time, as Blackie appears the dog paints him white. Blackie’s crossing has no effect. We suspect that the cat has to be black for the bad luck to actually work. Blackie runs back and forth in front of the dog to summon the next event in the sequence, but the riff is broken.. …until the little cat leaps into some black paint, walks in front of the dog and finishes the riff we all know. The dog passes out briefly and swallows the whistle. And so we come to the final comedic riff of the short, a Blackie-less variation on the middle riff: the dog hiccups, the whistle inside him blows, something falls on his head. After a couple of blows to the head, the dog gets wise and the last event changes to something narrowly missing him - though frame by frame suggests they draw it coming straight for him and he blips out of the way at the last possible frame. The fact that cats aren’t crossing his path breaks the rules of the world slightly, so presumably in order to distract us from this inconsistency the pace of the action speeds up. By now, we kind of expect unlikely stuff to fall out of the sky; the falling stuff escalates in absurdity and the intervals between hiccups and falling objects become shorter and shorter while the escalation gets completely absurd - a sink, a bathtub, a piano, a steamroller, an airplane, a bus and finally a battleship. It’s an accelerating crescendo of absurdity with the final event of the riff coming quicker and sillier until the villain runs off into the hills, vanquished. And it serves him right, too. After this there are no more riffs, just ten seconds of the characters shaking hands on a job well done and the small now black cat making evil faces as we iris out of the short. From doing this analysis I got a lesson in how audience and character expectations can be set up through establishing a pattern of events which then play out like a musical riff - except instead of notes, we have events. Sometimes it’s what we expect and sometimes it isn’t. The biggest turning points in the two initial characters’ respective fortunes came when the riff of events was waylaid by something getting in the way (an incinerator in the first instance, or white paint in the second). The mid-section of Rock-A-Bye Bear seems to work the same way - once the setup is established, for a couple of minutes we get a riff of “miscreant dog makes guard dog make a noise (usually by hurting him), guard dog rushes outside to make noise out of earshot of grouchy sleeping bear, guard dog dashes back inside”. Again, there’s escalation (from pin on chair to hammer on foot to dynamite on tongue) and the surprising subversion of expectations. (How can someone walk out of a house when their feet and hands are occupied? He finds a way.) But before that we also get a riff of “noise is made, bear comes out and shouts about it”. This is subverted utterly when the bear’s house explodes and he doesn’t wake up.. then it’s quickly unsubverted again when someone wolf-whistles at the Red pin-up. What makes it funny? Subverting expectations both in terms of established riffs and common sense, progressively escalating one or two events in already established riffs towards greater and greater absurdity.. and of course timing/staging/pacing it all so each event on the screen and soundtrack can be taken in clearly and unambiguously. In the end that’s a bit of a joyless dissection of comedic principles.. but hey, it still makes me laugh. Admittedly, this analysis has all been pretty writerly, but writing is the part I’m most interested in at the moment. Maybe the concentrated riffing is a Tex Avery trademark or maybe everyone riffs - I guess I’ll find out once I do a few more analyses. I’m keeping my cup of expectations empty for now.