Tracking script


(theeth) #1

First of all, I’d like to thank Jamesk for his walk-o-matic script, since I borrowed some of the functions from there.

anyway, here’s what I’m trying to use, and it makes some bizarre IPOs.


ObjectMain = "Empty"
ObjectTrack = "Track"
Start = 1
End = 50

from vecf import *
from Blender import Object, Scene, Ipo, Window

ObMain = Object.Get(ObjectMain)
ObTrack = Object.Get(ObjectTrack)

# Normal of the plane on which the tracking rotation occures
N = vnorm(ObMain.matrix[2][:3]) # in this case, the Z axis

def writeCurvePoint(ipo, frame, point):
    # ipo: the IPOblock to use           frame: at what frame
    # point: the 3D coordinate to write
    xc = ipo.get('RotX')
    yc = ipo.get('RotY')
    zc = ipo.get('RotZ')
    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('RotX')
    yc = ipo.addCurve('RotY')
    zc = ipo.addCurve('RotZ')
    for curve in [xc, yc, zc]:
        curve.setInterpolation(ipol)
        curve.setExtrapolation(expol)
    return ipo

scene = Scene.getCurrent()

IPO = makeIPO("Track", "Linear", "Linear")

for Fr in range(Start, End +1):
	scene.currentFrame(Fr)
	Window.RedrawAll()

	# Vector from the Tracking object to the Target
	AB = vecsub(ObTrack.matrix[3][:3], ObMain.matrix[3][:3])

	# projection of AB on the plane of the tracking rotation
	T1 = vnorm(vecsub(AB,proj(AB, N))) # in this case, the Y axis

	T2 = vnorm(crossp(T1, N)) # in this case, the X axis
	
		
	Rot = mat2euler_rot([T2, T1, N])	
		
	writeCurvePoint(IPO, Fr, vecmul(Rot,18/pi))

	ObMain.RotX = Rot[0]
	ObMain.RotY = Rot[1]
	ObMain.RotZ = Rot[2]

ObMain.link(IPO)

again, using the vecf.py module I posted the other day.

If someone could help me get the IPO part correctly, it would be close to finish.

Martin


(theeth) #2

I have a little test blend that tracks one object on a non-aligned axis and another object on a moving axis.

http://www.clubinfo.bdeb.qc.ca/~theeth/Track_Axis.blend

Martin


(theeth) #3

there’s a demo AVI (in DivX) there: http://www.clubinfo.bdeb.qc.ca/~theeth/Tracking.avi

Martin


(LukeW) #4

Hi,
I downloaded your blend file and trimmed it down… it looks like only a couple of the scripts are necessary - and that ipos can be created the normal way - by moving objects around and inserting keyframes.

I made a new animation for it:
http://members.ozemail.com.au/~wenke/blender/TrackAxis.blend

http://members.ozemail.com.au/~wenke/blender/TrackAxis.avi

It tests a lot of the extremes of the turret’s movement. It spins around at high-speed when the focus is near the centre of the rotation… That’s because the “bottom” part of the cannon’s barrels want to stay below the top, and when the barrels are vertical it is easy for the former top to become the bottom.

I don’t see any problems with your blend file… (besides the cannon being a bit crooked on that 45 degree slope - I fixed that)

Are you still having a problem with the IPOs? (because the scripts in my edited version of the blend didn’t use any IPO code and it works as expected…)

BTW, can that type of animation be done with using any scripting? Also, for a while I’ve been wanting to make eyes that follow an empty and eyelids that follow the eyes - but only as far as pitch (turning up/down) goes… I could probably modify that blend to do that… but I’d also like the eyes to be parented to a skeleton which would rotate its head around and walk around. I was wondering if you knew how to allow that cannon to be parented to something else (that blue 45 degree slope for example) so that it is properly attached to it and the cannon tracks the sphere properly… whenever I try the cannon falls apart and stops working properly. Thanks.


(theeth) #5

yeah, it works as expected, but I wanted to make a version that writes the rotation to IPO, so it could be used with particles and stuff like that.

It could be used for just about any setup that requires a joint with constraint axis, like a camera on a tripod, or a missile turret.

as for using parents, I would need to write additional math functions to allow this, since rotations will have to take parenting in consideration and all. not sure how to do that.

Martin


(Alltaken) #6

hi theet this is exactly what i wished for when i first posted my question!!!

one question is there a way to limit the movement in some way of the turret.

as your avi showed when the turret gets too vertical it spins funny.

also when it gets too low it would cut through a mesh below it.

(you have seen my tank animation i assume)
i was wondering, if the target went below the lowest logical point (eg the tuuret would cut a solid object) could there be a limiter of some kind to limit rotation in the vertical direction both up or down (actually to limit the rotation in any axis)

thanks !!! :smiley:


(LukeW) #7

alltaken:

as your avi showed when the turret gets too vertical it spins funny.

also when it gets too low it would cut through a mesh below it.

(you have seen my tank animation i assume)
i was wondering, if the target went below the lowest logical point (eg the tuuret would cut a solid object) could there be a limiter of some kind to limit rotation in the vertical direction both up or down (actually to limit the rotation in any axis)

Actually it was my avi that showed the problem when the turret is vertical…

Anyway, even if the tilting (up/down - “pitch”) part of the turret couldn’t move all the way up, it would still have problems when the ball passes directly overhead the centre of rotation… the turning part of the turret (left/right - “yaw”) tries to always face the direction of the ball… if the ball is at the turret’s turning axis, the turret will flip rapidly in order to face the direction of the ball…

This problem can be reduced though… in my avi I coloured the different sides of the turret different colours so you could see which way around the turret is (if it is flipped over or not). Well the animation shows that the red side of the turret’s barrel is always pointing to the right side of the ball. If the barrels could turn upside-down when the ball orbited over the top of the turret then the turret wouldn’t rapidly rotated when it passed over the centre… but if that turret was replaced with a video camera it would mean that the camera would be upside-down at the end… so if the rapid rotation problem was fixed it would mean that the tracking object (turret barrels or video camera) would be upside-side some of the time.


(eeshlo) #8

I don’t know if you can still use this, but this should work:


ObjectMain = "Empty" 
ObjectTrack = "Track" 
Start = 1 
End = 50 

from vecf import * 
from Blender import Object, Scene, Ipo, Window 

ObMain = Object.Get(ObjectMain) 
ObTrack = Object.Get(ObjectTrack) 

# Normal of the plane on which the tracking rotation occures 
N = vnorm(ObMain.matrix[2][:3]) # in this case, the Z axis 

def writeCurvePoint(ipo, frame, point): 
    # ipo: the IPOblock to use           frame: at what frame 
    # point: the 3D coordinate to write 
    idx = 0 
    for c in ipo[1:]: 
        c.addBezier((frame, point[idx]))
        c.update()
        idx += 1
      
def makeIPO(name, ipol, expol): 
    # name: desired name for this IPOblock    ipol: type of interpolation 
    # expol: type of extrapolation 
    # returns list of [ipo, newcurves]
    ipo = Ipo.New('Object', name) 
    xc = ipo.addCurve('RotX') 
    yc = ipo.addCurve('RotY') 
    zc = ipo.addCurve('RotZ') 
    for curve in [xc, yc, zc]: 
        curve.setInterpolation(ipol) 
        curve.setExtrapolation(expol) 
    return [ipo, xc, yc, zc]

scene = Scene.getCurrent() 

IPO = makeIPO("Track", "Linear", "Linear")
ObMain.setIpo(IPO[0])

for Fr in range(Start, End +1): 
   scene.currentFrame(Fr) 
   Window.RedrawAll() 

   # Vector from the Tracking object to the Target 
   AB = vecsub(ObTrack.matrix[3][:3], ObMain.matrix[3][:3]) 

   # projection of AB on the plane of the tracking rotation 
   T1 = vnorm(vecsub(AB,proj(AB, N))) # in this case, the Y axis 

   T2 = vnorm(crossp(T1, N)) # in this case, the X axis 
           
   Rot = mat2euler_rot([T2, T1, N])    
       
   writeCurvePoint(IPO, Fr, Rot)

You don’t actually have to convert the angles, that is done automatically when you use addBezier(), setting ob.RotXYZ is also not necessary, since I linked the ipo to the object before writing the curve and so it is updated when adding points. There is a lot of slowdown the more frames are calculated, which might be caused by calling update() every point.

The main cause of the strange behaviour seems to be the use of ipo.get() in your routines, the points were never written, or at least not all of them.
Maybe it used some part of unintialized memory or something, the numbers where often NAN or INF, which could also put Blender into a seemingly infinite loop when trying to use the home key to view the ipo. More 2.25 bugs I guess…


(theeth) #9

thanks, it worked great. New demo to come soon.

Martin


(theeth) #10

new demo done with the “write ipo” script, including a moving turret and a particles emitter.

http://www.clubinfo.bdeb.qc.ca/~theeth/Tracking2.avi

same blend link: http://www.clubinfo.bdeb.qc.ca/~theeth/Track_Axis.blend

Martin
<edit> I changed the link of the video since it pointed to the wrong file </edit>


(Jamesk) #11

Woah… theeth borrowing code from me… that’s a real honor! 8)

Great script too! Now I can borrow the rotational IPO-code back from you then… :smiley:


(RipSting) #12

About the turret spinning too quickly… Before you modify the turret’s position, you could compare its current position with its future one and limit how far it can rotate. The Maximum rotation could be a variable in your program. This would impose some lag into your script, so you couldn’t always count on your turret to be pointing at the target, but it would make it more believable. What would be cool would be to add some acceleration variables too, so it would have to speed up gradually to its maximum rotation value and then slow down. But doing it linearly would probably be easiest.


(theeth) #13

Ripsting: yeah, that could be done, but it’s not really in the scope of that script, although it would be nice for a complete battle simulation.

Martin