4
$\begingroup$

I have been creating a dragon model lately (it might come familiar to someone) and I've done a lot of work so far, I've also spent alot of time with creating shape keys for my eye. However, I see now that I have forgot to apply the subdivision surface modifier for my eye and when I remove the modifier it looks totally crappy.

I'm very-very confused now as I've looked help in Youtube and I've seen that almost everyone create their shape keys with subdivison surface modifier on (without having applied it earlier). I'm clueless how can this be, do they later on somehow do some kind of workaround to apply the subdivision modifier??

Am I really supposed to create shape keys for my eyelid or eyepupil when I have some crazy polycount (it's very hard to form the shapes I had previously).

I'm a bit in panic, so please pardon me. Maybe you could offer some ways to get through this :)

$\endgroup$
  • $\begingroup$ where do you want to use your (well known) dragon ? In UE ? I dont know if there is a way to export a mesh with shape keys in a good format for UE ? Have you checked all that ? $\endgroup$ – lemon Jun 28 '16 at 13:07
  • $\begingroup$ Have a try with a very simple mesh with some shape keys and a subsurf. $\endgroup$ – lemon Jun 28 '16 at 13:14
  • $\begingroup$ I truly think I have posted way too many things about my dragon project indeed.. :D UE4 seems to support this indeed. Shape keys there are called morph targets. However, I haven' t tried that earlier.. With very simple mesh, like cube, it's relatively easy to push or drag the geometry when subsurf is applied, but I have an eyelid which can' t be dragged as easily, even with proportional editing it's quite hard to get the shape I look for because there's too much geometry to handle... $\endgroup$ – TheLast_BlenderBender Jun 28 '16 at 13:30
  • $\begingroup$ FYI. I dont have UE, but I did some tests exporting and reimporting a simple object with both shape keys and subsurf. I did it in obj, and dae. Each time the result was bad : the reimported object was not good. I dont know if it is to considerer as "bad news" for you... but to be totally sure, you should import some simple mesh to UE and test it. $\endgroup$ – lemon Jun 28 '16 at 14:47
  • $\begingroup$ There is a workaround here blender.stackexchange.com/questions/9007/…. This is the same principle for subsurf and array. It works, I have tested it. $\endgroup$ – lemon Jun 28 '16 at 15:16
7
$\begingroup$

This answer comes from a previous one here Cannot Apply Array Modifier. I simply add some more details in the explanation and a way to do it for all shape keys at once.

Here is a simple shape, which has a subsurface modifier and shape keys :

enter image description here

enter image description here

Make one copy of your initial object for each shape key and set for each the shape key to "1" :

enter image description here

Select this copies and Alt + C and "mesh from curve/..." :

enter image description here

The modifiers are applied and the shape keys too (these objects now have no shape keys or subsurf modifiers).

Make another copy of your original object, remove the shape keys from it, and apply the subsurf modifier :

enter image description here

Now select the "shape keyed" objects, and the last copy we just made (in this order), and in the shape key panel use "join as shapes" :

enter image description here

We now have the final object, with the subsurface modifier applied and the shape keys available : enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks alot for this wonderful explanation. I don' t know what I would've done without your help (probably created all those 10 shape keys again...). Thanks.. man once again :) $\endgroup$ – TheLast_BlenderBender Jun 28 '16 at 18:31
  • 1
    $\begingroup$ you are welcome. I hope to see some pic of your dragon live : ) $\endgroup$ – lemon Jun 28 '16 at 18:32
  • $\begingroup$ but anyway.. have a check about how will UE accept shape keys (after an export from Blender) $\endgroup$ – lemon Jun 28 '16 at 18:35
  • $\begingroup$ Yep. I'll let you know when I finally finish it... which seemingly won' t happen in near future if I keep doing those mistakes that I'm doing (but it's really good to go through all those mistakes by myself so I could understand how much pain they can cause :) ). Yup. I'm trying to get to know it better. I have quite many problems already with UE4 by understanding what can be done or what can't.. For example, today I spent the whole day trying to understand whether I should use one multi-texture for my dragon using UDIM technology or use 3 separated objects instead. $\endgroup$ – TheLast_BlenderBender Jun 29 '16 at 0:41
  • $\begingroup$ Anyways. I'll let you know when the model is ready :D $\endgroup$ – TheLast_BlenderBender Jun 29 '16 at 0:41
1
$\begingroup$

I scripted @Lemon 's answer!

the code is kinda long, but I think it is (I hope it to be) self-explanatory. Just copy the code into a new file on blender's text editor, call the text file apply_with_shape_keys.py, and then, select the object with the modifiers and shape keys, (make a backup, just in case). Now from the console execute it like this:

>>> import apply_with_shape_keys
>>> apply_with_shape_keys.super_apply_modifiers()

the script will apply all the modifiers conserving the shape keys! and will create a new object called "backup" without the modifiers applied (just in case you wanna add new shape keys in the future).

If the object has an armature, the script will explicitly not apply that modifier. Also you have to make sure that the skeleton is in the original pose, otherwise strange things will happen.

here is the code!

import bpy

def reset_shape_keys ():    
    for name, shape_key in get_active_block().items():
        shape_key.value = 0

def get_active_block ():
    block_id = bpy.context.object.active_shape_key.id_data.name
    return bpy.data.shape_keys[block_id].key_blocks

def select (selection):
    bpy.ops.object.select_all(action='DESELECT')
    selection.select = True
    bpy.context.scene.objects.active = selection

def select_last_shape_key ():
    shape_key_count = len(get_active_block().items())
    bpy.context.object.active_shape_key_index = shape_key_count - 1

def remove_shape_keys (object):
    selection = bpy.context.object
    select(object)
    shape_key_count = len(get_active_block().items())
    select_last_shape_key()
    for i in range(0, shape_key_count):
        bpy.ops.object.shape_key_remove(all=False)
    select(selection)

def apply_modifiers (object):
    selection = bpy.context.object
    select(object)

    for key, modifier in object.modifiers.items():
        if key != 'Armature':
            bpy.ops.object.modifier_apply(apply_as='DATA', modifier=key)

    select(selection)        

def super_apply_modifiers ():
    original = bpy.context.object
    bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 0), "constraint_axis":(False, False, False), "constraint_orientation":'GLOBAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})
    backup = bpy.context.object
    backup.name = 'backup'
    remove_shape_keys(original)
    apply_modifiers(original)

    for key, shape_key in get_active_block().items():
        select(backup)
        bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 0), "constraint_axis":(False, False, False), "constraint_orientation":'GLOBAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})

        meshed_shape_key = bpy.context.object
        select(meshed_shape_key)
        reset_shape_keys()
        get_active_block()[key].value = 1
        bpy.ops.object.convert(target='MESH')

        select(original)
        meshed_shape_key.select = True
        bpy.ops.object.join_shapes()
        select_last_shape_key()
        bpy.context.object.active_shape_key.name = key

        select(meshed_shape_key)
        bpy.ops.object.delete(use_global=False)
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ I've made a simple change to your code, to give the backup object a more comprehensive name instead of just "backup" by adding "_backup" to the original file name.>>>backup.name = original.name +'_backup' $\endgroup$ – Ahmed Ali Sep 15 '18 at 23:25
  • $\begingroup$ Throws error: keyword "constraint_orientation" unrecognized. :( $\endgroup$ – BuzzKirill Jun 2 at 6:09
  • $\begingroup$ what version of blender are you using? I made it a long time ago lol... are you with blender 2.8+? $\endgroup$ – Bengalaa Jul 1 at 18:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.