# ---------
# Tested in Blender 2.75a and 2.76
# Makes a Bezier-spline motion trail for an object.
# Set the length of the tail in frames via the tail_length variable below.
# To run, select object, generate a motion path for the object (Editor>Motion Paths) across the total desired frame range, and Run Script.
# Warning: this can take a long time to run with long motion paths and long tail sizes
# Once the spline has been generated, extrude and/or add bevel and taper objects to the Geometry settings of the spline.
# Bret Battey / BatHatMedia.com September 2015
# ---------
import bpy
from bpy.props import *
from mathutils import *
from math import *
import time
# ----- FUNCTION DEFINITIONS -----
# Time utils thanks to http://blenderscripting.blogspot.co.uk/search/label/time
def get_last_time():
if len(time_list) < 2:
return "ERROR: must have two time entries to calculate the difference"
return time_list[-1] - time_list[-2]
def mark_time():
time_list.append(time.time())
time_list = []
##------------------------------------------------------------
#### Curve creation functions
# sets bezierhandles to auto
def setBezierHandles(obj, mode = 'AUTOMATIC'):
scene = bpy.context.scene
if obj.type != 'CURVE':
return
scene.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT', toggle=True)
bpy.ops.curve.select_all(action='SELECT')
bpy.ops.curve.handle_type_set(type=mode)
bpy.ops.object.mode_set(mode='OBJECT', toggle=True)
# create new CurveObject
def createCurve(verts, name):
# create curve
scene = bpy.context.scene
newCurve = bpy.data.curves.new(name, type = 'CURVE') # curvedatablock
newSpline = newCurve.splines.new(type = 'BEZIER') # spline
# The new spline already has one point. Add the remaining needed.
newSpline.bezier_points.add(verts-1)
# set curveOptions
newCurve.dimensions = '3D'
# create object with newCurve
new_obj = bpy.data.objects.new(name, newCurve) # object
scene.objects.link(new_obj) # place in active scene
new_obj.select = True # set as selected
scene.objects.active = new_obj # set as active
# set bezierhandles
setBezierHandles(new_obj)
return new_obj
#based on animation_rotobezier.py
def keyframeBezier(Obj, frame):
Data = Obj.data
for Spline in Data.splines:
for CV in Spline.bezier_points:
CV.keyframe_insert(data_path='co', frame = frame)
CV.keyframe_insert(data_path='handle_left', frame = frame)
CV.keyframe_insert(data_path='handle_right', frame = frame)
# ------------- SCRIPT START
tail_length = 60 # length of the spline in frames
object = bpy.context.object
path = object.motion_path
frame_start = path.frame_start
frame_end = path.frame_end
path_length = path.length
# --- create the Bezier curve
trail = createCurve(tail_length,object.name+" motion_trail")
mark_time() # start measuring elapsed time
# --- key frame the curve at every frame in the motion path
for i in range(tail_length-1,path_length): # motion path index
print("Point "+str(i))
for j in range(tail_length): # curve point index
trail.data.splines[0].bezier_points[j].co = path.points[(i-tail_length)+j].co # set the coordinates of the motion tail to the corresponding point on the motion path
# keyframe it
keyframeBezier(trail, frame_start+i)
mark_time()
print('The motion trail keyframing took {: 5g} seconds'.format(get_last_time()))
Bret Battey blogging sundry ideas, favorable events, works in progress, and miscellaneous solutions in digital music and video-music research and creation. I see this as a subsidiary of my web site, BatHatMedia.com.
Tuesday, February 16, 2016
Blender Script for creating animated motion-trail ribbon
Given an object for which a motion-path has been generated, will create a Beziér-spline ribbon that follows the motion of the object for a given tail length (designated in frames).
Blender Script for object-motion measurements
In Blender, given an object that has a motion path, will provide animated empties which indicate the object's velocity, acceleration, magnitude, and accumulated distance moved.
# ---------
# Tested on Blender 2.75a and 2.76
# For a given object, makes an empty, which moves to indicate the velocity (displacement between frames) for each axis of the original object
# and another empty providing magnitude of the movement
# and another empty providing accumulative displacement for each axis,
# and yet another for acceleration.
# To run, select object, generate a motion path for the object (Editor>Motion Paths) across the total desired frame range, and Run Script.
# Bret Battey / BatHatMedia.com Dec 2015
# ---------
import bpy
from bpy.props import *
from mathutils import *
from math import *
import time
# ----- FUNCTION DEFINITIONS -----
# Time utils thanks to http://blenderscripting.blogspot.co.uk/search/label/time
def get_last_time():
if len(time_list) < 2:
return "ERROR: must have two time entries to calculate the difference"
return time_list[-1] - time_list[-2]
def mark_time():
time_list.append(time.time())
time_list = []
# ------------- SCRIPT START
object = bpy.context.object
path = object.motion_path
frame_start = path.frame_start
frame_end = path.frame_end
path_length = path.length
# velocity empty
bpy.ops.object.empty_add(type='PLAIN_AXES', radius=1, view_align=False, location=(0,0,0), layers=object.layers)
velempty = bpy.context.object
velempty.name = object.name + '_velocity'
# vector magnitude
bpy.ops.object.empty_add(type='PLAIN_AXES', radius=1, view_align=False, location=(0,0,0), layers=object.layers)
magempty = bpy.context.object
magempty.name = object.name + '_magnitude'
# accumulative distance traveled
bpy.ops.object.empty_add(type='PLAIN_AXES', radius=1, view_align=False, location=(0,0,0), layers=object.layers)
accumempty = bpy.context.object
accumempty.name = object.name + '_accum_distance'
# acceleration
bpy.ops.object.empty_add(type='PLAIN_AXES', radius=1, view_align=False, location=(0,0,0), layers=object.layers)
accelempty = bpy.context.object
accelempty.name = object.name + '_acceleration'
mark_time() # start measuring elapsed time
for i in range(0,path_length-2): # motion path index
nextPointCo = path.points[i+1].co # next time point
thisPointCo = path.points[i].co # this time point
dif = nextPointCo-thisPointCo # x,y,z distances
mag = sqrt(dif[0]*dif[0]+dif[1]*dif[1]+dif[2]*dif[2]) # vector magnitude via pythagorean theorem
velempty.location = dif # set vel empty's location to the velocity vector
magempty.location[2] = mag # set z position of mag empty's location to the magnitude
frame = frame_start+i # get absolute frame number
velempty.keyframe_insert(data_path='location',frame=frame,index=-1) # set keyframe for velocity. index -1 = set all three axes
magempty.keyframe_insert(data_path='location',frame=frame,index=2) # set keyframe for velocity. index -1 = set all three axes
if i == 0:
accumempty.keyframe_insert(data_path='location',frame=frame,index=-1) # set keyframe. index -1 = set all three axes
accumdif = accumempty.location # start accumulated distance with a convenient 0,0,0 vector
else:
accumdif[0] += abs(dif[0]) # add absolute value of velocity to the accumulative distance
accumdif[1] += abs(dif[1])
accumdif[2] += abs(dif[2])
accumempty.location = accumdif # move empty to this point
accumempty.keyframe_insert(data_path='location',frame=frame,index=-1) # set keyframe. index -1 = set all three axes
accelempty.location = dif-lastdif # acceleration = dif between this frame's velocity and the previous frame's
accelempty.keyframe_insert(data_path='location',frame=frame-1,index=-1) # set keyframe ONE FRAME BACK. index -1 = set all three axes
lastdif = dif
mark_time()
print('The keyframing took {: 5g} seconds'.format(get_last_time()))
Tuesday, December 22, 2015
Video Preview of My New OptiNelder Plugin
Video preview of my new OptiNelder plugin for Apple Motion, using Nelder-Mead search agents to crawl on an input image.
https://vimeo.com/149694242
Multisample Antialiasing for FxPlugs
I finally implemented OpenGL Multisample Antialiasing in the context of an Apple FxPlug project. Took me a lot of time to figure this one out (why is it so hard to find clear implementation details on MSAA?). I hope I can save someone else the pain:
https://github.com/bbattey/MSAA-for-FxPlugs
https://github.com/bbattey/MSAA-for-FxPlugs
Saturday, December 19, 2015
Kochanek Bartels Spline Class for Objective-C + OpenGL
A Kochanek Bartels spline is a lovely, flexible means for casting a curve through multiple points, and providing artistically useful control over the character of the curve. It is also known as a TCB spline, because the controls are Tension, Continuity, and Bias. It was originally developed for providing smooth keyframed animation control curves, but it is also useful for general graphics purposes. For one of my Apple Motion FxPlug projects, I developed a Objective C class to render a Kochanek Bartels spline in OpenGL. It includes an additional feature of interpolating colors between the target points.
I have placed the code on GitHub. Corrections/improvements welcomed.
And here's a taste of what happens if one sets the parameters outside of the standard -1 to 1 range. Here T = -4.38, C = -1.31, and B = 0.37:
I have placed the code on GitHub. Corrections/improvements welcomed.
And here's a taste of what happens if one sets the parameters outside of the standard -1 to 1 range. Here T = -4.38, C = -1.31, and B = 0.37:
Sunday, November 15, 2015
Triptych Unfolding at Synchresis 2015
The 2015 Synchresis Festival will include Triptych Unfolding in screenings in Valencia (Nov 19), Granada (Nov 24), Canarias (Nov 25 & 26), and Madrid (Nov 27). More information can be found here.
Monday, October 26, 2015
Premiere Performances of "The Five"
My new piece, The Five (for vibraphone and responsive audiovisuals), commissioned by percussionist Andrew Spencer, will be premiered by him in his U.S. tour autumn 2015. The first three performances of his tour are October 30 at University of Northern Colorado, November 3 at San Jose State University, and November 6 at Arizona State University.
Subscribe to:
Posts (Atom)





