I’ve been looking for an excuse to get into some Source Engine modding ever since Half-Life 2 came out; and sure, I’ve wanted to do my own total-conversion mod (who hasn’t?) but knew I lacked the attention span to do so. So, along comes Half-Life: Source, a straight port of Half-Life content into Half-Life 2’s Source Engine. However, as I detailed in a post almost two years ago, Valve couldn’t even be bothered to do some decent textures or models for the port, despite them having most of the necessary materials already created for HL2.
This omission of graphical upgrade really irked me. At the time of the aforementioned post, I had even tried to copy the G-Man from Half-Life 2 into HL: Source, but alas the animations didn’t match up. Recently, I decided to go back through HL: Source again on a whim. Greeted with the same low-poly models and low-res textures as last time, I became more stalwart in my longing for high-quality graphics. I took another look at the G-Man to see how I might overcome his lack of vanilla Half-Life animations.
Given my experience with Valve’s model format in the past, it was obvious that I’d need to rework the G-Man’s animations to match what Half-Life: Source expected and that this would require the use of a SMD-compatible modeling program. It seemed like XSI Mod Tool was the preferred free modeling solution around the internet, but its interface is very complex and quite overwhelming. Even though I had an idea of what I wanted to do, I had limited success trying to figure out how to do it in Mod Tool. Not to mention, it has a horrible installer and installs some files wherever it pleases. It turns out, however, that Milkshape3D had been updated for Half-Life 2 and did everything I needed for this conversion; so I dropped Mod Tool. Despite the upgraded engine, the models function roughly the same as they did in the Gold Source engine, merely having more vertices and bones. Of course, I also needed a MDL decompiler to get the geometry and animations from the subject models and the Source SDK to compile and view the models (all of which, annoyingly enough, require being logged into Steam to use).
Unfortunately, Valve changed the pose for the model reference in Source. Most notably, the arms in Gold Source are down, close to the body; and the arms in Source are raised slightly. (This appears to allow for more polys underneath the arms.) This was a problem because it meant I had to fit a skeleton from Half-Life: Source using one pose into geometry from Half-Life 2 using another pose. My first attempt to overcome this was to move the bones in the skeleton into their proper place in the geometry. However, this resulted in the failure at right, because the bone sequences (animations) use absolute coordinates to move.
My next attempt to fit the skeleton and geometry was to reverse the previous process and move the geometry into the bones. This seemed to work, but ended up destroying a lot of vertices in the armpits due to the aforementioned arm pose conflicts. Next, I went about the laborious process of assigning vertices to bones, which was made even more problematic by the ten-fold increase in vertices for the HL2 model and the reduction in the number of bones in the HL:S model that caused existing assignments to not match up. By the end of the day, I finally had something that worked at least half-way in the screenshot at left. However, as one can clearly see, the eyes are rolled up into the head and the briefcase is floating behind the G-Man. Also, I still hadn’t figured out the mouth movement at this point.
Over the next few days, I dealt with each of the remaining major problems, which had rather unintuitive fixes–I was obviously still learning as I went, though. The G-Man’s briefcase was apparently a separate model which was attached to the G-Man’s skeleton; however, quite problematically, it had the HL2 model’s skeleton and thus refused to attach correctly to the HL:S skeleton I was using. I fixed this by just taking the geometry of the briefcase and putting it into the G-Man’s geometry. It was a clever and time-saving fix, albeit the briefcase now bleeds if shot. Fixing the eyes was significantly less straightforward and required several trial-and-error tests until finding out that the Flex data was required in the compile script even though the model didn’t take advantage of the Flex facial expressions. Some mainly random fiddling with the “eyeball” properties and “eyes” attachment was also in order.
Fixing the mouth was made more confusing than it should have been by decompile inconsistencies and more unintuitive Source changes to the model formats. Originally, I had suspected the bone controllers were responsible for the mouth and neck movements, and the Half-Life 2 Model Viewer seemed to confirm this theory. However, after having absolutely no luck getting bone controllers to work, I tried decompiling other HL:S models and found extra sequences for mouth and neck movement called blend sequences. The blend sequences basically just interpolate between multiple other sequences–in this case the mouth open and mouth closed sequences. Thankfully, it only rotated one bone (the jaw) in a single direction for two frames, so I could manually edit the sequences. What I didn’t know was that any blend sequence named “mouth” will automatically be assigned to the common mouth bone controller (which HL:S uses) by the Source engine. Then I hit another curious snag when I went to test the mouth after adding the blend sequences: the jaw moved fine, but the mouth appeared to be stretching open. It looked like the scene from The Matrix where Neo’s mouth becomes glued shut, you know “What good is a phone call, if you’re unable to speak?”. Turns out that was just because it’s insanely difficult to select the vertices on opposite sides of the mouth because they’re overlapping (probably to keep jaggies from appearing at the mouth) and are only a miniscule distance away from one another. It took some extreme zooming to find the right vertices to assign to the jaw bone.
At this point, I thought the model to be functionally complete, but I decided to test every appearance of the G-Man in the game to make sure. I quickly found that my model wasn’t walking correctly–the G-Man appeared to flash suddenly down his path. After more combing through the Valve Developer Wiki, I discovered that the root bone of the skeleton actually needed to move forward during a walking or running animation. It seems that the decompiler has issues with outputting proper walk animations.
Finally, I did a polish pass to clean up any of the lingering bugs with the model. One bug was that the teeth and mouth were unlit, making the G-Man’s mouth look like a black void (this is visible in the video below). This problem probably stemmed from a feature of HL2 that doesn’t exist in HL:S, where the material shader for the HL2 teeth is set to “Teeth” instead of VertexLitGeneric. The rest of the polishing involved mainly cleaning up vertex assignments to bones. Some vertices were assigned to the completely wrong bones, causing them to jut out during animations. Others just needed to be assigned to the next bone to prevent clipping or unnatural movement. The only problem I couldn’t fix completely was with the bottom of the suit near the crotch, apparently because the hip bone it’s assigned to has a bad rotation.
After my jubilations at fixing the G-Man’s walking animations, I did a little video to show him off in-game. I ended up just recording every one of his appearances in Half-Life, so this is not only neat because it’s HL2 G-Man in vanilla HL but also as a video reference of his appearances. It also features the awesome production quality that one should expect of me. And of course, you can download my converted G-Man for your Half-Life: Source. Or download the original video of what’s embeded below.