Maybe it would be better to post this in a Blender forum, but I could imagine people having encounterd the same issue before, when trying to use Blender’s shapekeys with UE4.
I’m on Blender 2.8 beta currently and ideally would like to keep it that way if it’s possible at all.
Basically, Blender doesn’t allow to apply any modifiers on meshes that have any shape keys (aka morph targets). Now I have a low-poly mesh with a subdivision surface modifier and I’m in the process of adding some shape keys. Ideally, I don’t want to apply the subdivision surface modifier, it’s just way easier in this instance to change stuff on the low-poly mesh, including adding shape keys. Usually I would just check “apply modifiers” in the fbx export options, but while I get my subdivision surface modifier applied that way, no shape keys are exported. The apply modifiers option states that no shape keys are exported when checked.
I’m going for a comic-esque style, so I don’t need all that many details, I just need the mesh to look decently smooth and be easy to work with. The subdivision surface modifier is pretty ideal for my character.
Are there any good solutions except applying the modifier and redoing the shape keys every time I need to export?
I did find a plugin somewhere for a way older version of Blender that I think had an option to apply modifiers with shapekeys. Something like that would be an option, I would just have to use this option every time I export the fbx again and undo it afterwards. I wasn’t able to find anything for recent Blender versions though.
I haven’t had a chance to actually try this out yet. But I think the way is to use python to duplicate your mesh, Delete the shapekeys on one copy, apply any modifiers and then copying back the shapekeys from the duplicate.
I’ll have to take a look at Blender’s Python API then. Hopefully the shapekeys of the highpoly mesh are easily accessible somehow… I never had to delve into scripting for Blender. Maybe Blender even allows to do this automatically before exporting and to undo it afterwards. That seems like a starting point though, thank you very much for your input. If I get it working, I’ll post the solution here.
Alright, I have something that works on my project. I can’t guarantee of course that it works with every modifier, but subdivision surface seems to be ok. After a bit of frustration I took a look at the addon ShapeKey Helpers, over at https://www.blendernation.com/2016/0…pekey-helpers/
While shapekey helpers is outdated currently, it was pretty useful to get an idea of how to do this. The process is a bit slow though unfortunately.
I’ll probably make this more convenient in the future but for now this is how it works (in Blender 2.8 beta) if anybody comes across this thread with the same problem: edit: 0.5. I made it into an easy to install addon you can install (if you use this, skip steps 1 and 2): https://mega.nz/#!kZknXQDC!lYhUFgYnj…JXiejKMmdsRs84
1. Go to the scripting workspace, add a new file and copy the script into it:
import bpy
class ApplyWithShapeKeys(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.applywithshapekeys"
bl_label = "Apply Modifiers With Shapekeys"
def execute(self, context):
selection = bpy.context.selected_objects
for obj in selection:
if obj.type == "MESH":
# lists store temporary objects created from shapekeys
shapeInstances = ]
shapeValues = ]
# Deactivate any armature modifiers
for mod in obj.modifiers:
if mod.type == 'ARMATURE':
obj.modifiers[mod.name].show_viewport = False
for shape_key in obj.data.shape_keys.key_blocks:
# save old shapekey value to restore later. Will set to 0 temporarily
shapeValues.append(shape_key.value)
shape_key.value = 0.0
i = 0
for shape_key in obj.data.shape_keys.key_blocks:
# ignore basis shapekey
if i != 0:
# make sure only relevant object is selected and active
bpy.ops.Object.select_all(action="DESELECT")
obj.select_set(state=True)
context.view_layer.objects.active = obj
# make sure only this shape key is set to 1
shape_key.value = 1.0
# duplicate object with only one shape key active. Blender does the rest
bpy.ops.Object.duplicate(linked=False, mode="TRANSLATION")
bpy.ops.Object.convert(target="MESH")
shapeInstances.append(bpy.context.active_object)
bpy.context.object.name = shape_key.name
bpy.ops.Object.select_all(action="DESELECT")
obj.select_set(state=True)
context.view_layer.objects.active = obj
shape_key.value = 0.0
i = i + 1
context.view_layer.objects.active = obj
# create final object
bpy.ops.Object.duplicate(linked=False, mode="TRANSLATION")
newobj = bpy.context.active_object
newobj.name = obj.name + "_APPLIED"
# clear all old shapekeys from new object
newobj.shape_key_clear()
# apply all modifiers on new object
for mod in newobj.modifiers:
if mod.name != "Armature":
bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name)
# iterate all temporary saved shapekey objects, select only that and the final object and join them
for shapeInstance in shapeInstances:
bpy.ops.object.select_all(action="DESELECT")
newobj.select_set(state=True)
shapeInstance.select_set(state=True)
context.view_layer.objects.active = newobj
result = bpy.ops.object.join_shapes()
# reset old shape key values
i = 0
for shape_key in newobj.data.shape_keys.key_blocks:
if i != 0:
shape_key.value = shapeValues*
i = i + 1
# reset old shape key values
i = 0
for shape_key in obj.data.shape_keys.key_blocks:
if i != 0:
shape_key.value = shapeValues*
i = i + 1
# delete temporary objects
bpy.ops.Object.select_all(action="DESELECT")
for shapeInstance in shapeInstances:
shapeInstance.select_set(state=True)
bpy.ops.object.delete(use_global=False)
# redeactivate armature modifiers
for mod in obj.modifiers:
if mod.type == 'ARMATURE':
obj.modifiers[mod.name].show_viewport = True
for mod in newobj.modifiers:
if mod.type == 'ARMATURE':
newobj.modifiers[mod.name].show_viewport = True
return {"FINISHED"}
def register():
bpy.utils.register_class(ApplyWithShapeKeys)
def unregister():
bpy.utils.unregister_class(ApplyWithShapeKeys)
if __name__ == "__main__":
register()
2. rightclick in the text window and run the script. Running the script just adds an entry to the search window (F3), so you only have to run it once every time you restart Blender. I found this to be a bit more convenient because you don’t have to switch to the scripting workspace or open a text window every time you want to export.
3. select the objects you want to export and go to object mode
4. press F3 and search for “Apply Modifiers With Shapekeys”, and select the entry
5. you get a new object called <yourObjectName>_APPLIED that should have all modifiers applied but with retained shape keys and armature. This is the object you want to export. You can delete it afterwards.
THANK YOU. This is unbelievably helpful! I was worried I wouldn’t be able to use the mesh I was working on (And had already created a bunch of shapekeys for) because I didn’t think to apply the subdiv modifier. All the other scripts wouldn’t work in 2.8 and I was getting really worried. Thank you for this!