6
$\begingroup$

Here's a question just for the sake of curiosity... I was watching the new Damon Albarn video, the one that features his 3d head. And for the major part of the video it just looks like someone is recording what is seen on the screen of the computer, "camtasia"-like. or something.

But near the end, it start using really realistic lighting and shaders, and it ocurred to me that what actually is going on, is that, somehow they captured the movements the user was doing in the original interface, and used them as camera movements and settings.

I don't know if i am being clear, but do you guys think is possible with some scripting? Here's the video, near the end, by the way: https://www.youtube.com/watch?v=rjbiUj-FD-o

$\endgroup$
  • $\begingroup$ The problem I see is that one has not a good enough PC to render the working process. Even if you take a "sceenshot" from the camera every x second, the previous picture has to be finished because Blender can only handle one rendering at a time? $\endgroup$ – WorldSEnder May 24 '14 at 12:51
  • $\begingroup$ No, that's not what i'm asking. what i would like is to cature the movement, as if it were a camera animation, so i can render later with whatever settings i choose. $\endgroup$ – invicente May 24 '14 at 12:53
  • $\begingroup$ Ah, now, I think that should be possible. It's just that I can't watch the video in Germany because it's blocked. $\endgroup$ – WorldSEnder May 24 '14 at 12:56
8
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ This is awesome! Thank you!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $\endgroup$ – invicente May 24 '14 at 17:46
5
$\begingroup$

You can use Record animation and Lock camera to view to do this without python, however it only works in fly/walk mode:

  1. Enable it in Timeline > Header:

    enter image description here

  2. This will insert keyframes for any objects/bones you move/transform, including the camera.

  3. In camera view (Numpad 0), enable Lock camera to view in 3D view > Properties region:

    enter image description here

    You should see a dotted line on the outside of the camera view, and moving the view with MMB should also move the camera.

  4. Press AltA to start the animation, then press ShiftF to enter Walk Navigation. This also works in Fly mode (3D view > Header > View > Navigation > Fly Navigation).

$\endgroup$
  • 1
    $\begingroup$ you should mention that, with this method, you have to set start and end beforehands because Alt+A will loop the player. $\endgroup$ – WorldSEnder May 24 '14 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.