This script should fulfill your needs. Basically it uses a modal operator (runs parallel to Blender), takes the current position and view and stores those in an array (records at the currently selected framerate of the selected scene). When you click with Left-Mouse a new camera is created that has your movement assigned to it. Right-Mouse or Esc will cancel the command. You can find it by pressing Space in the 3D-Viewport and searching for "Record View Movement". When you leave the viewport the script pauses recording until you reenter.
Just copy and paste the script into a texteditor and run it once (Alt+P) or write a full plugin (in this case give some credits to stackexchange). Anyway, here is the script:
import bpy, time, bgl, blf
from mathutils import Vector, Quaternion
def bgl_draw_fx(self, context):
"""A drawing routine that we show while our operator is active"""
font_id = 0 # XXX, need to find out how best to get this.
bgl.glColor4f(1, 0.3, 0.3, 1)
blf.position(font_id, 15, 30, 0)
blf.size(font_id, 12, 72)
blf.draw(font_id, 'Recording...')
# restore OpenGL to default
bgl.glDisable(bgl.GL_BLEND)
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
class RecordOperator(bpy.types.Operator):
"""Translate the view using mouse events"""
bl_idname = "view3d.record_movement"
bl_label = "Record View Movement"
def __init__(self):
self.fps = 1
self.timer = None
self.lasttime = 0
self.recorded_movement = []
def registerModal(self, context, event):
args = (self, context,)
self._handle = bpy.types.SpaceView3D.draw_handler_add(bgl_draw_fx, args, 'WINDOW', 'POST_PIXEL')
self.timer = context.window_manager.event_timer_add(1.0/self.fps, context.window)
context.window_manager.modal_handler_add(self)
def unregisterModal(self, context):
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
context.window_manager.event_timer_remove(self.timer)
def execute(self, context):
"""Gets called by us"""
action = bpy.data.actions.new('RecordingCamera') # create action
curveLocX = action.fcurves.new(data_path="location", index=0) # create curves
curveLocY = action.fcurves.new(data_path="location", index=1)
curveLocZ = action.fcurves.new(data_path="location", index=2)
curveRotX = action.fcurves.new(data_path="rotation_quaternion", index=0)
curveRotY = action.fcurves.new(data_path="rotation_quaternion", index=1)
curveRotZ = action.fcurves.new(data_path="rotation_quaternion", index=2)
curveRotW = action.fcurves.new(data_path="rotation_quaternion", index=3)
frames_c = len(self.recorded_movement) # get frame-range
curveLocX.keyframe_points.add(frames_c) # add frames
curveLocY.keyframe_points.add(frames_c)
curveLocZ.keyframe_points.add(frames_c)
curveRotX.keyframe_points.add(frames_c)
curveRotY.keyframe_points.add(frames_c)
curveRotZ.keyframe_points.add(frames_c)
curveRotW.keyframe_points.add(frames_c)
for frame, (loc, quat) in enumerate(self.recorded_movement):
curveLocX.keyframe_points[frame].co = frame + 1, loc[0] # set keyframes
curveLocY.keyframe_points[frame].co = frame + 1, loc[1]
curveLocZ.keyframe_points[frame].co = frame + 1, loc[2]
curveRotX.keyframe_points[frame].co = frame + 1, quat[0]
curveRotY.keyframe_points[frame].co = frame + 1, quat[1]
curveRotZ.keyframe_points[frame].co = frame + 1, quat[2]
curveRotW.keyframe_points[frame].co = frame + 1, quat[3]
# apply created data
cam = bpy.data.cameras.new('RecordingPlayback')
camObj = bpy.data.objects.new('RecordingPlayback', cam)
camObj.rotation_mode = 'QUATERNION'
anm = camObj.animation_data_create()
anm.action = action
context.scene.objects.link(camObj) # link to scene
context.scene.update()
def modal(self, context, event):
if event.type == 'LEFTMOUSE':
# apply movement
self.execute(context)
self.unregisterModal(context)
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
self.unregisterModal(context)
return {'CANCELLED'}
v3d = context.space_data
if v3d.type != 'VIEW_3D':
return {'RUNNING_MODAL'}
ctime = time.clock()
if (ctime - self.lasttime) > (1.0/self.fps):
rv3d = v3d.region_3d
# record movement
current_rot = Quaternion(rv3d.view_rotation)
if rv3d.view_perspective == 'PERSP':
current_pos = rv3d.view_rotation.to_matrix().col[2].to_3d()
current_pos *= rv3d.view_distance
current_pos += rv3d.view_location
elif rv3d.view_perspective == 'CAMERA':
current_pos = Vector(context.scene.camera.location)
else:
print('BUG, unknown perspective:', rv3d.view_perspective)
self.recorded_movement.append((current_pos, current_rot))
self.lasttime = ctime
# don't block input
return {'PASS_THROUGH'}
def invoke(self, context, event):
self.fps = context.scene.render.fps
self.registerModal(context, event)
return {'RUNNING_MODAL'}
def register():
bpy.utils.register_class(RecordOperator)
def unregister():
bpy.utils.unregister_class(RecordOperator)
if __name__ == "__main__":
register()
Note: You can combine this with any technique that manipulates the current view (for example flight-mode Shift+F to record the movement and play it back. This is imo one of the best features of this script. Just trigger recording and go into flight mode. Keep in mind that you have to press Left Mouse to keep the recorded animation.