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!

Japanese for sumo fans

Part of the reason I started learning Japanese again was because I started following Grand Sumo. New sumo fans are confronted with a lot of untranslated terminology which takes a good while to get up to speed on. After a scant ten months of sumo fandom, I can tell makushita (third division) from makunouchi (top division) and oshidashi (shovey-outy) from oshitaoshi (shovey-downy).

Is any of this Japanese terminology useful in the context of learning Japanese though? I wanted to know if common sumo terms like ashitori, tsukebito, oshidashi or shitatenage could give me a leg-up on my vocab and grammar. It turns out the answer is yes – if you break them up a bit and do your homework. This is what I hope to show you how to do.

The basics

If you’re completely new to Japanese, read on. If not, feel free to skip to the next section.

Japanese has a couple of gotchas we need to be aware of before we turn jargon into useful language. Fortunately it’s also an extremely regular language compared to English with all its exceptions.. well, regular except in the way it’s written. More on that later.

Sound groups

The sounds of Japanese group together a little bit differently than in English. Mostly it’s like ka-ki-ku-ke-ko or na-ni-nu-ne-no, but sometimes you get ta-chi-tsu-te-to, sa-shi-su-se-so or ha-hi-fu-he-ho. While we’d say that the sound at the beginning of “tea” and “turtle” are the same, the sounds at the beginning of “cheese” and “turtle” are different. In Japanese, they’re variations of the same sound. The same goes for “sap” and “sheep”. To spell a sound like at the beginning of “sharp” they smoosh “shi” together with “ya”.

Sound changes

The Japanese word for person is hito. When it’s compounded with certain words, it becomes -bito. This change happens all over and it’s the bane of every novice Japanese learner. The Japanese call it rendaku (“sequential voicing”). All you need to remember is that in some names and compound words, k becomes g (mae + kashira = maegashira), t becomes d, h becomes b (kin + hoshi = kinboshi), s becomes z (oo + seki = oozeki), ts can also become z (yoko + tsuna = yokozuna) and ch becomes j.

Kanji and kana

Japanese has three distinct writing systems on top of the ones you already know. (Japanese uses Roman letters like the ones you’re reading and Arabic numbers like 234.)

The two phonetic (what-you-write-is-what-it-sounds-like) writing systems are called kana, both with about 50 letters which each represent a phonetic unit called a mora (“syllable-but-not-quite”). There’s hiragana which is used for native words and katakana which is often used to spell out abstract noises and foreign words.

The two kana systems are pretty easy to tell apart. This is cursive round squishy hiragana: これがひらがな。This is angular sharp stabby katakana: アフリカパソコン。

Japanese also uses a complicated system of characters called kanji. There’s maybe about 50,000 kanji characters, but people are only expected to know a couple of thousand of them by the time they finish school. Kanji are relevant to learning Japanese with sumo because the names of the rikishi and stables are all spelt almost entirely using kanji.

Kanji are however slippery because they often sound different depending on which word they’re being used in. Even just looking in top division sumo, we can find the kanji 大, meaning “big” or “great”, realised as three different sounds: Chiyotairyu 千代大龍, Daieisho 大栄翔 and the rank of oozeki 大関. (Sidenote: Chiyotairyu’s name means “Eternal Great Dragon” and that’s pretty awesome.)

I mention the different kinds of writing because they have helpful clues.

Mining sumo jargon for verbs

Kimarite are sumo’s winning techniques. Each of them has a name like oshidashi, abisetaoshi, uwatenage, yorikiri and so on. Sumo fans learn the more common ones by heart.

Many of these terms are actually compound verbs in “stem” form. One giveaway for this is if you see kanji intermixed with kana: 押 (oshidashi), 浴 (abisetaoshi), 上手投 (uwatenage – one kana still counts) and 寄 (yorikiri). The other giveaway is the sound: notice how there’s a lot of something-y-something-y? That’s the telltale sound of Japan’s doing words having little word parties, that is.

How can we use this though? Japanese has two (and a bit) groups of verb. There’s Group I which has a stem form ending in -i, and Group II where the stem form might end in -e or -i. If you want to extract verbs from kimarite names, you can start by splitting them up where a -i or -e occurs. This might net you two verb stems. It might not. The two irregular verbs aren’t worth mentioning here.

To get a “plain form” verb which you can use in sentences and look up in dictionaries, you can change the final -i to an -u (remembering that -chi becomes -tsu and -shi becomes -su). For Group II verbs, you add -ru if the stem ends in -e. Some stems ending in -i are actually Group II which means having to add -ru to them. You can try one if you get no luck with the other.

And no matter what, you can take the stem form, whack -masu on the end and have a ready to go polite verb.

Let’s give it a whirl!

First, let’s try oshidashi. Split the word up to get oshi 押し and dashi 出し. Change from stem to plain form to get osu 押す and dasu 出す. Wouldn’t you know it: osu means “push” or “overwhelm” and dasu means “put out”. To overwhelm and put out.

Let’s see what we can do with 浴せ倒し – abisetaoshi! Split it up to get abise 浴せ and taoshi 倒し. Abise ends in -e which means it might be a Group II verb, so we add a whole -ru to the end and look for abiseru 浴せる. The other half taoshi becomes taosu 倒す. Again we’re in luck: abiseru means “pour something on” and taosu means “knock down”. Oh the words we already know.

Kimarite are not always verb stems, however. My absolute favourite kimarite is ashitori 足取り where one rikishi picks up the other rikishi’s leg and hops them out backwards. This looks like it’s spelled a bit different to the first two examples though. There’s no kana dividing the two characters. We can find toru 取る meaning “pick up”, but we won’t find asu because the word we’re after is actually ashi 足 meaning “leg” or “foot”. The lack of kana is the big clue there. (If we look for a verb like 足す we’ll find the word “to add”. And it’s pronounced tasu.)

There’s a similar thing waiting for us with uwatenage 上手投げ. Are we looking for uwateru and nageru? Not quite. Again, the relative lack of kana in the spelling is the clue here. While nageru 投げる definitely means “to throw” (also “to launch”), uwateru isn’t a word. Looking for just uwate turns up “over-arm grip”. When you see -te- 手 in the name of a kimarite, it often refers to an action of the arm or hand – te 手 means hand or arm. And the character 上 has the implication of above or over. Literally: over-arm throw.

Wait on, there’s a -te at the end of kimarite. And there’s a lot of kana in its Japanese spelling: 決まり手. So is kimaru a verb too? Yep! It means “to be decided” or “to be settled” – as in, settling a match. One of the many meanings of te is “technique”. Kimarite literally means “deciding technique”. Nice!

Finally, let’s look at yorikiri 寄り切り – the standard issue frontal force-out beloved of top division’s belt-focussed wrestlers. Using the methods above, we get yoru 寄る and kiru 切る. Yoru means “get up close” (among other things) and kiru means.. “cut”? Sort of. As the second part of a compound verb, kiru acts as an auxilliary verb. (English auxiliary verbs include ought and must along with go when it’s used in sentences like “go suck eggs”.) So instead of “cut”, kiru means “to finish and complete”. That means in the word yorikiri we have the notion of getting up close to someone with an implication that something is completed.. like shoving them out of a ring! 🙂

Of course, if you’re more of a foodie than a sumo fan, perhaps you’d prefer to break up words like teriyaki 照り焼き – you’ll soon discover teru 照る (to shine) and yaku 焼く (to barbecue) lurking within. It works for yakitori as well.

I hope you enjoyed this peek into vocabulary building and that I’ve inspired you to find out more. Thanks for reading and here’s to a great 2019 January Basho! (魁聖関、頑張れ!)


So that was 2018…

It’s 1 January 2019 as I write this, so Happy New Year!

At the changing of the years, I like to go back over the previous twelve months, and think about what I want do over the next year. I did a similar thing in 2017, and looking over it this sentence in particular struck me:

The day job may have other things to say about all of this, especially if I score the promotion I’ve been working towards and people keep departing, but we’ll see.


– me, 12 months ago

The day (and often late night) job

I got the promotion. Yay! But the other thing happened too. Boy did it ever.

Before the year’s end, all but one other person in my team of six (not counting the new hire) had been poached by another (much better paying) company across town. Two levels of management above my team had already gone the same way, and one of those managers had taken over from another poached manager. My team in particular has domain knowledge the poachy company wants and so every single one of us was approached, me included. Only one of us flat turned them down.

When they approached me, I said “not yet”. At the time I didn’t want that kind of distraction hanging over a big unfinished project when it was so very close to done.

The project’s done now. It’s an enterprise search system. People tell me it works better than Google’s did.

This year’s big project

A search engine is sort of a specialised database. You feed documents into it to create an index, then you run queries on the index to retrieve information. The way it retrieves that information is calculating lots of points in N-dimensional space representing its documents, then figuring out how close those points are to the point which represents the thing you asked for. A well-configured search engine also transforms its index and query data to allow for more intuitive results. (If you search for cat you probably want cats as well. If you search for qoull, of course you meant to type quoll.) There’s quite a lot of domain knowledge involved in information retrieval but that’s honestly a series of blog posts all on its own.

The company’s Google enterprise search hardware was due to go out of licence in July, after which it would stop working. I couldn’t spend any actual money buying a replacement, but I had to come up with something all the same.

After months of working almost entirely solo, I put together a search service based on the open source search engine Apache Solr and it’s been received extremely well. Maybe it’s because the interface also shows a cat emoji if someone’s search contains the word “cat”. Or possibly because it authenticates people invisibly and actually finds things, something the Google one had no end of trouble with.

I’m really proud of what I achieved with it, but my creative momentum and mental health definitely suffered. That’s why I mention it.

Meanwhile, in Blender…

If there’s been an overarching theme to this year creatively, it’s been stepping back from big complicated things and working simpler and smaller.

…the Sun shines brightly!

This year AMITS stopped being the focal point for my creativity. I’m no longer under any illusion that it’s possible to learn animation from the context of making an animated movie. Animation is way too complicated to figure out as I go along, and I haven’t got enough practical experience to build on. Fair enough, though: I didn’t know what I didn’t know.

As a result, “A moment in the sun” was mostly back-burnered, although it continued to simmer. Then suddenly in October, there came a burst of inspiration: a story rewrite, a scratch audio track, thumbnail sketches and a story reel! Gosh! It’s now in its best ever state story-wise – short (90 seconds), dense, unambitious, silly and fun. All I had to do was stop working on it entirely for a few months and it came good. Yay.

I’m not holding myself to a deadline or a schedule on AMITS anymore. I want to work on it as time and energy allow – a proper crafty hobby project.

Little things (for the fun of it)

I wanted to become more confident and competent with animating anyway, so back in February, I started some self-paced courses in animation over at CG Cookie. I’m a long way from where I was a year ago, although I still have a long way to go again before I’m where I want to be. I know much more of what I don’t know.

My main blocker has been learning to use reference effectively. Stepping back from animation and understanding how I use reference in general has helped there too. In short, I let the reference dictate its own ideas instead of using it to inform my own ideas. It’s something I want to work on.

Beyond finally knocking half a dozen animation exercises over, I want to do more “little things for the fun of it” in 2019. I want to do more work on visible things which I can share instead of being stuck doing invisible things for months on end.

Keyframe Tools

Friendly animator Looch badgered me into porting a couple of tools from his favourite Maya plugin animBot into Blender 2.79. This became the Keyframe Tools add-on. The tools are functional right now but neither numerous nor super-polished. It’s still in a state of “feel free to use it but don’t expect much” (pre-alpha).

I want to get it working in 2.80 but beyond that, I have no big plans. I have more than enough software to support at my day job to want to support software outside of my day job, and Blender’s API for F-Curves is still too messy to want to deal with in my spare time.

Other things

Whatever happened to the synthesiser… ?

The interest in Eurorack petered out in 2018. The last thing I bought was the mighty Intellijel Metropolis stage sequencer – a reward after completing a release milestone for the search service.

I’m happy to report I haven’t spent a cent on any new music gear since August. (Yay. I’m cured.)

I recorded some nice whooshing noises from the modular all the same and put them up on Bandcamp. I also re-released an old album of loud ambient music called Music for Open Plan Offices. I haven’t had much use for it at the day job since everyone quit.

Writing novels

I don’t really talk about my writing much either, except in the context of “I’m writing to procrastinate animation”. But since this is a recap of the year, this is what I wrote.

I got through writing most of a first draft of a novel in February. It was about a cut-throat society of vermin living in a sort of midway universe between Mundane Reality and Deep Magic, and the chaos that ensues when someone indefatigably pleasant finds their way into a scheming nest of bastards who all want him for themselves. I put it down because it was too complicated to work out the middle and I didn’t like it enough to go to the effort of finishing it.

Before the cholecystectomy in late October, I decided to bust out a novel NaNoWriMo-style for the hell of it. Two weeks and 63,000 odd words later, I’d drafted a story about a gifted magical being more concerned with lording his talents over the easily impressed than doing anything useful. This arrogance winds up getting him exiled into the human world where he has to fit in for a whole month or face a terrifying forfeit. It’s a sweet little story with some fun characters.

I mention these only to see if anyone will ask about reading them.

Japanese

I started learning Chinese in November 2017 when Duolingo released their Chinese course, but this year Japanese was coming up a lot more in my day-to-day life (following sumo, mainly). I don’t have much use for Chinese other than saying dissidenty-type things at my Chinese-made mobile phone.

Recently I’ve kicked it up a notch and got into spaced repetition systems to boost my vocab and grammar. It’s intense but it’s definitely delivering results. I feel it turning into one of those things where the challenge, frustration and reward make it fantastically addictive – except instead of having spent loads of cash and time with electronics, I spend less cash overall and understand a whole other language. Bonus!

The future of the blog

I started keeping this journal back in 2012 on Tumblr. Back when AMITS was really roaring along, I posted something every weekend as a show and tell. The idea was to represent the passing of time as the project got made so that when someone goes back and reads it, they get a sense for the tempo of the project.

AMITS’s tempo subsequently dropped and the weekly updates became monthly. I got interested in other things again and the monthly recaps got much less focussed on animation.

My engagement levels from here are pretty close to zero as well. I would love to say that I’m not fussed about engagement but even I’m at the point now where I want to re-think what purpose this blog even serves. Regular posts feel more out of habit than for having something interesting to say.

I’m going to just get on with my 2019 and if Something Happens, I’ll make a concerted effort to be interesting about it. Very possibly I’ll blog about Japanese.

For now, that’s it. Have a great 2019!

December 2018 retro

December 2018! Western quolls at the Arid Recovery desert site appear to be doing well, and (as feared) all but one of the team-mates at work has resigned. Also I have a new-fangled block-based editor to play with for this blog. Gosh.

The sun and moments therein

I finished a cut of the AMITS: Hello! story reel at the beginning of the month. It’s just shy of 90 seconds which is a nice compact running time. And here it is! (Spoiler warning, obviously.)

After literally years of struggling to write a story with these two characters, this story reel is a quietly magnificent relief.

I modelled and rigged the Hellobot in the Blender 2.80 beta. It’s a simple rounded cylinder, with the eyes rigged to change colour and shape. It should be more than enough to get me through layout. Here is a short demo. (Very slight spoiler warning.)

There are now eight assets left to build, including scenery, a few props and two characters. Producing AMITS to any kind of deadline or schedule is completely unthinkable at the moment, unfortunately.

Blender 2.80 beta is coming along nicely but I haven’t made any updates to Keyframe Tools just yet. Hopefully the API to access keyframe data is not as convoluted as it is in the 2.7x series.

今日は、日本語!

This month mainly I’ve mainly been studying Japanese. Or should I say Kongetsu ni watashi wa omoni nihongo wo benkyou shite-ita. Or should I say 今月に私は主に日本語を勉強しいた。I can do that now. 今は出来るよ。OK, I’ll stop.

I’ve shifted gear from five minutes a day farting around on Duolingo to at least an hour a day learning Japanese characters, vocabulary and grammar. It’s really worth a blog post of its own. IOU!

That’s about it for December. I’ve got a yearly recap blog pencilled in for New Year’s Day or thereabouts, so expect that soon!