Well, it's been a long time since I've had a chance to post here. Thanks again for all the feedback. After finishing the public dev build in October, I jumped straight onto porting Papers Please to iPad. That finished up in December and a bunch of family stuff has kept me from spending full time on Obra Dinn.
I did manage to make some progress though, on creating the ship's ropes, sails, and rigging. I thought this would be done in a few days but it ended up taking a few weeks. There was a lot more technical work than I expected, and several different systems that I needed to figure out in Maya and the game. I'll list what I ended up with for each system and the stuff I tried before getting there.
Maya Script OpsBefore that though, a brief explanation of the scripting setup for this project in Maya. I mentioned way upthread that I prefer modifier-based editing over Maya's lossy system. To get that working, I attach custom commands to a node's "notes" attribute (editable directly in Maya).
Notes attached to a node in Maya
Then I've got a big "applyOps()" script command bound to Cmd-R. When I hit Cmd-R, it duplicates the object, applies all the commands, then hides the original. If I Cmd-R on the opped copy, it deletes that copy and unhides the original again. So I can quickly tweak the geometry and commands. Each time there's some new operation I need, I add it to the applyOps() function. There are already tons of commands like "cut", "add", "combine" (boolean operations), "bend", "pieces" (split into pieces), "duplicate_reflect", "material", etc.
The system isn't perfect (I can't edit and see the results at the same time for instance) but it's good enough. And there's an unintended benefit to staying out of Maya's construction history that I'll talk about below.
Rigged RopesAll the rigged ropes are generated from Maya curves. The "rope" command allows me to specify non-rope geometry to place at the start and end for pulleys, deadeyes, etc. And I can also easily add a slight sag to the geometry.
Pressing Cmd-R on a bunch of curves to generate ropes+pulleys
At the beginning I tried hand-modeling a single rope, then instancing it across the ship but that turned out to be a huge pain in the ass. Placing ropes is much easier if you can just drag the two endpoints of a curve around. Getting that to work requires scripting/engineering work as opposed to artistic sweat.
"Ladder" ropes are also really hard to do by hand. After a few tries I gave up and wrote a script for that too.
Script-generation of crossing ladder ropes
In Maya I apply a "vertical" or "horizontal" material to each rope, which gets picked up in the game to generate special uv-coords on import. These coords are used by the vertex shader to flap the ropes around in the wind while keeping the ends pinned. Generally-vertical ropes flap differently from generally-horizontal ones. Getting sets of ropes (the shrouds for climbing the masts) to flap around in sync required some extra work.
Using a vertex shader for this animation allows Unity to consider all the rope meshes as "static" and batch them together to save draw calls. That ends up being a big win. The downside is that I don't have a good way to treat the the pulley verts on the end differently from the ropes, so there's some unwanted warping there.
Flapping ropes
BoomsThe sail booms are pretty simple except that they have ropes attached to them. So if I want to swing the booms back and forth a bit, the ropes need to somehow move with them. If I had a true in-game rope system this would probably be easy, but all the rope geometry is baked/static.
I ended up generating skinned meshes on import to Unity, with definitions in the Maya file for how each attached rope should be bound.
Instructions for the importer to generate a skinned mesh bound to transforms with certain weights
This technique creates a slightly-unnatural bending in the attached ropes and they don't slacken/tighten correctly. But it also doesn't interfere with the flapping vertex shader and as long as the attached ropes are long and the movement is subtle it looks fine.
Ropes attached to swinging booms using skinned meshes
SailsThe flapping vertex shader worked great on the ropes so I tried the same thing with the sail fabric. Unfortunately, flapping 2D cloth is a lot more complex than anchored 1D ropes. After some unfruitful vertex shading experiments I discovered that Unity has a built-in cloth system. The editing interface is buggy beyond useless, but you can set the cloth coefficients directly in code no-problem. The results run fast and look good enough.
Torn sails using Unity cloth
For better performance, the cloth is non-colliding. This requires some special modeling to guarantee no intersections - and a constant wind force from behind to push the sails away from the masts and all the rigging.
I use the texture v coordinate to specify whether a cloth vert should be pinned or not. Using UVs like this, and not for actual texturing, has been a common and really useful trick for this project.
Using texcoord V value to specify cloth coefficients
Rendering for the sails is slightly different: they're two-sided and use a special lighting function to make them fully-white when viewed from the front and fully-black when viewed from the back. I found that proper lighting makes them too distracting, especially with the low-poly cloth-friendly geometry and all the ropes passing around.
Piled RopesOne thing I learned in researching all this rope rigging bullshit is that old sailing ships were basically just wooden boxes full of ropes. The amount of ropes holding everything together is staggering. I don't even have all the rigging in place and it's already distracting to look up and see all those lines.
On top of the rigged ropes though, these ships also had a ton of coiled and piled ropes just lying about - ready to be used quickly. I wanted to capture this sense of excess by leaving realistically-coiled ropes all over the deck. My first attempt at that was hand-modeled and is visible in the first dev build as a tire-looking thing on the aft deck:
Original piled rope. Don't steal.
To get these looking right, I needed technology:
dynamics. Maya Complete has a great nDynamics system built in, but up until recently I've been using Maya LT, which has exactly nothing. This was the final straw for me working around Maya LT's limitations though so I finally cracked and bought a license for Maya Complete. My thanks again to the success of Papers Please that I can make purchases like this; Maya Complete is expensive.
The enormous downside of upgrading to Maya Complete at this point is that it can't open any file generated by Maya LT (.mlt). That's purely a marketing/DRM thing from Autodesk - they don't want studios buying lots of cheap LT licenses for their animators while the TDs use one or two expensive Maya Complete copies for the heavy lifting. It makes sense tbh, but it really sucks when you're like me and just want to upgrade your single-seat studio to the full version.
The recommended path for LT->Complete is through FBX export/import. Unfortunately and predictably this loses tons of information, most critically all HumanIK properties and all node construction history. I haven't tackled HumanIK yet, but the heavens shine on me for construction history. Since I'm using my simple applyOps() system for most of the complex modeling I can just delete the "opped" output meshes in the imported FBX and regenerate them in Maya Complete.
Now that the ship scene has been transferred to Maya Complete (.ma) I have access to nDynamics. Specifically, the hair follicles system is just right for taking a hand-modeled curve, giving it dynamic properties to have it fall in a pile, then converting it to a rope using my existing scripts.
Using hair dynamics in Maya Complete to physicalize/drop/collide a curve
In practice there are plenty of small complications with the scripting here: detecting and temporarily physicalizing all meshes beneath the rope, choosing dynamics properties for a good shape, running the simulation for a few frames, optimizing the output curve shape, converting to a polygon rope, adding color bands for in-game rendering, etc. But all told I'm really happy with this. So far I've only added a few loose and piled ropes but it's so quick that I'll hit my target of "way too many ropes lying about" easily.
O.S.H.A violation
The crew couldn't tidy up before dying violently
RenderingOk, one last thing. Something I worried about for a while was how exactly to render all the rigging ropes. Drawing them with the standard outlines looks ok close up, but ends up generating too much visual chatter and thickness for distant ropes. The fix is to LOD the ropes so the outlines stop rendering at a certain distance.
Dropping outlines on distant ropes
From HereMost of this rigging work so far is for the main realtime scene. The flashbacks won't have any movement so the vertex animation, skinning, and cloth will all be baked/modeled straight in Maya. I've purposely held off on filling out all the rigging in this scene since I won't know exactly how it'll look until more flashbacks are implemented.
TimelapseSeveral weeks of sporadic work compressed into 18 minutes. Skip to
~17:10 to see a short in-game walkthrough of the final results.