Search Unity

[Solved] Fallout 4: automatic "fatness"

Discussion in 'General Discussion' started by joshcamas, Mar 6, 2018.

  1. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    According to https://wiki.nexusmods.com/index.php/Creating_an_armour_for_Fallout_4._Part1, armor meshes no longer need 2 types of meshes to blend between to create a fat/skinny body, like skyrim did.

    In other words, the engine itself somehow generates a fat or skinny or muscled body automatically!

    On the technical side, does anyone know how this is done? I cannot find any information on the topic.

    Even with skyrim, how does having 2 meshes (normal vs fat) allow the engine to modify certain areas of the body, such as leg length and arm fatness etc?

    For skyrim, (which used two meshes, one fat and one "normal") my only guess for is that the engine knows what a "leg" is, since it has the weights for the armature. It then does some quick maths to somehow blend only that part,to whatever ratio they want.

    But for fallout 4, my only guess is that perhaps for every body mesh there are a few meshes (muscular, fat, skinny, normal) and they use that data to somehow figure out how to modify the armor.... Otherwise? I have no idea!

    Since my game is also a game with lots of armor and races, I'm really not wanting to have the same body size for everyone, and having to add blend shapes to every mesh sounds tedious. I'd rather spend many hours programming something than doing that

    Thank you so much!

    Josh
     
  2. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,205
    A starting point for the information you want to research is summed up in the wiki article itself.
    Character meshes use bones for animation but they need weights assigned to them to know how to properly manipulate the mesh. You're not restricted to just translation and rotation though. You can scale them too. By scaling certain bones by certain amounts you can get different body proportions.

    Clothing is handled the same way. It's effectively just another part of the body to the game.
     
    Last edited: Mar 6, 2018
    joshcamas and theANMATOR2b like this.
  3. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,573
    The cheapest way to make characters fatter/thinner is to scale armor bones.

    Or, to be more precise... to the actual skeleton the characters use, attache secondary layers of "adjustment" bones and bind armor to those rather than binding them to skeleton itself.

    Once character is in the game you'll be able to adjust thinness of individual body parts, by scaling adjustment bones.

    A hirerarchy could go like this:
    Code (csharp):
    1.  
    2. Hip
    3.     HipTweak
    4.     Spine0
    5.         Spine0Tweak
    6.         Spine1
    7.             Spine1Tweak
    8.             LShoulder
    9.                 LShoulderTweak          
    10.                 LUpperArm:
    11.                     LUpperarmTweak
    12.                     LLowerArm
    13.                         LLowerArmTweak
    14.                         LHand
    15.  
    (One Ident Level --> On level of depth in hierarchy)
    IIRC Uma had something similar, actually.

    The reason for having tweak bones, is if you scale an upper arm bone, directly, it'll affect every single bone in the hierarchy below it.
    If you scale a "tweak" bone, it will not affect anything else.

    OF course, this kind of method is quite cheap, and you'll achieve higher quality if you use blendshapes.... but it'll be more expensive in a different way.
     
  4. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Interesting! Does unity support this with the humanoid system? Since I seem to remember having lots of problems with having custom bones...
     
  5. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    Take a look at UMA. It uses bones to scale up and down and you can that either through code or through the UMA system. It is free as well and currently developed by a team of volunteers. I think it would be possible to change body size in run time using UMA. I am not a coder though....but it seems it would work.
     
    joshcamas and Ryiah like this.
  6. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,573
    Yes, body size is supported, however, UMA can be incredibly tricky to use with your own meshes. (Unless something changed)

    UMA, as far as I know, performs body size adjustment in the way I described here. Except it generates "tweak" bones for the whole body via programming means.
     
    joshcamas likes this.
  7. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Awesome! Sounds like something I could program myself, I'll check out how they do it!
     
    Teila likes this.
  8. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Well, UMA looks very powerful, but being myself, I have decided to do this myself. First off, I have put my tweak bones into the actual FBX, instead of writing a script. This is simply to give more power to my modelers, and since all of our assets are made by us this isn't a problem. In fact, most tweak bones will be generated with a nice little python script (all it does is duplicate certain bones, change their parents, and rename them), so that's cool.

    One thing I've noticed is simply scaling a bone usually doesn't work - instead, you want to locally scale certain directions (so for example, x and z but not y). This makes things look a lot better.

    Yay! Thank you guys, this sounds totally doable :))
     
  9. BIGTIMEMASTER

    BIGTIMEMASTER

    Joined:
    Jun 1, 2017
    Posts:
    5,181
    I have no idea if this would be a viable alternative, but something like a displacement map could be another route?

    It's pretty foreign and mysterious to me, but I was messing around and realized I could use my height maps to essentially scale my meshes outwards. Results were weird, but I think if you approached it with a plan you could make a texture channel that would cleanly inflate the mesh in a believable way.

    I have no clue if that is better or worse than some kind of bone scaling system, just a thought.
     
    joshcamas likes this.
  10. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Sounds kinda cool! I think I'm personally going to go the bone route, but displacement maps certainly sounds like a possibility, that could actually create some interesting results!
     
  11. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Well, looks like simply adding some tweak bones works! Here is an example, and also here is a little python script snippet I made that duplicates rigify's ORG bones and turns them into TWEAK bones!




    Code (csharp):
    1.  
    2. class TweakGenerator_Panel(bpy.types.Panel):
    3.     bl_label = "Tweak Generator"
    4.     bl_space_type = "PROPERTIES"
    5.     bl_region_type = "WINDOW"
    6.     bl_context = "data"
    7.     bl_options = {'DEFAULT_CLOSED'}
    8.  
    9.  
    10.     #Simply checks if armature is a rigify armature by checking if it has a
    11.     #ORG-spine bone
    12.     @classmethod
    13.     def poll(self, context):
    14.         if context.object and context.object.type == 'ARMATURE':
    15.             try:
    16.                 oneBone = bpy.context.object.data.bones["ORG-spine"]
    17.                 return True
    18.             except:
    19.                 return False
    20.    
    21.     def draw(self, context):
    22.         self.layout.prop(context.object,"overwrite_tweak")
    23.         self.layout.operator("ardenfall.gentweak")      
    24.        
    25.  
    26. class UnityMecanim_GenerateTweakBones(bpy.types.Operator):
    27.     bl_idname = "ardenfall.gentweak"
    28.     bl_label = "Generate Tweak Bones"
    29.  
    30.  
    31.     def execute(self, context):
    32.      
    33.         bpy.ops.object.mode_set(mode='EDIT')
    34.      
    35.         ob = bpy.context.object
    36.         porg = re.compile('ORG-*')
    37.      
    38.         #Loop through all org bones, and replicate
    39.         for object in ob.data.edit_bones:
    40.             if porg.match(object.name):
    41.                 #new name of new bone
    42.                 newname = "TWEAK-" + object.name[4:]
    43.              
    44.                 #Check if bone already exists. If overwrite is disabled,
    45.                 #then skip this bone.
    46.                 if newname in ob.data.edit_bones:
    47.                     if(bpy.types.Object.overwrite_tweak == False):
    48.                         continue
    49.                     #Otherwise we're just modifying the bone we found
    50.                     newbone = ob.data.edit_bones[newname]
    51.                 else:
    52.                     #Create new bone
    53.                     newbone = ob.data.edit_bones.new(newname)
    54.              
    55.                 #The parent is the current org bone
    56.                 newbone.parent = ob.data.edit_bones[object.name]
    57.              
    58.                 #Replicate the position of the org bone
    59.                 newbone.head = object.head
    60.                 newbone.tail = object.tail
    61.              
    62.                 #Move to layer 27
    63.                 newbone.layers[27] = True
    64.              
    65.                 #Enable deform
    66.                 newbone.use_deform = True
    67.      
    68.         bpy.ops.object.mode_set(mode='OBJECT')
    69.         return{'FINISHED'}
    70.  
    71. def register():
    72.     bpy.types.Object.overwrite_tweak = bpy.props.BoolProperty(name="Overwrite Tweak", default=False)
    73.     bpy.utils.register_class(UnityMecanim_GenerateTweakBones)
    74.    
    75.    
    76. def unregister():
    77.     bpy.utils.unregister_class(TweakGenerator_Panel)
    78.     del bpy.types.Object.overwrite_tweak
    79.    
    80.  
    Note: I pair this with https://github.com/trynyty/Rigify_DeformBones to automatically convert a rigify rig into a rig that can be utilized as a humanoid unity rig. (Basically disables dorming on DEF, MECH, and a few specific ORG bones). Just be sure to modify it to also export TWEAK bones as well!
     
  12. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,573
    Interesting.

    It reminded me that I once thought about making a better rigify skeleton template more suitable for unity - because in the latest rigify update the default skeleton is too complicated and has "unwelcome" bones.

    Never got around doing that.
     
    joshcamas likes this.
  13. MrArcher

    MrArcher

    Joined:
    Feb 27, 2014
    Posts:
    106
    So I've been poking around a bit with displacement maps over the last week. The displacement code itself is easy to do from the shader's vertex function:

    Code (ShaderLab):
    1.  
    2. fixed4 displacementMap = tex2Dlod(_OffsetTex, fixed4(v.texcoord, 0,0));
    3. v.vertex.xyz += (v.normal * (displacementMap.rgb - 0.5)) * _ScaleFactor * displacementMap.a;
    4.  
    Then your shader uses the texture's four channels to offset the vertices relative to their local normal - red for x, green for y, blue for z and alpha for scale.

    I think the key thing is creating a way to bake one down from a different mesh. Never got too far with this particular tech demo, but it wouldn't be too difficult to compare one mesh's verts to another and bake the difference into a texture.
     
    joshcamas likes this.
  14. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,278
    Ahh yes. I'm currently using the older rigify system.

    I'm working on a converter based on https://github.com/trynyty/Rigify_DeformBones's, I guess I can release it when it's done!

    I personally ADORE both blender and Unity because of how powerful their API's are to make tools. I always felt like that was a weakness of UE4, I know they sorta supported it but not many people did it.