# Jamesk's Walk-o-matic version 0.49.7 # for Blender 2.25 and a fully installed Python 2.0 [required] # mise jour pour blender 2.33 : jm soler, 10 mai 2004 # SET/CHECK THE PARAMETERS BELOW BEFORE EXECUTING THE SCRIPT. # Make sure to select your proxy object, then run the script with ALT+P. # Please consult the documentation for a full description of the parameters. # ...Aaaaand check the console window for any messages. # GENERAL SETTINGS: FF = FIRST_FRAME = 1 # begin evaluating at this frame LF = LAST_FRAME = 161 # stop evaluating after this frame HS = HEEL_SEPARATION = 1.5 # desired distance between heel targets (in Blender Units) MT = MOVE_TIME = 6.0 # number of frames/cycle a foot is moving (not locked to ground) MSD = MOVE_STOP_DELAY = 2 # any value above zero will prolong the time a foot stays in the air. HEEL_TO_FLAT_DISTANCE = 0.8 # desired distance between a heel target and its associated foot look-at-target FLAT_TO_TLAT_DISTANCE = 0.3 # desired distance between a foot look-at-target and its associated toe look-at-target AL = ALWAYS_LIFT = 0 # set to zero to prevent feet moving up/down when proxy has speed 0 CTD = C_TARG_DISTANCE = 2.0 # how far above proxy to place center target LA = LIFT_AXIS = 'local' # lift feet along global Z or local proxy Z? CTDLA = CTD_LIFT_AXIS = 'local' # raise center target along global Z or local proxy Z? # LIFT ENVELOPE SETTINGS: LP = LIFT_PEAK = 0.5 # how far to lift above proxy initially FLATLP = FLAT_LIFT_PEAK = 0.2 # how far to lift foot look-at-target above proxy initially TLATLP = TLAT_LIFT_PEAK = 0.2 # how far to lift toe look-at-target above proxy initially LPT = LIFT_PEAK_TIME = 0.2 # time to reach lift-peak. (relative to movetime) MP = MID_PEAK = 0.4 # how far from proxy after lift-peak FLATMP = FLAT_MID_PEAK = 0.4 # how far to lift foot look-at-target TLATMP = TLAT_MID_PEAK = 0.4 # how far to lift toe look-at-target MPT = MID_PEAK_TIME = 0.5 # time to reach mid-peak (relative to movetime) FP = FINAL_PEAK = 0.5 # how far from proxy before setting down again FLATFP = FLAT_FINAL_PEAK = 0.7 # how far to lift foot look-at-target TLATFP = TLAT_FINAL_PEAK = 0.9 # how far to lift toe look-at-target FPT = FINAL_PEAK_TIME = 0.8 # time to reach final_peak (relative to - you guessed it - movetime) # # Concept and coding by James Kaufeldt a.k.a. Jamesk # Made in Sweden, november 2002 # Contact: james.k@home.se # # Special thanx to d0pamine and theeth for some hints regarding vector math, # and Martin "Strubi" Strubel from whom I borrowed the "normalize" function # found in his "vect.py" utility module. # # --------------------------------------------------------------------------------------- # EDITABLE SECTION ENDS HERE! # # NO USER DEFINABLE VALUES BEYOND THIS POINT! # --------------------------------------------------------------------------------------- # # # # LT = MT CT = MT + LT import Blender from Blender import Object, Scene, Window, Ipo import sys, math proxy = Object.GetSelected() status = 'UNDEFINED ERROR' layer = 0 print print '----------------------------------' print 'W A L K - O - M A T I C V 0.49.8' print '----------------------------------' print # make sure that there's an actual walker proxy to use: if proxy == []: print 'No proxy indicated, terminating...' status = 'NO PROXY OBJECT SELECTED' if proxy != []: print 'Proxy in use: \t',proxy[0], layer = proxy[0].Layer print 'in layer',layer proxy = proxy[0] status = 'OK' sys.stdout.flush() scene = Scene.getCurrent() # make sure there's a scene to use (should always be one, but wth...) if scene == []: print 'No scene available, terminating...' status = 'NO CURRENT SCENE AVAILABLE' if scene != []: print 'Target scene: \t',scene sys.stdout.flush() # some generally useful functions below: def normalize(v): r = math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) return (v[0]/r, v[1]/r, v[2]/r) def moveAlong(origpos, distance, vector): newpos = [0,0,0] newpos[0] = origpos[0]+distance*vector[0] newpos[1] = origpos[1]+distance*vector[1] newpos[2] = origpos[2]+distance*vector[2] return newpos def invertVector(v): return ((-1*v[0], -1*v[1], -1*v[2])) def getOffset(origin, frame, xdir, xdist, forward): # origin: the point to offset frame: framenumber # xdir: 1 = positive offset along X, -1 = negative offset # xdist: how much to offset if Blender.Get('curframe')!= frame: Blender.Set('curframe',frame) Window.Redraw() loc = origin.getMatrix()[3] loc = moveAlong(loc, forward, normalize(origin.getMatrix()[1])) direction = normalize(origin.getMatrix()[0]) if xdir == -1: direction = invertVector(direction) return moveAlong(loc, xdist, direction) def getLiftAxisOffset(origin, frame, liftaxis, liftdist): # origin: the point to offset frame: framenumber # liftaxis: 'global' or 'local' lifting liftdist: the amount of lift if Blender.Get('curframe')!=frame: Blender.Set('curframe',frame) Window.Redraw() loc = origin.getMatrix()[3] direction = normalize(origin.getMatrix()[2]) if liftaxis=='global': direction = [0,0,1.0] return moveAlong(loc, liftdist, direction) def getElevation(origin, frame, axis, zdist, xdir, xdist, forward): # origin: the point to offset frame: framenumber # axis: 'local' or 'global' zdist: how much to elevate # xdir: the X offset xdist: the distance to offset along X loc = getOffset(origin, frame, xdir, xdist, forward) if axis=='local': direction = normalize(origin.getMatrix()[2]) return moveAlong(loc, zdist, direction) if axis=='global': direction = [0, 0, 1.0] return moveAlong(loc, zdist, direction) def writeCurvePoint(ipo, frame, point): # ipo: the IPOblock to use frame: at what frame # point: the 3D coordinate to write xc = ipo.getCurve('LocX') yc = ipo.getCurve('LocY') zc = ipo.getCurve('LocZ') idx = 0 for c in [xc,yc,zc]: c.addBezier((frame, point[idx])) idx += 1 c.update() def makeIPO(name, ipol, expol): # name: desired name for this IPOblock ipol: type of interpolation # expol: type of extrapolation ipo = Ipo.New('Object', name) xc = ipo.addCurve('LocX') yc = ipo.addCurve('LocY') zc = ipo.addCurve('LocZ') for curve in [xc, yc, zc]: curve.setInterpolation(ipol) curve.setExtrapolation(expol) return ipo def move(ipo, origin, destination, startframe, framespan, proxob, xdir, xdist, forward): # ipo - what ipo to write points to origin - the location (3Dpoint) to start at # destination - the location to end up at startframe - frame to set the first curvepoint at # framespan - total number of frames for the move proxob - the proxy/reference object # xdir - pos or neg offset along proxy X-axis xdist - how much to offset along proxy X-axis writeCurvePoint(ipo, startframe, origin) if AL==1 or origin!=destination: # Write curvepoints for LiftPeak and LiftPeakTime: # Pretty hackish formulae for proxyTime here... But they do work, so wtf... lpProxyTime = startframe + (LPT*framespan*2)-framespan*0.25 lpRealTime = startframe+(framespan+MSD)*LPT lpLocation = getElevation(proxob, lpProxyTime, LA, LP, xdir, xdist, forward) writeCurvePoint(ipo, lpRealTime, lpLocation) # Write curvepoints for MidPeak and MidPeakTime: mpProxyTime = startframe + (MPT*framespan*2)-framespan*0.25 mpRealTime = startframe+(framespan+MSD)*MPT mpLocation = getElevation(proxob, mpProxyTime, LA, MP, xdir, xdist, forward) writeCurvePoint(ipo, mpRealTime, mpLocation) # Write curvepoints for FinalPeak and FinalPeakTime: fpProxyTime = startframe + (FPT*framespan*2)-framespan*0.25 fpRealTime = startframe+(framespan+MSD)*FPT fpLocation = getElevation(proxob, fpProxyTime, LA, FP, xdir, xdist, forward) writeCurvePoint(ipo, fpRealTime, fpLocation) writeCurvePoint(ipo, startframe+framespan+MSD, destination) return (startframe+framespan, destination) def hold(ipo, location, startframe, framespan): # ipo - what ipo to write points to # location - the position (3Dpoint) to hold at # startframe - the first frame in the hold sequence # framespan - total number of frames to hold writeCurvePoint(ipo, startframe+MSD, location) writeCurvePoint(ipo, startframe+framespan, location) return (startframe+framespan, location) def doIt(forwardOffset, addCenter, whatsUp): print print 'Currently processing:',whatsUp # Start building the IPO for the right foot: ffootipo = makeIPO('rfoot', 'Linear', 'Constant') cpf = currentProxyFrame = FF # make first step (only half as far as the others): ffootloc = getOffset(proxy, cpf, 1, HS/2, forwardOffset) ffootframe = cpf targetloc = getOffset(proxy, cpf+MT, 1, HS/2, forwardOffset) ffootframe, ffootloc = move(ffootipo, ffootloc, targetloc, ffootframe, MT/2,proxy, 1, HS/2, forwardOffset) ffootframe, ffootloc = hold(ffootipo, ffootloc, ffootframe, LT) # now make the rest of the steps (full length): done = 0 while not done: cpf += CT targetloc = getOffset(proxy, cpf+MT, 1, HS/2, forwardOffset) ffootframe, ffootloc = move(ffootipo, ffootloc, targetloc, ffootframe, MT,proxy, 1, HS/2, forwardOffset) ffootframe, ffootloc = hold(ffootipo, ffootloc, ffootframe, LT) if cpf>LF: done=1 # Then we'll build the IPO for the left foot: sfootipo = makeIPO('lfoot', 'Linear', 'Constant') cpf = currentProxyFrame = FF # this one starts in hold-mode (waits for right foot to finish) sfootloc = getOffset(proxy, cpf, -1, HS/2, forwardOffset) sfootframe = cpf sfootframe, sfootloc = hold(sfootipo, sfootloc, cpf, MT/2) done = 0 while not done: cpf += CT targetloc = getOffset(proxy, cpf, -1, HS/2, forwardOffset) sfootframe, sfootloc = move(sfootipo, sfootloc, targetloc, sfootframe, MT,proxy, -1, HS/2, forwardOffset) sfootframe, sfootloc = hold(sfootipo, sfootloc, sfootframe, LT) if cpf>LF: done=1 if addCenter: # And to finish it off, let's put something in the middle of this: # This will simply add a third target floating above the proxy. # It will respect the specified lift axis, hence useful as parent for an armature ctargetipo = makeIPO('center', 'Linear', 'Constant') for cframe in range(FF, LF): targetloc = getLiftAxisOffset(proxy, cframe, CTDLA, CTD) writeCurvePoint(ctargetipo, cframe, targetloc) # Finished. Add the empties and link them to their respective IPOblocks. leftikt = Object.New('Empty','leftikt') rightikt = Object.New('Empty','rightikt') print 'Added',leftikt,rightikt if addCenter: centertarget = Object.New('Empty', 'centertarget') print 'Centertarget',centertarget centertarget.Layer = layer scene.link(centertarget) centertarget.setIpo(ctargetipo) leftikt.Layer = layer rightikt.Layer = layer scene.link(leftikt) scene.link(rightikt) leftikt.setIpo(sfootipo) rightikt.setIpo(ffootipo) print whatsUp,'IPO:s',sfootipo,ffootipo print '---------------------------------------------------------' sys.stdout.flush() ######################################### # if everything's OK, let's get to work # ######################################### if status=='OK': currentUserFrame = Blender.Get('curframe') #first pass, heel targets: doIt(0, 1, 'Heel targets') #second pass, foot look-at targets: LP = FLATLP MP = FLATMP FP = FLATFP doIt(HEEL_TO_FLAT_DISTANCE, 0, 'Foot look-at targets') #third pass, toe look-at targets: LP = TLATLP MP = TLATMP FP = TLATFP doIt(HEEL_TO_FLAT_DISTANCE+FLAT_TO_TLAT_DISTANCE, 0, 'Toe look-at targets') # At last, as a friendly gesture, restore the frame to whatever the user # was looking at before running the script, and refresh the screens: Blender.Set('curframe',currentUserFrame) Window.RedrawAll() print 'Processing completed.' print 'Thank you for using Walk-O-Matic :D' sys.stdout.flush() ################################################### # if things are not right, print some dying words:# ################################################### if status!='OK': print '' print 'Walk-o-matic is sadly forced to report that' print 'it could not go to work properly.' print 'Cause of termination: ',status print 'Please consult the documentation regarding proper use.' sys.stdout.flush() """ Since you've read this far - here's a funny story: Three old guys were visiting the doctor in order to have their mental capacity evaluated. The doctor asks the first guy: 'What's three times three?' First guy answers: '274' The doctor looks a bit worried, but asks the second guy: 'What's three times three?' Second guy answers: 'Tuesday' Our beloved doctor looks quite shocked, but continues to ask the same question to old guy #3: 'What's three times three?' Third guy answers: 'Nine' The doctor immediately looks a lot happier. 'How did you come up with that answer?' he asks. Third guy answers: 'That's simple. I just subtracted 274 from Tuesday' """