Cropping softbody motion to any object in 2.5

Just wanted to share current progress …

Purpose:
Crop a reduced, that is boiled down to
Location Rotation Scale
version of the movement a soft body on simulation does .

Why this?

  • reducing data ( if you are lucky … you can have data using 1/100 or less memory, disk space … even better, because it it is baked hours of simulation time )
  • explore how ‘real’ objects move … to give an estimate for ‘believable’ objects in space and time

# 
# 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 :)
#
class crop_softbody:
    # noisy1 is pretty much a debug optiion .. to see what goes wrong
    target_name="you"
    sourec_name="suck"
    first_frame=0
    last_frame=0
    inc_frame=1
    def noisy1(ob):
      print("noisy1 **************** ") 
      print("noisy1 tell you everthing you don't want to know ")   
      sb= ob.soft_body
      if sb:
       print("lcom:")
       print(sb.lcom)
    
       print("ob.location:")
       print(ob.location)
        
       print("lrot:")
       print(sb.lrot)
    
       print("lscale:")
       print(sb.lscale)
    
       print("euler:")
       euler=sb.lrot.toEuler() 
       print(euler)
    
       print("scale:")
       scale=sb.lscale.scalePart() 
       print(scale)
      print("noisy1 **************** ") 
    
    
    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[i][j] = sb.lrot[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.lrot.toQuat() 
        
    
        target.location= sb.lcom
        target.scale=sb.lscale.scale_part()
      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.estimate_matrix: 
       #uncomment noisy1 .. if there are doubts on the matrix returned     
       #noisy1(s)
       self.estimated_to_animato(s,t)
       self._add_key(t)
       bpy.context.scene.set_frame(bpy.context.scene.current_frame +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.set_frame(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.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")

/me grumbles … 'd like to post the entire test file here …
and please … read the comments in the file … just in case they may answer some of your questions

well…
and there was a change on SVN at Revision: 26239
if target.scale=sb.lscale.scale_part() does not work for you
try target.scale=sb.lscale.scalePart()
complete test file is there (really bad stunt … sorry )
http://blenderartists.org/forum/showthread.php?p=1563693#post1563693

I have changed you srcipt to work well in Blender 2.55 beta:

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 :slight_smile:

import bpy

class crop_softbody:
# noisy1 is pretty much a debug optiion … to see what goes wrong
target_name=“you”
sourec_name=“suck”
first_frame=0
last_frame=0
inc_frame=1
def noisy1(ob):
print("noisy1 **************** ")
print("noisy1 tell you everthing you don’t want to know ")
sb= ob.soft_body
if sb:
print(“lcom:”)
print(sb.lcom)

   print("ob.location:")
   print(ob.location)
    
   print("lrot:")
   print(sb.lrot)

   print("lscale:")
   print(sb.lscale)

   print("euler:")
   euler=sb.lrot.toEuler() 
   print(euler)

   print("scale:")
   scale=sb.lscale.scalePart() 
   print(scale)
  print("noisy1 **************** ") 


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_world[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.scale_part()
  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     
   #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.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”)