Veridus Quo

Tonight I was at a local gathering of moonlighting game developers. One artist was having a lot of issues with his character rigging in Maya. He kept having to go back and recreate his skeleton and skin weights over and over again. He wanted to know what the typical workflow was for rigged characters. He described exporting the skin weights so that he could reimport them if things went wrong.??

This is not a technical explanation. These concepts will be just as valid for Blender or 3dsMax as they are for Maya.

Here were my suggestions.??

 

The first guideline to remember is to make backups often. That means save the maya file and make a duplicate, or put it in a version control system. How often? At least once an hour. Also save additional copies when you feel you have finished something complicated. There are some tools out there that will do this automatically for you.??

Be sure to save the it as a Maya file. Exporters should only ever be used as a last resort. Don’t use a skin weights exporter to ‘save’ the state of that part of the mesh. Always save everything, and that means the Maya file itself.

Phase 1: mesh phase

Get your mesh formed how you want it in a bind pose. Do lots of test deforms manually, and then reset it back. This will be the only phase you will be able to easily add or remove vertexes. You can move the vertexes easily later for tweaking, but adding or removing them later can be dangerous.

Put extra vertexes near joints that are expected to bend significantly, like more than 20 degrees. Take a human elbow for example. You might think one ring of vertexes at the place that the elbow will bend internally would be enough. Instead, have at least two rings of vertices just above and below where the elbow will bend. This will later be used to smooth out the large joint changes.

You may freely do texturing in this phase if desired. It is easier to do if you aren’t adding and removing vertexes, but it doesn’t hurt to do it here (or in any following phase).

Phase 2: building the skeleton

Now we will build the armature that must line up with the mesh. It is vitally important that you don’t move forward until the skeleton lines up with the expected internal joints of the mesh.

Starting in a 2d view, perhaps Front, build the armature and line it up with your mesh, all in this 2d view only. Do not bind the mesh yet! Then use a Side view and tweak only the depth of each pivot point. You will likely have to adjust the joint lengths slightly to maintain the proper lengths.??

As you build each joint, this is the best time to create any movement constraints you want on your joints. The range of motion can be adjusted later, but the correct orientation of the joint must be set now. In the case of an elbow, you will want to align one axis with the large up and down rotation that elbows can do, leaving the other axis for the smaller side to side motion limits.

You are welcome to add any desired inverse kinematics or other control structures at this or later phases. This can be handy for quickly testing the resulting mesh. Just be sure to undo any movement created by the controls before you get out of sync with the mesh.

Largely you will want joints that match up with real physical joints. A joint at an elbow for example. That said, there are some unexpected tweaks that can significantly improve the quality of the final skeleton.??

An arm with a hand on the end should have an extra joint added just above the wrist joint, perhaps a quarter of the way between the wrist and the elbow. Keep it in line with the ‘bone’. This joint will never be rotated to ‘bend’ the bone, only ever rotated to partially follow the wrist rotation. This way the wrist can rotate up and down, and side to side while not significantly affecting the forearm. (See this superb but technical paper for more information.)

Another exception is to remember that the joints do not have to stay physically inside the mesh. If there is a large curved mesh section that will never change curvature (like an alien arm with a curved bone), just make a single joint from one end to the other. You do not need smaller joints in between just to keep it visually within the mesh. Joints are never rendered.

Once you have realigned everything, go back to a perspective view, and triple check the joint positions. You will not be able to easily go back and change the joint lengths after this phase.??

Phase 3: binding the skin

It is finally time to bind the skeleton to the mesh in its bind pose. Pay close attention to the options in the binding tool. You will want to have Maya make as many vertex weight calculations as possible for you. Therefore bind it, and then start deforming the joints to see how well the default skin looks. The resulting mesh should look good in most places, and need tweaking in a few. If the skin moves like it is a mushy sack of potatoes, undo the bind, set a smaller influence radius and bind it again. On the other hand, if the skin looks rigid then the influence radius is too small.

Phase 4: everything else

At this point the key features are set in stone: the vertex count and the joint count. From here is all tweaking. Editing the texture itself, or the uv coordinates is perfectly fine. Editing the skin weights is a must to get every movement just right.

You may edit the positions of some vertexes, tho it is discouraged. Doing so also requires adjusting the skin weights. Typically it is better just to adjust the skin weights alone. Either way, do not add new vertexes or remove them. It tends to mess things up badly.

Avoid changing joint lengths. You can do it, but then you have to adjust a fair number of vertex positions and weights to make it not feel stretched.

 

Maybe this artists guide to the workflow of creating skin meshes will help someone out there. It already helped one, so it must be of some use! If it is useful to you, pass it on. If I’m wrong about something, poke me on twitter @DrakkenWulf. Happy modeling!

UFOs and the aliens that drive them

At one point in every coder's career, you will get that one requirement that you just don't understand why they would have such an inane requirement. Thanks to a good presentation, I can now close the book on the worst one of my career.

 

Once upon a time I worked at a place that wanted something better. They wanted reusable code. This was the early 2000's and we were coding in perl. This company was built on custom cgi servers written in c, and we used perl for all the admin/backend stuff. It worked for us. It was perfectly fine that they wanted something better. The catch was, they had no idea what "better" looked like. But I'm getting ahead of myself.

So they hire a java guy with a pretty certificate he propped on the windowsill behind some glass. This did not bother me. They told me, him, and our user interface artist to rebuild an existing administration website using a reusable object model. This bothered me – I had written the current site (in perl), and it worked.

Being a professional, I got down to business. Learned enough Java and the Tomcat environment to put an active website together. Listened to the new guy about designing the site in five "layers."

  • Presentation: the browser
  • UI: converts data to html for display
  • Business Logic: application specific decision logic
  • Data Access: intermediary to Database
  • Database: actual data store

And that's what we did. It worked, but only barely. It took far longer than just writing the app with the previous standard perl did. And the code was terrible. Most of it was very delicate, and in no way reusable. When the bosses wanted a new field, we had to literally edit ten different places to do it.

So we presented this project to the bosses. And what did they say? "We don't like it. Clean it up and do it all over again. You have a week."

At the beginning of that week, I thought it should not take long to clean it up. But as each day passed, the nights got later, and the goal got further and further away. The due day came, and we had absolutely nothing to show for it. At nine years in, already anything but a spring chicken, I had my first and only panic attack. I had never failed so utterly before or since.

 

Fast forward another decade. I'm regularly working with people who were children when I started coding. Makes me feel old. Along comes the Kansas City Developer Conference (http://kcdc.info). For two days, I go to every code design presentation that I could, barring one presentation about making good presentations. But I digress.

There it was: "Pragmatic Architecture in .Net," hosted by Cory House (http://www.bitnative.com). One presentation, just one hour, I am introduced to some things that answered every question about why that project failed so many years before.

In game development, typically the most abstract you get is MVC if you are lucky, spaghetti code if you are not so lucky. I've been hearing things like Service Oriented Architectures (SOA) for a few years along with a host of other acronyms. But as far as I could tell, they had no real bearing on game development. Finding simple explanations was fairly difficult, just from the plethora of acronyms available these days.

At the time it seemed unreal to have every layer need a separate declaration of the exact same block of data. Or why I should need a completely separate object just to run a SQL query that literally populated a flat datablock. Or how many places needed to be touched every time we wanted to add a single new data field.

Learning from past mistakes is something I care deeply about. For the first time, I could finally understand the fundamental principles they were asking me to implement on that job so many years ago. More importantly, I can now recognize the proper use of those principles. Were I to go back in time, I could have argued with the bosses much more convincingly: they were asking for a SOA design, yet their business needs were truly served better by the simpler Active Record approach.

 

Disclaimer: this post was not solicited in any way. For years I've been the fix-it guy for many projects and it's about time I started expounding so someone else might avoid making the mistakes I've seen. Therefore these writings are entirely self-serving because I don't want to be the one to fix it anymore!

Hellfire (iPhone Game)

App Icon

  • Product description: Free-to-play Card Collecting game
  • Release Date: April 9, 2013
  • Product history/genesis: This is the first Unity3d-based title for the company. I was brought on to add new features to the product.
  • Team: Lead Coder, Self, Three Coders, Three Producers, Multiple Artists, QA team.
  • Core Technologies: C# in Unity3D, with native Java and ObjC code for platform specific plugins.
  • Most proud of: Quickly learned Unity3D, and made significant improvements quickly.
  • Responsibilities: Added Special Dungeon features, Code Refactoring and Engine support

Flick Controls Appstore Image
While I had done a little research into Unity3D previously, I did not feel a need to get deeply into it. After my company was bought, they forced a new tech direction, and by the time they allowed for native game engines again, theComplex had stagnated for two years.

As things turned out, it was the best possible situation. The deeper I got into Unity3D, the more the engine resembled the core design ideals of my own. In fact there were a few situations where I was able to guess the internal design of some Unity3D features simply by imagining how I would have written it in my engine.

Deck Edit Appstore Image
While my tasks started small, in the six months leading up to this major release I touched nearly every facet of the game. Adding new user interface scenes, working with downloadable asset bundles, creating asset bundles, and adding to the sqlite data management system.

One of my major tasks was to make scrolling lists act correctly on the new iPhone 5 with its taller screen. Up to this point the game simply stretched the standard 320×480 scene to the larger aspect ratio, and the effect was noticeable. I rewrote major chunks of the scrolling system to support proportionally correct scrolling, while still filling the entire display.

I also was a significant part of creating a new event type, the “Special Dungeon.” In standard dungeons you can choose to play any specific round of the game in a largely static environment. Special Dungeons have a specific progression of rounds that got progressively harder. With each round you would visually “crawl” through the dungeon to face the next foe.

I have continued to make improvements on this title, but now am on to other projects at the company.

Coin Push Frenzy HD (iPad Game)

App Icon

  • Product description: Free-to-play carnival game.
  • Release Date: Nov 24, 2010
  • Product history/genesis: Original title (Coin Push Frenzy) was handed to me to clean up enough to release. After doing so, I recoded it in my game engine (theComplex) to create the iPad version. Re-used most artwork from the original game.
  • Team: Self, Producer, Artist, QA team.
  • Core Technologies: C++ game in theComplex engine supporting iPhone OpenGL, and partial Android OpenGL
  • Most proud of: This was a very fast conversion. By this point my game engine had matured enough to allow this conversion of a very messy, zero commented, plain C codebase into a sleek and efficient game within a couple weeks.
  • Responsibilities: All code and art integration

Game Screenshot

All of the 2d user interfaces were implemented using Interface Builder. theComplex was able to load xib files directly and create OpenGL-based objects with them. This also included support for any aspect ratio screen (as would be needed on Android).

There are actually two physics engines in use on this product. theComplex has bullet physics integrated into it, and this was used for almost every object. However, in the original game, all the coins that were directly on the face of the playfield were handled manually in a 2d-only, much simpler physics system. This was done as a performance optimization. The side effect was that a coin that dropped onto the playfield at a slight angle (say, by getting hung up on the pusher) would actually stick at that angle permanently as it moved down the playfield instead of laying flat as one would expect. The HD version of the game preserves this error, despite the fact that the improved engine did not need the optimization any longer.

Machine Selector

When beginning this conversion, I built a few alternate models for the playfield to take advantage of the iPad’s larger display size. None of these alternate models made it into the final game, but the engine was able to play just fine with them.

Some of the most difficult things to reproduce in the new engine was the particle effects of the original. The original was based on redrawing everything every single frame, and the new engine is designed with a core concept of “assume it will exist in the next frame.” This was eventually handled by adding some particle system support to the engine, with dynamic vertex buffers. Up to this point, supporting both Apple’s vertex buffer standards and the ARB versions (for different hardware) was not that simple. But Apple had finally made the ARB versions available across all hardware which considerably simplified the task.

This was the first game based on theComplex game engine to run partially on Android devices. It could get into and display the main game board. I was unable to complete the port, as ngmoco had just purchased Freeverse and completely changed the technology direction behind our games, canning it.

An older (but more exciting!) portfolio page for this project.

NBA Hotshot (iPhone Game)

Game Icon

  • Product description 3D pop-a-shot basketball game. Reached #29 on Top Applications across entire App store.
  • Release Date Jan 5 2010
  • Product Genesis Had previously built a basketball shooting multigame (Flick Basketball) with my theComplex engine. We redid the models and graphics, breaking this component out into it’s own title to focus and polish it.
  • Team Self, Producer, Artist, QA team.
  • Core Technologies C++ game in theComplex engine supporting iPhone OpenGL
  • Most Proud Of Integrated a theora video decoder for the backboard to animate short videos triggered by the player’s actions, like that seen at arcades. This was on devices that could not yet do any sort of video through standard apple APIs.
  • Responsibilities All code except the ball throw itself.

Gameplay Screenshot

All of the 2d user interfaces were implemented using Interface Builder. theComplex was able to load xib files directly and create OpenGL-based objects with them. This also included support for any aspect ratio screen (as would be needed on Android). Later on I found out the producer was able to create a free advertisement-based version of the game without any need of a coder until it was practically complete.

Backboard and net movement were animations imported from Maya using the Collada importer of theComplex engine.

Added synchronized network play with four other players via GameKit (bluetooth or wifi). It synchronizes the game start, then displays the scores of the other players in real time.

High Score Display Screenshot
Integrated Plus+ leaderboard system.

Built an in game “store” that you can purchase additional basketballs and prizes. How you did in the game awarded you special points that you redeem in the store.

There was a bit of discussion around the ball throw itself. I had built a method of throwing the ball that worked out the ideal angle/speed to throw the ball, and then averaged all the player input to modify it. The feel was pretty easy, good for casual gamers. However the game Skeeball had recently been released and was a fairly big hit. In that game, only the player’s beginning and end of the swipe mattered, and it was used to make a direct correlation to the velocity and angle of the throw. It was much more difficult in my opinion.

An older (but more exciting!) portfolio page for this project.