C4D animation via Python


#1

Hi there,

I am trying to make a simple animation consisting of moving a cube from point 1 to point 2 via Python-only. The animation will start at frame 1 and end at frame 120. The number of frames per second (FPS) is 30. The cube will be called: “MyCube” and the basic units of the model are: meters, grades and seconds.

The two states that define the cube at each frame are:

State at frame 1:

  • Position: (0,0,0)
  • Rotation: (0,0,0)
  • Size: (1,2,2)
  • Segments: (10,20,20)
  • Material: “Neon Blue”
  • Bend (Deformer):
    … Position: (0,0,0)
    … Rotation: (0,0,0) # in HPB format
    … Size: (1,2,2)
    … Mode: “Limited”
    … Strength: 45
    … Angle: 30

State at frame 120:

  • Position: (9,12,25)
  • Rotation: (45,80,120)
  • Size: (2,3,7)
  • Segments: (20,30,70)
  • Material: “Neon Red”
  • Bend (Deformer):
    … Position: (9,12,25)
    … Rotation: (45,80,120) # in HPB format
    … Size: (2,3,7)
    … Mode: “Limited”
    … Strength: 120
    … Angle: 60

For now, this is what I have already done in Cinema 4D R13…

import c4d
from c4d import gui

def main():
	fps=30
	
	cube=c4d.BaseObject(c4d.Ocube)
	cube.SetName("MyCube")
	
	cube.Message(c4d.MSG_UPDATE)
	doc.InsertObject(cube)
	
	frame=0
	doc.SetTime(c4d.BaseTime(frame,fps))
	
	cube.SetAbsPos(c4d.Vector(0,0,0))
	cube.SetAbsScale(c4d.Vector(1,1,1))
	cube.SetAbsRot(c4d.Vector(0,0,0))
	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(100,200,200)
	cube[c4d.PRIM_CUBE_SUBX]=10
	cube[c4d.PRIM_CUBE_SUBY]=20
	cube[c4d.PRIM_CUBE_SUBZ]=20
	
	c4d.CallCommand(12410)
	
	frame=120
	doc.SetTime(c4d.BaseTime(frame,fps))
	
	cube.SetAbsPos(c4d.Vector(900,120,250))
	cube.SetAbsScale(c4d.Vector(1,1,1))
	cube.SetAbsRot(c4d.Vector(0.785398,1.396263,2.094395))
	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(200,300,700)
	cube[c4d.PRIM_CUBE_SUBX]=20
	cube[c4d.PRIM_CUBE_SUBY]=30
	cube[c4d.PRIM_CUBE_SUBZ]=70
	
	c4d.CallCommand(12410)
	
	c4d.EventAdd()
	
if __name__=='__main__':
	main()

And the problem with this script is that it is not actually recording the state of each frame (frame 1 and 120). Additionally, I need to add the material and deformer into the cube at each state…

My actual work consists of making a realistic-visualization of a 80-Story Reinforced Concrete Building subjected to a set of several earthquakes (40 earthquakes in total, which means 40 animations). The simulation was performed using an external program and now I need to make a visualization of the behavior of the building using a set of data obtained from this program. The set of data is composed by thousands of numbers… so I think the straightway to make this is via a programming language. I thought in Python but I am right now stuck!..

Your help will be greatly appreciated!

Thank you.

Ricardo.


#2

The way you’re doing this. The object you want to set animation keys on needs to be active first.

import c4d
from c4d import gui

def main():
	fps=30
	cube=c4d.BaseObject(c4d.Ocube)
	cube.SetName("MyCube")
	doc.InsertObject(cube)
	cube.SetBit(c4d.BIT_ACTIVE) #Select the cube so it's active

	frame=0
	doc.SetTime(c4d.BaseTime(frame,fps))

	cube.SetAbsPos(c4d.Vector(0,0,0))
	cube.SetAbsScale(c4d.Vector(1,1,1))
	cube.SetAbsRot(c4d.Vector(0,0,0))
	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(100,200,200)
	cube[c4d.PRIM_CUBE_SUBX]=10
	cube[c4d.PRIM_CUBE_SUBY]=20
	cube[c4d.PRIM_CUBE_SUBZ]=20
	cube.Message(c4d.MSG_UPDATE)

	c4d.CallCommand(12410)

	frame=120
	doc.SetTime(c4d.BaseTime(frame,fps))

	cube.SetAbsPos(c4d.Vector(900,120,250))
	cube.SetAbsScale(c4d.Vector(1,1,1))
	cube.SetAbsRot(c4d.Vector(0.785,1.396,2.0943))
	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(200,300,700)
	cube[c4d.PRIM_CUBE_SUBX]=20
	cube[c4d.PRIM_CUBE_SUBY]=30
	cube[c4d.PRIM_CUBE_SUBZ]=70
	cube.Message(c4d.MSG_UPDATE)
	
	c4d.CallCommand(12410)
	cube.DelBit(c4d.BIT_ACTIVE) #De-Select the cube
	
	c4d.EventAdd()
	
if __name__=='__main__':
	main()

There is another way to create keys on things by creating tracks and curves for them directly instead of using the record button. But that’s a whole different kettle of fish.
You shouldn’t need to use that method for what you’re doing. But if you do eventually want to go that route. Go to the Python forum at the plugincafe.com and search for “Curves” or “Tracks”.
There’s a few threads on creating animation tracks, curves, and keys in the archives with examples to help you get started with that method. If you feel you need it.

-ScottA


#3

Dear Scott, thank you very much for both the reply and the additional information. I think I will continue using the first method proposed. But do you know how can I introduce the material and the bend deformer into the cube? This is the only thing I have not been able to find anywhere through internet. Would you help me again.

Thanks a lot for your kind of help.

Ricardo.


#4

Sorry for the delay.
I have never key framed a materials color before. So I had to teach myself how to do it.

Here is most of what you wanted in your wish list.
It only works for R13(hope that’s what you have) because FindCTrack() isn’t available in R12.
I didn’t add things like positions because the script was getting too long and complicated to post here. And you should be able to add them yourself as needed.

import c4d
 
 def main():
 	fps=30
 
 	mat = c4d.BaseMaterial(c4d.Mmaterial)   #Create a new material
 	doc.InsertMaterial(mat)				 #Insert the material into the document
 
 	cube=c4d.BaseObject(c4d.Ocube)		  #Create a new cube object
 	cube.SetName("MyCube")
 	doc.InsertObject(cube)				  #Add it to the OM
 
 	mtag = c4d.TextureTag()				 #Create a new texture tag 
 	mtag.SetMaterial(mat)				   #Link it to our new material
 	cube.InsertTag(mtag)					#Add it to the cube
 
 	bend=c4d.BaseObject(5128)					   #Bend Deformer
 	strength = c4d.DescID(c4d.DEFORMOBJECT_STRENGTH)#Creates keyframe selection 
 	bend.SetKeyframeSelection(strength, 1)		  #Adds the Keyframe Selection option
 
  #The "size" attribute on the bend deformer is a vector with three sub-attributes we need to access
 	size = c4d.DescLevel(c4d.DEFORMOBJECT_SIZE, c4d.DA_VECTOR, c4d.Obasedeform)
 	id = c4d.DescID(size)
 	bend.SetKeyframeSelection(id, True)
 	id = c4d.DescID(size, c4d.DescLevel(c4d.VECTOR_X, c4d.DA_REAL, c4d.DA_VECTOR))
 	bend.SetKeyframeSelection(id, True)
 	id = c4d.DescID(size, c4d.DescLevel(c4d.VECTOR_Y, c4d.DA_REAL, c4d.DA_VECTOR))
 	bend.SetKeyframeSelection(id, True)
 	id = c4d.DescID(size, c4d.DescLevel(c4d.VECTOR_Z, c4d.DA_REAL, c4d.DA_VECTOR))
 	bend.SetKeyframeSelection(id, True)
 
 	doc.InsertObject(bend,cube)   #Add it to the OM as a child of the cube
 	
 	cube.SetBit(c4d.BIT_ACTIVE)   #Select the cube so it's active
 	bend.SetBit(c4d.BIT_ACTIVE)   #Select the deformer so it's active   
 	
 
   #The color channel in materials is controlled by three sub attributes
   #X = Red
   #Y = Green
   #Z = Blue
   #So we need to get at each of these tracks. Or create them if they don't exist
 
 	redtrack = mat.FindCTrack(c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR,c4d.DTYPE_COLOR,0), c4d.DescLevel(c4d.VECTOR_X,c4d.DTYPE_REAL,0)))
 	if not redtrack:
 	   redtrack = c4d.CTrack(mat, c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR, c4d.DTYPE_COLOR, 0, ), c4d.DescLevel(c4d.VECTOR_X, c4d.DTYPE_REAL, 0)))
 	   mat.InsertTrackSorted(redtrack)  #Add the Red track to the material's color channel
 
 	greentrack = mat.FindCTrack(c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR,c4d.DTYPE_COLOR,0), c4d.DescLevel(c4d.VECTOR_Y,c4d.DTYPE_REAL,0)))
 	if not greentrack:
 	   greentrack = c4d.CTrack(mat, c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR, c4d.DTYPE_COLOR, 0, ), c4d.DescLevel(c4d.VECTOR_Y, c4d.DTYPE_REAL, 0)))
 	   mat.InsertTrackSorted(greentrack)  #Add the Green track to the material's color channel
 
 	bluetrack = mat.FindCTrack(c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR,c4d.DTYPE_COLOR,0), c4d.DescLevel(c4d.VECTOR_Z,c4d.DTYPE_REAL,0)))
 	if not bluetrack:
 	   bluetrack = c4d.CTrack(mat, c4d.DescID(c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR, c4d.DTYPE_COLOR, 0, ), c4d.DescLevel(c4d.VECTOR_Z, c4d.DTYPE_REAL, 0)))
 	   mat.InsertTrackSorted(bluetrack)  #Add the Blue track to the material's color channel
   ######Done with the material for now
   
   
 	frame=0
 	fps = doc.GetFps()
 
   #Edit the cube's attributes
 	cube.SetAbsPos(c4d.Vector(0,0,0))
 	cube.SetAbsScale(c4d.Vector(1,1,1))
 	cube.SetAbsRot(c4d.Vector(0,0,0))
 	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(100,200,200)
 	cube[c4d.PRIM_CUBE_SUBX]=10
 	cube[c4d.PRIM_CUBE_SUBY]=20
 	cube[c4d.PRIM_CUBE_SUBZ]=20
 	
   #Edit the deformer's attributes	
 	bend[c4d.DEFORMOBJECT_STRENGTH]= .7854
 	bend[c4d.DEFORMOBJECT_SIZE]= c4d.Vector(1,2,2)
 	
   #Add a key to each material color track	  
 	redcurve = redtrack.GetCurve()
 	redkey1 = redcurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	redkey1.SetValue(redcurve, 0)
 	
 	greencurve = greentrack.GetCurve()
 	greenkey1 = greencurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	greenkey1.SetValue(greencurve, 0)
 
 	bluecurve = bluetrack.GetCurve()
 	bluekey1 = bluecurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	bluekey1.SetValue(bluecurve, 1)
 
 	mat.Update(True, True)	   #Updates the thumbnail image	
 	cube.Message(c4d.MSG_UPDATE) #Update the material
 
 	c4d.CallCommand(12410) #Record everything now
 
 
 
 	frame=120
 	doc.SetTime(c4d.BaseTime(frame,fps))
   #Edit the cube's attributes
 	cube.SetAbsPos(c4d.Vector(900,120,250))
 	cube.SetAbsScale(c4d.Vector(1,1,1))
 	cube.SetAbsRot(c4d.Vector(0.785,1.396,2.0943))
 	cube[c4d.PRIM_CUBE_LEN]=c4d.Vector(200,300,700)
 	cube[c4d.PRIM_CUBE_SUBX]=20
 	cube[c4d.PRIM_CUBE_SUBY]=30
 	cube[c4d.PRIM_CUBE_SUBZ]=70
 	cube.Message(c4d.MSG_UPDATE)
 
   #Edit the deformer's attributes   
 	bend[c4d.DEFORMOBJECT_STRENGTH]= 2.0944
 	bend[c4d.DEFORMOBJECT_SIZE]= c4d.Vector(20,60,700)
 
   #Add a key to each material color track 
 	redcurve = redtrack.GetCurve()
 	redkey2 = redcurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	redkey2.SetValue(redcurve, 1)
 	
 	greencurve = greentrack.GetCurve()
 	greenkey2 = greencurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	greenkey2.SetValue(greencurve, 0)
 
 	bluecurve = bluetrack.GetCurve()
 	bluekey2 = bluecurve.AddKey(c4d.BaseTime(frame, fps))['key']
 	bluekey2.SetValue(bluecurve, 0)
 
 	mat.Update(True, True)		#Updates the thumbnail image	
 	cube.Message(c4d.MSG_UPDATE)  #Update the material
 	
 	c4d.CallCommand(12410)	  #Record everything now
 	cube.DelBit(c4d.BIT_ACTIVE) #De-Select the cube
 	bend.DelBit(c4d.BIT_ACTIVE) #De-Select the bend deformer
 	c4d.CallCommand(12501)	  #Goto Start
 	
 	c4d.EventAdd()
 	
 if __name__=='__main__':
 	main()

While this is a very simple task you’re doing. The code is bit complex looking because you’re dealing with lots of those little Ctrl+click dots to create the animations.
Any time you deal with those little dots. The code is a bit ugly and intimidating looking compared to other (neater looking) code we normally write.

Note- The forum is probably going to mess up the code spacing. So you’ll probably need to fix that.

-ScottA


#5

Dear Scott, thanks a lot for the time you are spending on helping me.

I just took your script and run it. But an error has appeared.

Do you know what the error means? Do I need to import a module?

Thank you.

P.S. I am using Cinema 4D Broadcast R13.051 on Mac OS X 10.7.2 (Lion).


#6

Sorry, solved! I had to edit (re-write) some lines…


#7

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.