Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Baking Sverchok animation to Shape Keys (Script) #2390

Closed
vicdoval opened this issue Mar 17, 2019 · 15 comments
Closed

Baking Sverchok animation to Shape Keys (Script) #2390

vicdoval opened this issue Mar 17, 2019 · 15 comments

Comments

@vicdoval
Copy link
Collaborator

vicdoval commented Mar 17, 2019

I wanted to share this little script for Blender 2.79 to bake Sverchok animations to Shape Keys
This allows to have smooth motion blur, very fast viewport animation, sending it to a render farm or to render the output animation it in 2.8
It works by creating a copy of the selected object and adding every frame a new keyframed Shape Key

To use it just paste it in a text-block, select the original object and hit 'Run the script'

import bpy

original_name = bpy.context.active_object.name
first_frame = bpy.context.scene.frame_start 
end_frame = bpy.context.scene.frame_end 
bpy.context.scene.frame_current = first_frame
bpy.ops.node.sverchok_update_all()
bpy.ops.object.duplicate()
bpy.context.active_object.name = 'Baked_' + original_name
bpy.context.active_object.data.name = 'Baked_' + original_name
bpy.data.objects[original_name].select = True
bpy.ops.object.join_shapes()
for actFrame in range(first_frame+1, end_frame+1):
    bpy.context.scene.frame_current = actFrame
    bpy.ops.node.sverchok_update_all()

    bpy.ops.object.join_shapes()
    bpy.context.object.active_shape_key_index = actFrame-1
    keys_name = bpy.context.object.data.shape_keys.name
    k = bpy.data.shape_keys[keys_name]
    k.key_blocks[-1].value = 1
    name = bpy.data.shape_keys[keys_name].key_blocks[-1].name
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name +'"].value')
    k.key_blocks[-2].value = 0
    name_p = bpy.data.shape_keys[keys_name].key_blocks[-2].name
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name_p +'"].value')
    bpy.context.scene.frame_current = actFrame-1
    k.key_blocks[-1].value = 0
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name +'"].value')

(It was asked here #469 but I opened a new issue to keep it cleaner)

Maybe it could became one sverchok operator but by now here is the script :)

@zeffii
Copy link
Collaborator

zeffii commented Mar 18, 2019

i want to add my support for this approach to animation via sverchok. Using sverchok as only part of the process allows you to control a lot more, even animate properties that don't have socket-input.

@nortikin
Copy link
Owner

nortikin commented Mar 24, 2019

why not modify this
https://github.com/nortikin/sverchok/blob/master/node_scripts/SNLite_templates/shape_key_bake.py
It can be as node to bake one object

@zeffii
Copy link
Collaborator

zeffii commented May 15, 2019

@vicdoval reckon you could assemble a small script that does, something like

for frame in range(30, 60):
    # set desired render file name and location ( if it can't be done automatically )
    # render()

@vicdoval
Copy link
Collaborator Author

vicdoval commented May 15, 2019

Like this?
The bad thing is that it does not report to the ui the render progress.
It has been done in 2.79, when i try it in 2.8 does not save the file but i does not report any errors...

import bpy 
file_name = '/tmp\\imtest2\\'

start_frame = 10
end_frame =14

for act_frame in range(start_frame, end_frame + 1):
    bpy.context.scene.frame_current = act_frame
    bpy.ops.node.sverchok_update_all()
    bpy.ops.render.render()
    this_file = file_name + str(act_frame).zfill(4) +'.png'
    bpy.data.images["Render Result"].save_render(filepath=this_file)
    print(act_frame)

print ('done')

@zeffii
Copy link
Collaborator

zeffii commented May 15, 2019

hmmm.. i think maybe the solution is to add an event handler in the script (post_render) to do the save_render(file_path=.... ) stuff..

i suspect when you set the frame_current, that would already trigger sverchok_update_all()

@vicdoval
Copy link
Collaborator Author

I will try to check the handler idea

i suspect when you set the frame_current, that would already trigger sverchok_update_all()

I thought so too, but if you update the frame from a script it does not update the nodetree

@vicdoval
Copy link
Collaborator Author

the 2.8 version of the "baking animation to shapekeys" script:

import bpy

original_name = bpy.context.active_object.name
first_frame = bpy.context.scene.frame_start 
end_frame = bpy.context.scene.frame_end 
bpy.context.scene.frame_current = first_frame
bpy.ops.node.sverchok_update_all()
bpy.ops.object.duplicate()
bpy.context.active_object.name = 'Baked_' + original_name
bpy.context.active_object.data.name = 'Baked_' + original_name
bpy.data.objects[original_name].select_set(state=True)
bpy.ops.object.join_shapes()
for actFrame in range(first_frame+1, end_frame+1):
    bpy.context.scene.frame_current = actFrame
    bpy.ops.node.sverchok_update_all()

    bpy.ops.object.join_shapes()
    bpy.context.object.active_shape_key_index = actFrame-1
    keys_name = bpy.context.object.data.shape_keys.name
    k = bpy.data.shape_keys[keys_name]
    k.key_blocks[-1].value = 1
    name = bpy.data.shape_keys[keys_name].key_blocks[-1].name
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name +'"].value')
    k.key_blocks[-2].value = 0
    name_p = bpy.data.shape_keys[keys_name].key_blocks[-2].name
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name_p +'"].value')
    bpy.context.scene.frame_current = actFrame-1
    k.key_blocks[-1].value = 0
    bpy.data.shape_keys[keys_name].keyframe_insert(data_path='key_blocks["'+ name +'"].value')

@zeffii
Copy link
Collaborator

zeffii commented May 15, 2019

I thought so too, but if you update the frame from a script it does not update the nodetree

ok. hmmmm.

@vicdoval
Copy link
Collaborator Author

this would work rendering n frames in the 2.8

import bpy 
file_path = '/tmp\\imtest8\\'

start_frame = 10
end_frame =14

for act_frame in range(start_frame, end_frame + 1):
    bpy.context.scene.frame_current = act_frame
    bpy.ops.node.sverchok_update_all()
    bpy.context.scene.render.filepath = file_path + str(act_frame).zfill(4) +'.png'
    bpy.ops.render.render(write_still=True)
    print(act_frame)

print ('done')

@javismiles
Copy link

javismiles commented May 15, 2019

@vicdoval yes this works thank you ;)

@enzyme69
Copy link
Collaborator

enzyme69 commented May 16, 2019

@nortikin Your Script Node Lite solution is interesting but not sure how it would work? I tried it does not work.

I have weird method at some point, basically passing the data into Shapekeys... via Object ID.
https://www.youtube.com/watch?v=eIPRhKzJ6fM

It's like Victor baking data into shapekeys.

UPDATE: Ok wait maybe not above one, but I did "propose" or asking question about using Shapekeys as "Intermediate Object"....

This one:
https://www.youtube.com/watch?v=OBx1JmbIfrY

ANYWAYS... I think @vicdoval solution is simplest.

@nortikin
Copy link
Owner

@nortikin How to use this node? about (shape_key_bake.py)。I hope you can give me an example to understand it

update sverchok - collections links added
link nodes:
изображение
choose frame and define parameters:
изображение
change active to 1 and back to 0 to deactivate after:
изображение

@nortikin
Copy link
Owner

nortikin commented Feb 3, 2021

@nortikin use blender2.91.No bake shape keys,what should I do to bake shape keys

upgrade sverchok and add SNL shape key bake again from scratch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants
@zeffii @javismiles @enzyme69 @nortikin @vicdoval @Durman and others