Saturday, December 31, 2011

Facade and Edifice - Visual Language

Given the recent present-buying season, it seems appropriate to wrap up 2011 with some reflection on brand and marketing. This may be a slight departure from our usual tech-art speak, but it's related to design (yay design!) and fits the bill for horizon-broadening homework.

The above image is of a Tivoli Audio radio. We'll come back to it a bit later.

I love marketing. It's some fantastic stuff. Through the right techniques, an ad can switch your interaction with a product from a logical analysis to a deeply emotional response. The most common way this happens is through association of a product with a lifestyle or social status.  already discussed this subject at length. The tone of said article, however, annoyed me a bit. It seems to suggest, "isn't it pathetic that people fall for this" and "aren't these social constructs sickening?" Primarily the author underlines the flimsiness of the thought process that might lead a reader of the Economist to buy a $100,000 Patek Philippe watch. Yes, such a decision is likely irresponsible for most readers. The assertion, however, implies something interesting about the actual value of said watch, namely that brand doesn't actually add any. But what is value?

Today I went to the Natick Collection with my parents, an upscale mall roughly 40 minutes outside of Boston. While browsing, I found myself inexorably drawn to a Tivoli store containing the product pictured above. I was not drawn to this radio because of the quality of the sound (I had not yet heard it), nor was I drawn to it due to my pressing need for a new radio (Millennials need radios like snakes need socks). I was drawn to this store because the product suggests ironic appreciation of retro-trappings and elegant design. It wasn't the product, but everything else in our culture the product suggests that I wanted to buy. Retro suggests a quirkiness, a certain against-the-grain attitude that hipster meccas like Urban Outfitters have been cashing in on in a major way. Even recognizing that this is the case, I am happy to lean into this perceived image for one reason: others will make the same cognitive leap. It isn't merely a perceived value in my head, but a social trope that will illicit similar reactions in anyone who is similarly suspended in young American culture.

To wheel around back to my thesis, buying a product because its image and associations change how people interact with it isn't imagined value, it's actual and important value. It's value tangible enough that companies spend the majority of their revenue to obtain said value. It's the same sort of value that makes film,  game, and advertising actual art. It's the thing that determines the success or failure of any artistic or commercial venture: context.

Edit: I have to add an awesome bit of copy that I just found. Since looking at Tivoli, wooden clock ads are coming my way. This one from Areaware is great:
"Remember those faux wood grain GE flip clocks that sat on every bedside table just a couple of decades ago? The Alarm Dock uses a nostalgic product language to meet the progressively thin and disappearing profiles of consumer electronics. It is at once a critique and an accommodation to new technology. Place an iPhone or iPod Touch running a flip clock app onto the dock, and see an iconic and meaningful form return to your nightstand, mantel, or shelf."

Remember a couple decades ago? Do you love "nostalgic product language?" How about finding "iconic and meaningful form" for your nightstand, mantel or shelf? Dang, these guys are good.

Sunday, December 11, 2011

Onward and Awkward

Happy Holidays! Though belated, I hope everyone had an enjoyable Thanksgiving.

I've gone through a few goodbyes recently that I wasn't expecting nor prepared for. Comings and goings, however, are by their nature subjective. No story has truly ended to all of the players. Ultimately, I have confidence that everyone involved will go on and continue to do great things. Doors close, windows open, and those with wisdom find the way forward. As Einstein said, "in the middle of difficulty lies opportunity."

I used much of this past holiday to reset. I've never been one to sit idly for too long, however, so resetting has given way to new projects. I'm practicing C++ with a calendar program (good regex practice), painting some 40K minis on commission (slowly), and catching up on some C.G. Jung. Joseph Campbell was my introduction to Jung, so it's only fitting that he edited the collection I've chosen to review: The Portable Jung. Any fiction writer would benefit from this book. The insights into the human experience, the resonance of childhood, the shared symbols of mythology, feel strikingly true and powerful. Once I finish with Jung, I plan to move on to Marie-Louise Von Franz's The Interpretation of Fairy Tales. Yeah. We're gonna get all archetypal up-ins.

At work, I've been thinking about the problem of balancing planning versus implementation. I'm a big fan of "failing fast:" don't worry if your solution is optimal. Implement, see where you erred, then correct. This mentality saves you from the trap of indecision and infinite postponement of implementation. The problem is that, honestly, I'm not the best implementer. I'm focusing on improving my CS chops because I tend to get muddled up on syntax and data structure. I may be working towards failing fast. Until then, I have faith that proper planning and support of my team members will carry us through. As we've said before, weighing principle versus pragmatism will lead you to the best solution.

I've gotten some very positive feedback regarding my Maya 2012 review in Game Developer Magazine, which is fantastic. I hope to find more writing opportunities soon. Speaking of opportunities: if you are a talented Maya Character Rigger and are looking for work, please let me know! Riot Games and I would very much like to hear from you. :)

Cheers, and here's looking forward to the new year.

Tuesday, November 15, 2011

Publishing and Programming

If you haven't seen the November issue of Game Developer Magazine, you might want to check it out! There's a really awesome article called "The Game Entity" that talks about... game entities, how they're constructed, and many pitfalls developers tend to fall into. Not being overly familiar with main loops and game engines and hardcore multi-thread memory problems, there were a few points that needed some google-fu. Still, I found it very informative (and co-workers who are familiar with these things enjoyed it immensely!) This one is appropriate for all audiences.

Oh, also: I wrote a Tool Box review of Autodesk Maya 2012!

It's my first published work as a game professional, which is incredibly exciting! The folks over at GD were very helpful through-out the whole process and I'm really happy with how it came out. I'm not allowed to re-post it here yet, but please do check it out in magazine form. (Edit: considering it's been 4 years and it's online in PDF form... link above) Not to spoil anything, but I get a couple good jabs in there about Autodesk's appetite for early releases and hot-fixes.

My team is talking about adopting Google's 20 percent time concept, which is also exciting. The concept is, since most sprint planning and retrospective days turn our schedules into meeting Swiss cheese anyway, we should take those days to work on personal projects. This allows us to expand our skills, kill a few bugs, increase team bonding, implement a few small nifty-but-not-essential features, and generally become 20% cooler.

My time will probably be spent continuing to learn C++ and C#. I am rediscovering C++ syntax (it's been a while) and am remembering all the crazy shenanigans it gets up to. Yesterday I wrote a list class as a refresher; I will not tell you how many times I tried to run and said, "oh, right, I need a blank .cpp for this header," or, "I guess it's not really going to error... it thinks that variable is out of scope, but visual studio is just lying." A couple engineers on our team have volunteered to help lead this effort (much thanks!), the whole tech art team is pilling in, and it's going to be a party.

I believe the ability to learn can be improved with practice. It's a key component of mental fitness to constantly try new things, especially subjects alien to your core studies. I want to see more developers learning new languages, singing opera, watching documentaries, taking sailing lessons, playing rugby, or learning instruments. It may even feed back into your core discipline! You may see something new about water physics while fishing or learn more about AI through paintball. That mental flexibility will give you tons of value and insight you would have never found at work.

Honestly, though, that's not even the big win. I don't care if my capoeira classes ever further my career or give new insights into animation. The big win is in living a richer life and feeling like every day has something unique in it. I love drawing connections between things when it's not even useful. Today Troy was showing me a new auto-attack particle for a champion; The only thing I could think of was, "that flash and smoke trail looks just like the mini-sonic-boom a pistol shrimp makes."

And that's not useful. That's just cool.

Thursday, November 3, 2011

Level Up + Force Multiplying

Hello internet,

First, personal news: it's been a good week! I'm excited to say that, after finally receiving my yearly review, I've been officially stripped of my junior status. My title has evolved from "Associate Technical Animator" to simply "Technical Artist," indicating an increased range of responsibilities and influence within Riot Games. Huzzah! I'm very honored and excited to move forward with my team as we continue to improve our tools and pipeline. It's going to be rad.

During my review, one of the points Riot underlined for me was the importance of being a force multiplier. For those unfamiliar with the phrase, essentially it speaks to the value of teaching and enabling those around you to be more effective. Providing better tools, teaching new methods, improving communication, or simply increasing morale are all forms of force multiplication. To me, it is the core principle of tech art.

Last year, I was in a much different place at Riot. At the time, most of my work was related to hooking up new character rigs and skins. I was also responsible for creating dynamic poses for the characters, as we used these for reference when crating splash art. We had about seven character skins coming out per patch, so this represented a large chunk of my work velocity. It was difficult for me to do this work and simultaneously undertake tools initiatives or otherwise improve the pipeline. I was also a bottleneck: splash artists and QA depended on me finishing these characters before their work could begin.

Two important things happened: first, we sought to train others on the animation team to do these tasks. Sharing knowledge and responsibility made us more flexible. Second, we challenged the process. We experimented with outsourcing and creating other ways to generate poses that didn't rely on the animation team. Ultimately, we found that while some concepts might benefit from 3D poses for reference, many worked well (or even better) free-hand. By reducing the number of cross-team dependencies and increasing the number of routes to achieve our goal, the pain point almost entirely disappeared.

This is just one example, but it speaks to a philosophy. Whatever your work may be, continue to ask the question: "What is more difficult than it needs to be?" Where can we reduce dependencies? How can we share knowledge? What happens to your production if you get hit by a bus? As counter-intuitive as it may seem, you actually want to make yourself obsolete. Remember: if you want to be promoted, the best strategy is to train your replacement. Until you do, you are stuck.


Tuesday, October 18, 2011

Trip Success! + Overdue Post Mortem

Today's art borrowed from the excellent

Despite a flat tire in the middle of nowhere and very little sleep, I had a wonderful time in Florida last week! Many thanks to our hosts at Ringling College of Art and Design. We had a great turn out for both the presentation and Q&A sessions, and the student work was really impressive. Best of luck to the Seniors with their thesis games. Hopefully we will return in the Spring for some more presentations and portfolio reviews.

Whenever asked, I always advise aspiring tech artists to blog about problems they've solved. I thought it might be finally time that I follow my own advice. What follows is a walk through of the script I wrote as a test while in my last semester at Ringling. This is what got me into Riot as an intern! I'm going to make this walk-through very high-level, trying to focus on steps I'd approach when writing any script. Let's do this.

First off, here is a video that I made back when I first finished the tool demoing the functionality (might need to re-size window to view). Check out that sweet Maya 2009 GUI! I will describe the problem and my thought process below, so don't worry if you don't want to spend fifteen minutes watching through the whole thing. Secondly, here is the script.

The goal of the script was to mimic some XSI weighting functionality that the customer's version of Maya (read: Maya 8) did not have. The problem as described was, "be able to select a set of verts and joints and intuitively weight those points to those joints, either evenly or by distance." This has obvious uses, such as when one has many noodle-y appendages near one another and does not want to hand-paint away all undesired spill-over weighting from nearby joint chains.

So! What do we need to do to make this happen? Whenever I approach a script, I do the following things:
  • Design a work flow/ user experience
  • Write up pseudo-script logic of what the script will do
  • Identify any problem spots I'm not sure how to do
  • Draw some mock-up UI
In the case of this script, the user experience I imagined was:
  1. Select the verts that need to be re-weighted
  2. Select the joints they should be weighted to
  3. Set whatever settings we need (evenly or by distance? max influences? Anything else?)
  4. Push button, receive bacon weighting!
Seems easy enough. Okay, so aside from the UI, what does the script actually do when I run it? Time for some pseudo-code:

joints = list of joints selected
verts = list of verts selected
for vert in verts:
    bonedist = dictionary of distances to each bone
    for joint in joints:
        bonedist.append(distance from vert to joint, paired to bone name)       
    count = user setting for max influences
    while count > 0:
        if even bind:
            lowbone = bone with (count)th lowest distance
            vertweighting(vert, lowbone) = 1/max influences
            count - 1
        if distance bind:
            distSum = sum of all items in bonedist
            lowbone = bone with (count)th lowest distance
            vertweighting(vert, lowbone) = bonedist(lowbone)/distSum
            count - 1
Okay, cool. Less than twenty lines of pseudo-code! It tells us the logic of the work that needs to be done. This will ideally turn into the notes in our script reminding us what we're actually doing.

Next, we need to identify the parts of this script that are difficult. Depending on your experience with Maya or python, you may be hesitant about:

  • How to organize this data elegantly
  • How to use the dictionary data structure for the bone/ distance pairs
  • How Maya stores vertex weighting
  • What command sets the weighting of a specific vertex to a specific bone
Luckily, a bit of internet searching can answer any of these questions! With a bit of digging, you will learn that a dictionary is an unsorted list of key/value pairs that can be searched by key or value. You will discover that Maya polygon objects store a weighting matrix of vertices and joint influences. You will discover that you need the setVertWeights command for this task. Isn't the internet awesome?

Here is the final UI (again in awesome Maya 2009 style) that I arrived at. As you can see, I provided check boxes and radio buttons for all the options we planned for, as well as several that merited addition after some further research. 

Once we have all these things in place, it's time to actually start coding. I'm not going to go into this step as this post is getting a bit long. Suffice it to say that no mater how well we plan, it usually becomes apparent that things are more complicated than we anticipated. In my case, I ended up dividing functions and re-combining them as I struggled to understand python class/ object structure. I learned a lot through this project about the structure of a tool, a lot about object oriented programming, and a lot about vertex weighting in Maya.

When writing any tool, it's important to not lose sight of your goal. Think of the person that you're designing for, and try to imagine what it will feel like to use the tool you've created. Is it intuitive? Does it do all the things it should do? Is it fast? Could you make this tool simpler? For anyone who might want to improve upon your work, did you comment your code sufficiently that another programmer could follow your thought process?

I heard a great piece of advice from a co-worker: when you code, you have three customers. The first is the end-user, who will use your work. The second is other coders, who may have to edit and maintain it. The third is the hardware, which will have to process it as efficiently as possible. Making just one or two of these customers happy is not enough. Weigh principle against pragmatism, and invest your efforts where they'll be most beneficial to the project.

That concludes this post mortem of the jpWeightsTool. I hope you got as much out of reading it as I did out of writing it! Cheers, and happy coding.

Friday, October 7, 2011

def HelloWorld(newContext):

Hello internet! Since I last posted here, many things have happened... most of them incredible.

I not only had a fantastic internship at Riot Games, but since became a full-time technical animator. I have seen our product, League of Legends, evolve from a pretty popular online game to a multi-award-winning, international, multi-million-player sensation. I have a GDC award sitting on my desk. I love my job. Everything went... way better than expected.

I also had a bit of a career re-focusing. When I last posted here, I listed my skills as "animator and concept artist." While I still love to draw and animate, my career path has strayed almost entirely into technical art. This is actually awesome. For the past year, I've become involved with a very smart and passionate group of people focused on helping others on their teams be effective. Though I've animated a few characters for LoL (Swain, Urgot, and Jarvan IV!), I've touched every character in the game by re-making their rigs, fixing problems, making tools, and generally filling that all-important support role. I'm learning more about rigging and programing (so far, mostly Python with a smidgen of C++) and a lot about game production. I'm really excited to see what sorts of problems I try to solve next!

The switch from student to industry professional happens incredibly fast. It was bizarre for me to go back and read my first couple of post on this blog; I was totally focused on the goal of getting hired and, as soon as it happened, I needed to totally re-contextualize my idea of success. I'm sure most Rioters who have been part of this ride from the beginning are stunned constantly by how far the company has come.

I'm excited to say I've had a few opportunities to help other students make the switch to industry professional as well. I've looked at dozens (hundreds?) of portfolios at GDC and SIGGRAPH. I've made a presentation with my co-workers to student volunteers just a year after I was sitting right where they were. Next week, I'm going to have the incredibly surreal experience of making a "how to get into the industry" talk at Ringling, speaking to many of the people I've known as a student! I'm incredibly excited for this trip. I've got my slides ready and a follow up Q&A lined up with the Game Design Club. It's going to be sweet.

I don't know how often I'll update this blog. Ideally, I start posting some work related to tech art; none of my internet presence currently suggests what I actually do. This is terribly hypocritical, seeing as I encourage every student I speak with to demonstrate their work and thought processes through blogs or websites. Historically my interests have been incredibly fickle; I start and stop side projects all the time. Within the last couple months I've started D&D campaigns, Warhammer 40K leagues, music jam sessions, indie games... tonight alone I painted miniatures for a co-worker, edited an article that'll be coming out soon in Game Developer magazine (super excited!), watched SoloMid livestreams, and wrote this blog post. I'm not sure I'll be able to stuff everything I want to do into the nights and weekends, so expect updates to be sporadic as usual.

For most of my life, I've felt guilty about the projects I keep starting and stopping. I'm starting to think, however, that it doesn't really matter; all of this is valuable. Even if I can't maintain focus on one problem for months on end, it's exactly this desire to stick my hands into everything that's allowed me to grow into a support role across many different projects. I'm excited for seeing where it all goes next.