YL2 Update Jan/Feb 2019 - Body type demonstration!
First and foremost, thank you so much for your patience. We know we are late with this update, for reasons we will get into soon.
These past weeks have been a huge trial for both me (odes) and dogson. The body type system and the content authoring for it have been immensely challenging for us, to the point that we were close to giving up on eachother. There were times when we were seriously considering to part ways. But despite the hardships, we endured. If anything, I think this whole experience has made us stronger. In moments like these where uncertainty and setbacks loom, all you really need to know is that if you just keep trying and keep making an effort, it's inevitable that success will eventually be granted. It's with great joy that we can say we're still kicking and still able to provide an update like this for you.
So with all that said, lets have a look at our latest developments and why things are taking the time they do.
Before we being, let's just summarize what body types are and our thought processes behind their realization.
In Yiffalicious (1), we always felt that the diversity of our characters and their differences in shape was one if not the biggest selling point of the app. Having this diversity just made things so much more interesting, and opened up so many more opportunities for fun and sexy interactions.
When we started working on YL2, we knew we wanted to try and preserve this diversity. At the same time, we also wanted to offer a character editor, but making a character editor that allow for the same amount of diversity as in Yiffalicious is very challenging. An obvious way to circumvent this problem could have been to simply offer two different types of characters - user generated ones made with the editor, and unique "special" characters made by us (similar to how Yiffalicious worked). This way, we could create vastly different characters without having to worry about integrating them into any editor. But we didn't like this approach. We found something profoundly appealing with the idea of all characters being made in the character editor, because this would force us to make all the content we create compatible with it and thus accessible to our fans. So we abandoned the idea of "special" characters to focus entirely on the editor.
Our original idea was to simply use sliders for the shape authoring of the characters in the editor, just like so many other games/applications do. However, we quickly discovered that this approach meant we would either have to limit just how far these sliders could affect the shapes, or limit the amount of sliders, in order for things to work and be manageable. Indeed, even for professional character editors you find in high budget video games, you don't see them able to create characters with the difference in shape and size as between let's say "Fraenir" (male dragon) and "Cat" characters in Yiffalicious. With these editors, it's usually quite easy to see that every character is based on the same model - any differences between them are just slight modifications of that said model. For example, In Skyrim it's easy to see that all the characters are essentially the same. Furthermore, each character that is, let's say, fat, would always look like the same kind of fat even though fatness can look in so many different ways. With our character creator, we wanted to get away from all of these limitations. Being the small team that we are, we knew this would be a huge challenge, but a challenge worth exploring none the less.
In order to achieve our vision of a diverse set of shapes for our characters, we had to abandon the slider based system and instead pursue something different. In search of ideas and inspiration as to what this new system could be, we browsed though content generated by the furry fandom, and came to the realization that most characters are actually based off stereotypical body types. Of course there are differences between all characters, but there definitely are archetypal shapes that can be abstracted and categorized, such as huge muscular dudes, thicc females, short stacks, slender beauties, and so on... So we began working towards this idea - the definition and implementation of body types as a selectable and configurable concept in YL2.
We liked this idea a lot, because it meant we gained full artistic freedom and control of the shape authoring process, allowing us to sculpt these body types individually and in great detail. It also meant we could implement several different versions of the same kind of archetype - for example different kinds of chubby where the fat has accumulated differently across the belly. However, this body type system came with many different challenges:
1. How do we create a generic low poly mesh that is robust enough to encapsulate the diversity of body types that we want to implement?
2. How do we migrate high poly body types to the generic low poly mesh?
3. How do we author different body parts (heads/hands/feet) that fit with each body type?
4. How do we handle parts that greatly affect the body type, such as digitigrade feet?
5. How do we eliminate seams between body and parts so they don't appear as being separate?
In short, it is these questions and our attempts at solving them that has taken us such a long time to tackle.
Generic low poly mesh (1)
This has definitely been one of the bigger challenges of the ones listed above, and also one of the scarier ones. Because when we started with it we didn't really know what this mesh should look like, so we were pretty much reaching in the dark. Each time we encountered a problem, we went back to the drawing board, adapted the mesh to handle the problem, and tried again. There were many times where we thought we had gotten it right, only to be proven wrong later down that path, forcing us to go back and fix the issues. The problem with this is that the longer we had worked on an iteration without any problems emerging, the more invested we would get into it, so when we eventually did run into a problem, any additional content made for this now obsolete model would have to be remade and adapted as well. As you might imagine, this iterative process has cost us a tremendous amount of time, and without really having much to show for it other than simply new variations. This has been frustrating for us - partly because doing the same thing over and over is annoying - but also because we have been working so hard each month, without being able to explain or show the full extent of our efforts. I'm still proud of the progress we've been able to show off in each update, but know that there's usually a lot more going on than we're able to show...
High poly -> low poly migration (2)
Creating a low poly mesh from a high poly model is simple enough, but this is not what we're doing here. Instead, what we're trying to do is adapting an already authored low poly mesh against a high poly model with a completely different shape. Luckily, there are software tools to help with this adaptation process, but learning them and incorporating them into our workflows has taken time. Furthermore, we've had to develop our own methods in addition to mentioned tools in order to get things to where we wanted them to be.
Part authoring & adaptation (3)
Creating and adapting separate body parts that are supposed to fit with a base body model can be quite tricky already as it is, but here we're making the processes even more difficult by having to do it for every body type that we implement. Each part needs variations that fit with every body type. This has been extremely difficult, and has forced us to develop our own plugins for our authoring software in order to author these shapes as well as manage the complexity. Even with these plugins, this work has been immensely difficult and complex, to the point where we've had to do a lot of internal documentation and training sessions in order to remember how to do everything properly. We believe we now have a working method for this task that we're starting to get the hang of. For every new part and body type that we implement, we get a little better at it.
In addition to having to adapt each part to each body type, we also have to do the reverse for parts that are in digitigrade form. I.e., each body type also needs a digitigrade shape that fits with the digitigrade feet. This isn't necessarily a problem, but it does mean there's more to keep track of, and any adjustments made to one thing will create a rippling effect, requiring changes in others as well, extending the amount of time required to get everything right.
The appearance of seams between models can be attributed to two things - 1) the mesh normals and 2) the different texture spaces. So we've had to handle these two.
For the first one, we implemented our own mesh normal calculator that runs on the GPU, making normals across seams point in the averaged direction of the connecting vertices, and thus making them appear as one model. Now, I bet most devs would have been happy with this solution, but of course we were not. Why? Because when importing a model into Unity, its source information of quads is translated into a more GPU friendly triangle representation. Why is this a problem? Well, this can be explained with these images.
Here, the highlighted vertex has 4 adjacent quad faces. The normal of a vertex is the average of its adjacent faces:
However, look what happens if the mesh is triangulated. Suddenly, the very same vertex has 6 adjacent faces! This skews the normals in the wrong direction, as some (formerly quad) faces are counted "twice"!
(When importing a mesh into Unity, it actually uses the original quad normals, but if you then "manually" calculate normals on the triangle mesh, they will be skewed. We need to calculate the normals manually to fix the seams.)
To solve this issue, we store each mesh not only as a regular Unity 3D model, but also as a quad mesh (using our own format), where all the original mesh data is preserved. We created a module that is able to translate between the triangle and quad mesh representations, which we use to calculate the quad normals, which are then injected into the triangle model. Such a seemingly simple problem required all of this work...
Ok, so that was for the mesh normals. Next was textures.
Blending textures is simple enough, all we need to know is what coordinates to use (the UVs). For this, we actually store a part of the body's UVs in each part, making it able to look up textures from the body. Then we simply blend the body and part textures according to a mask.
But here's when we ran into a problem... Blending normal maps across different tangent spaces (derived from UVs) is not possible. You need two sets of tangents in order to do that. Unfortunately, this simply isn't possible to do with Unity's SkinnedMeshRenderer, which required us to write our own skinned mesh renderer. This is something we experimented with months ago, but the custom renderer we made was only a proof-of-concept - not something we could actually use in a final build. So this month, we've made a release-ready version of this that is not only handling the tangent issue, but is also able to handle blend shapes (vertex offsets forming a shape) in a much more efficient manner than Unity's native skinned mesh renderer. This is because we're baking blend shapes we know to be static for a certain character configuration, and further more only perform the blend shape offsets if they have changed from last frame rather than every frame, meaning we save a lot of processing. (Blend shapes are processed prior to rendering in a compute shader, rather than during rendering as Unity's Skinned Mesh Renderer does.)
(Unity's skinned mesh renderer lack luster blend shape performance is especially noticeable if you use a shader with many passes, such as a fur shader which has dozens of passes, since each pass will essentially perform the blend shape processing. In Yiffalicious (1), we had to move the blend shape processing from Unity into our own module in order to get good frame rates. Here we're doing that too, but this time entirely on the GPU. There is a setting in Unity to move the blend shape processing from GPU to CPU which "fixes" this issue, but naturally increases load on CPU.)
Body type refactoring
In our original body type implementation, we had attempted a layering system, where each layer referenced a body type that could be blended in according to a slider and a referenced mask. The idea behind this system was that you could cherry pick and mix different body types according to your own liking. Of course this would cause issues, so we also invested a lot of time into something we called shape correction, which was a procedural correction technique used to apply a shape as an offset to the current skeleton rather than as a global offset.
Once we had enough content to start testing this system, we quickly discovered that the layering and shape correction weren't enough to make this look good in all cases. You could create general shapes that looked OK, but there usually were artefacts and iffy areas. Furthermore, the layering and mask authoring simply weren't any fun to use. It felt cumbersome and results were often unpredictable. We still think this system could work in theory given the right amount tools and correction techniques. However, in the form that it was, it simply wasn't enough. This is where we started to have second thoughts about this system, because if we were to make it work, we would have to implement even more systems to make up for its flaws, but there was no guarantee this would actually succeed (and we were already behind schedule). Furthermore, we also felt that regardless of what tools we'd implement to try and make this work, it would all feel so technical and boring to use as a user. That's not what we wanted.
So we went back to the drawing board. Keep it simple, keep it stupid. Results should be easy, instant and fun, not require a ton of work. Our new idea was to focus entirely on the individual body types and introduce "tweakables" - body type specific blend shapes that alter the character in different ways. Examples of such tweakables could be the abs of a muscular character - should they be clearly visible or more like that of Rhino in Yiffalicious? So instead of having to achieve that by authoring a mask and blending in another body type, it would simply be a slider. Also, since these tweakables are compartmentalized to each body type, it means we circumvent a lot of complexity that otherwise would become unmanageable. So we can implement tweakables at will without worrying how they interfere with other body types.
(I might add that inflation is something we tailor for each body type and that's always accessible for all body types regardless of what tweakables are present. Tweakables are a per body type addition to inflation.)
Body type & part demonstration
So with all that said, lets finally demonstrate how body types and parts currently work in YL2!
Here we have our new universal (generic low poly) model integrated into the editor. Apart from a different topology and higher triangle density, this one also stands in a hybrid T-X pose rather than a A-X pose. (We discovered that having a T-pose gave us more room to work on the arms, which is handy for big shapes like those on beefy muscle guys.)
With the character builder object selected, simply browse down to the "Shape" section and "Body type" sub category, and click "Body type". A window appears showing what body types are currently present in the app. As of right now, we don't have any preview images, so they all appear in white, but naturally the idea is to actually show what the body types look like during the browsing.
To apply a body type on your character, simply drag and drop it in the view (or select and press OK, or double click it):
As you can see, the character is significantly changed from its original shape.
You can still apply the body type according to a slider:
Parts are also affected by body types being applied, changing not only location and size but also shape:
This means we are not limited to having areas of the body that may not change. Necks, wrists and ankles are allowed to alter their shape between body types, giving us more freedom during body type authoring.
Also, notice that the areas connecting parts with the body are seamless.
As the body type is applied, maps are altered as well:
Here's what it would look like without maps:
To try another body type, simply drag and drop it in the same fashion:
Despite these two shapes being vastly different, they both work on the same universal mesh topology. This is at the core of our vision!
Naturally, like any body type, this one is also possible to affect with a slider:
If you want to switch a part (head/hands/feet) on the model, simply browse down to the "Species" category and click what part you want to change. Here, we're switching the feet from being plantigrade to being digitigrade:
Notice that the feet and body are adapted to fit with eachother! This goes for any shape, so if you were to apply the muscular body type, the feet adapt to fit its shape:
Of course, the digitigrade feet also work without any body type applied:
In addition to body types themselves, each body type can also have additional body type specific shapes that we call "tweakables". Since we have applied the bt_m_muscular body type, tweakables for this body type have been loaded in and are accessible in the "Tweakables" sub category:
(A "daddy" belly for bt_m_muscular, inspired by Rhino's belly in Yiffalicious.)
(A beer belly tweakable for bt_m_muscular.)
In the pictures above, notice that the maps are altered as the tweakables are blended in.
(Neck muscles. Despite the neck being vastly altered, the body and head still connect seamlessly.)
The cool thing about tweakables is that we can just keep on adding more and more over time. So if fans have requests for tweakables that they'd like to see on a certain body type, we would be able to add that. I was thinking maybe we could start providing polls for such things!
It has taken us a long time to reach this point. While the technology is for the most part fully implemented, we're still missing content in the form of body types, tweakables, inflation and parts. This is what we will continue working on in the future.
While the body type refactoring was a major task, it didn't take more than a few weeks to complete. So while dogson has been working on content for the body type system, I've been busy implementing other features in the meantime.
Skinned mesh import support
Previously, only static models were possible to import into YL2, but now we have a method of importing skinned meshes using the collada (.dae) format. This is a major feature that will enable you to import things like tails and have them bend during interaction authoring. The idea is to enable automatic physical behavior of things like tails, but that's something we haven't gotten to implementing yet. Still, this would not be possible without skinned mesh import support.
(We took Charlotte's tail and separated it into its own mesh. Then we exported it and imported into YL2.)
Just to prove it's actually a skinned mesh... (Affecting joints is not yet possible in the character editor.)
YL2 now also supports import of JPG textures in addition to PNG.
I was always under the impression that JPG was a big no-no when it comes to textures in games - that the lossy compression would be too apparent for them to be acceptable. However, in our testing, we've discovered that they actually work pretty well, even for things like normal maps! While all textures shipped with the app itself naturally will be stored in a higher quality format, JPGs may come to play a huge role in user authoring because of their small size, which brings us to our next topic...
PBR & normal occlusion layers
The acceptable quality of JPGs and their small size has giving us the confidence to add two new types of layers that are entirely user texture based - PBR layer and normal occlusion layer.
The PBR layer simply references imported textures for the albedo, emission, metalness and smoothness (inverted roughness) channels. Likewise, the normal occlusion layer is able to reference imported normal and occlusion maps, and blend them in on top of the body type normal-occlusion stack according to a mask and blend mode (either combines channels or replaces them, according to mask).
This way, you're essentially free to author maps in any software you like, and then simply import them into the app. The reason this wasn't viable before was because PNGs are simply too heavy. But with JPGs this is possible to do while maintaining relatively small file sizes.
These layers will open up for literally any type of texture customization you can think off, since you've got access to all texture channels used by the character shader.
(Example of authoring a texture in Substance Painter and then importing it into the app. Naturally, you would have to do this for the other channels as well to get the same look. In this instance, I think the smoothness was a bit higher in Substance Painter which made it look a bit shinier.)
(Local assets will listen for changes to files and update them automatically if the "Reload" option is checked in the local asset object, as demonstrated here. It's just a demonstration, not an artistic expression. I'm a programmer, what do you expect lol.)
Detail textures are patterns that tile multiple times over an object, defining its "feel". For example, a typical detail texture in the context of anthropomorphic characters could be a snake scale pattern, to make it appear more reptilian. Now, we have full support for these textures in YL2.
To assign a detail texture, simply import a repeating normal map you want to use. Make sure to use the "Map" mode when importing:
Then, in the "Detail texture" object inside "Character builder", simply click "Detail texture" and select your imported map:
In the sub objects of the detail texture object, you can customize the detail texture tiling and offset for each submesh index.
You can also assign a mask to use with the detail texture, so it only appears in certain areas. Here, we're simply demonstrating the technique using a radial gradient mask (procedural):
(Detail texture only applied where mask is authored. You'll probably want to author your own textures and use a mask texture instead rather than a radial gradient, but just as an example...)
(By enabling the "Final" view mode in the mask, we can see the changes in real time as you alter the mask. This is just an example.)
This is a minor change, but thought I'd mention regardless.
You are now able to scale spine and neck bones in addition to head, arms, hands, legs and feet. Also, the allowed slider ranges have been increased from 20% to 50%. This means you could theoretically alter your character regardless of body type to be more top-heavy, for example.
I think in the future, we will replace the float sliders with vector sliders, so you're able to scale on each individual axis rather than uniformly.
Quad triangle GPU raycaster
Mostly a side note, but figured I'd share...
As you may know from earlier updates, we have implemented our own GPU raycaster that is able to raycast against skinned meshes in real time. Now, we have improved this raycaster according to state of the art research, speeding it up by around 50% (1.5x). This is done by exploiting the wide vector width of GPUs and their SIMD functionality (Single Instruction Multiple Data), essentially testing four triangle-ray intersections at a time per thread rather than one, meaning we only need a quarter of the threads required previously. The instructions that benefit from SIMD will essentially perform 4 operations at the cost of 1. (This method requires a bit more setup and not all instructions can utilize SIMD, which is why we "only" get 1.5x and not 4x boost.)
The body type system has been challenging for us to implement and create content for, requiring refactoring and a lot of iterations on the content. We're happy to say we finally have a proof-of-concept for the entire process - from authoring and integration to being able to browse and apply these body types in the editor. From the app's point of view, the body type system is essentially fully implemented - all that's left to do is create content.
The body type refactoring was finished before the content was complete, so while dogson has been busy iterating on the content, I've been implementing other features in the meantime. Among those is support for the importing of skinned meshes and JPG textures. As it turns out, JPG textures actually look totally OK, which has made us more confident in implementing purely texture based layer types, offering you even more opportunities as a user. (Size would otherwise be an issue for other image formats.)
Detail textures is another feature that is now fully implemented, allowing you to define the "feel" of the surface for your characters. This will be super handy for things like snake scales.
Bone-scaling and GPU raycaster optimization are two other things that have received our attention.
These past months have felt like a huge crunch and we're quite exhausted. Especially this last week has been absolutely insane. We're happy that we finally seem to have figured out all the steps involving body types - from creation to integration and implementation. But there's still much left to do. In the coming weeks, we will continue working on making the universal mesh as adaptable as possible, as well as creating and integrating new body types and parts. It's all shaping up and we're getting very close to a first release! As far as features are concerned, there's only a handful left to implement.
We hope you have enjoyed this somewhat lengthy update. Props to you if you read through the whole thing!
With all that said, we wish you all a nice weekend!
All the best.
- Yiffalicious crew