Baking soft bodies to object matrix in 2.5

Just want to let you know.
I was working on a fusion … transition to get any diffuse point cloud motion back to a ‘low parameter scale’ …
finally succeeded in prof of concept … see file
SB2_5_crop_2_0_fix.blend (112 KB)
which contains a python script cropping efforts to proof.
As you can bake a soft body to ‘Empty’ keeping as much information as possible.
Um – that is 2.5 SVN … but your 2.5 may work as well …

Well python has changed a lot … works on 260.4 here
Update to 2.6SB2_6_crop_fix.blend (108 KB)

Bump up to 2.6
and fix + enable noisy


#push the 'run script' button to 'bake' .. run the animation to see :)
#
# bakes soft body motion to anything derived from Object
# names hard coded for now 
# some pythoneer will write a UI for that
#
#
# beside it is a demo for the power and limits 
# of vcloud_estimate_transform()
# used in SB_estimate_transform() 
#
#AND YES it suffers "the rotation flip" ... i think you are too smart not knowing how to resolve that :)
#

import bpy


class crop_softbody:
    # noisy1 is pretty much a debug optiion .. to see what goes wrong
    # fix for 2.6x
    target_name="you"
    sourec_name="suck"
    first_frame=0
    last_frame=0
    inc_frame=1
    def noisy1(self,ob):
      print("noisy1 *Begin************ ") 
      print("noisy1 tell you everthing you don't want to know ")   
      sb= ob.soft_body
      if sb:
       print("sb.location_mass_center:")
       print(sb.location_mass_center)
    
       print("ob.location:")
       print(ob.location)
        
       print("sb.rotation_estimate:")
       print(sb.rotation_estimate)
    
       print("sb.scale_estimate:")
       print(sb.scale_estimate)
    
       print("euler:")
       euler=sb.rotation_estimate.to_euler() 
       print(euler)
    
       print("scale:")
       scale=sb.scale_estimate.to_scale()
       print(scale)
      print("noisy1 *End*********** ") 
    
    
    def estimated_to_animato(self,source, target):
      sb= source.soft_body
      if sb:
        if target.rotation_mode in ["XYZ","XZY","YXZ","YZX","ZXY","ZYX"]:
        #ugly direct copy to object matrix, not sure if that will work in future ??
          for i in range(0,3):
            for j in range(0,3):
              target.matrix_local[i][j] = sb.rotation_estimate[i][j]
          #not sure if that works with all euler modes ?? 
          #target.rotation_euler= sb.lrot.toEuler() 
        if target.rotation_mode in ["QUATERNION"]:
          target.rotation_quaternion= sb.rotation_estimate.toQuat() 
        
    
        target.location= sb.location_mass_center
        target.scale=sb.scale_estimate.to_scale()
      else:
        print("object is not soft_body")
    
    def _add_key(self,target):
        if target.rotation_mode in ["QUATERNION"]: 
           target.keyframe_insert("rotation_quaternion")
        if target.rotation_mode in ["XYZ","XZY","YXZ","YZX","ZXY","ZYX"]: 
           target.keyframe_insert("rotation_euler")
        target.keyframe_insert("location")
        target.keyframe_insert("scale")
    
    def _add_with_increment(self,frame_inc):
     t=bpy.context.scene.objects[self.target_name]
     s= bpy.context.scene.objects[self.source_name]
     if (s and t):
      if s.soft_body.use_estimate_matrix: 
       #uncomment noisy1 .. if there are doubts on the matrix returned 	
       #self.noisy1(s)
       self.estimated_to_animato(s,t)
       self._add_key(t)
       bpy.context.scene.frame_set(bpy.context.scene.frame_current +frame_inc)
       return (0)
      else:
       print("Source has estimate_matrix turned off")
       return (1)
    
    def _bake_v001(self):
       print("SB bake first frame",self.first_frame,"last frame",self.last_frame,"inc",self.inc_frame) 
       print ("target name:",self.target_name,"source name:",self.source_name) 
       if (self.first_frame <= self.last_frame):  
        frames_to_go = self.last_frame - self.first_frame
        bpy.context.scene.frame_set(self.first_frame) 
        actual = self.first_frame 
        while (actual < self.last_frame):
         error = self._add_with_increment(self.inc_frame)
         if(error):
          print("Error in bake")
          return (-actual)
         actual += self.inc_frame
    
       return (actual)
    def debugoutparams(self):
        print ("target name",self.target_name) 
        print ("source name",self.source_name) 
        print ("first_frame ",self.first_frame) 
        print ("last_frame ",self.last_frame) 
        print ("inc_frame ",self.inc_frame) 
        
         


#needs UI to set source/target/increment  ...
#so for testing 
#make class instance
crsb = crop_softbody()
#set up 
crsb.target_name= "XYZ_Mesh"
crsb.source_name= "Cube"
crsb.first_frame  = 0 
crsb.last_frame  = 300 
crsb.inc_frame =1
#crsb.inc_frame >1  works fine too but needs extra care for angle flips

#crsb.debugoutparams()

#finally call it
print("running SB_to_Object bake ")
#run bake
crsb._bake_v001()

# might as well loop over frames ...
# deprecated tesing .. still
#error = crsb._add_with_increment(1) 
#if(error):
#   print("Error")
	
   

just by the way … for coders …
the function ‘vcloud_estimate_transform()’ used here can be uses to track any set of points :slight_smile:
it might be exposed to Py_api with care