I wrote script that create a custom deformer to a mesh over time. Using python is very slow so I'd like to be able to bake the position of my vertices deformed over time and be able to play it back at a better frame rate.
So, I'm trying to find a good solution to bake the position of vertices of a mesh over time like the physics/rigid body system in Blender.
I guess there is no direct access to create my own internal point cache (but if somebody knows how to do that I'm interested) so what I plan to do is to have a list that store the position of my vertices for a range of frames. As I'd like to be able to cancel while baking (using 'ESC'), I guess using a modal operator is the best way to go but i can't get my head around how to set up the modal operator particularly with the return values.
Here is what I get so far:
import bpy
##some code##
##store global
class G:
pass
## bake deformer
class JDEF_BAKE(bpy.types.Operator):
bl_idname = "wm.bake_jdef"
bl_label = "Bake deformer"
bl_options = {'UNDO', 'REGISTER'}
_frame = 1
_bake_mat = []
_index = 0
obj = None
_endframe = 0
def __init__(self):
self.obj = bpy.context.object
G.baked=False
G.baking=True
self._frame = bpy.context.scene.frame_start
G.ls_bake=[]
self._bake_mat = [0.0,0.0,0.0]*len(self.obj.data.vertices)
self._endframe = bpy.context.scene.frame_end
def __del__(self):
G.baked=True
G.baking=False
def execute(self,context):
context.window_manager.modal_handler_add(self)
context.scene.frame_current = self._frame
JDEF(context) #execute some function to move the vertices
self.obj.data.vertices.foreach_get('co',self._bake_mat)
G.ls_bake.append([self._frame,self._bake_mat])
self._frame += 1
return {'RUNNING_MODAL'}
## bake deformer
def modal(self,context,event):
if (self._frame <= self._endframe):
self.execute(context)
elif (self._frame > self._endframe):
return {'FINISHED'}
elif event.type=='ESC':
G.baked=True
G.baking=False
G.ls_bake.clear()
return {'CANCELLED'}
return {'PASS_THROUGH'}
So this doesn't seems to work and blender freezes each time I launch the operator. It doesn't come from the function JDEF because even if I comment it blender will still froze. I think I'm not handling the return values and execute/modal functions the right way.
Sorry if the bad code make you tear blood but I'm still a learning noob :D
Thank you for your help.
__init__(self)
toinvoke(self,context,event)
. Invoke is what is called when the modal is invoked. Inside that fce move thecontext.window_manager.modal_handler_add(self)
- you want to run that only once. Erase theexecute
and move it undermodal
. Execute don't return Running modal and you are using it only there under modal. If this works for you I will post it as an answer, cant test your code. $\endgroup$__init__(self)
def then in comparison of theinvoke()
? $\endgroup$