Vizard 7 » Tutorials & Examples » Example scripts » Physics » Tracking an object
7.3

Tracking an object

\examples\physics\physics1.py

This script demonstrates how to track an object.

"""
Click on an object to track it
Right click to stop tracking
Press 'r' to reset the simulation
"""
import viz
import vizact
import vizmat

viz.setMultiSample(4)
viz.fov(60)
viz.go()

import vizinfo
vizinfo.InfoPanel()

#Declare some constants
NUM_BALLS = 20
BALL_ALPHA = 0.5

#We need to enable physics
viz.phys.enable()

#Add a ground with an infinite collision plane
ground = viz.addChild('ground.osgb')
ground.collidePlane()


target = 0  #The target we are tracking
lockedTarget = 0    #Have we locked onto the target?
currentLook = viz.Vector()  #Our current look vector
lastTick = viz.tick()   #The last update time

#The list of rigid body objects
bodies = []

#Add a bunch of balls to the physics simulation
for x in range(NUM_BALLS):
    #Add the geometric representation of the ball
    ball = viz.addChild('beachball.osgb',cache=viz.CACHE_COPY)
    #Make ball twice as big
    ball.setScale([2,2,2])
    #The balls collision will be represented by a sphere
    ball.collideSphere()
    #Set the alpha value of the ball
    ball.alpha(BALL_ALPHA)
    #Add the ball to the physical objects list
    bodies.append(ball)

#Add a box model
box = viz.addChild('crate.osgb')
#Use the boxes bounding box for collisions
box.collideBox()
#Set the alpha value of the box
box.alpha(BALL_ALPHA)
#Add the box to the list of physical objects
bodies.append(box)

#Move the head position back and up and look at the origin
viz.MainView.setPosition([0,6,-15])
viz.MainView.lookAt([0,0,0])

#This function will reset the physics simulation
def Reset():
    for x,b in enumerate(bodies):
        #Reset the physics of the object (This will zero its velocities and forces)
        b.reset()
        #Translate the object to the proper height
        b.setPosition([vizmat.GetRandom(-0.2,0.2),x*1.5+15,vizmat.GetRandom(-0.2,0.2)])
        #Reset the rotation of the object
        b.setEuler([0,0,0])

Reset()

def mytimer():
    global lastTick, currentLook, lockedTarget
    if target:
        #Calculate elapsed time
        elapsed = viz.tick() - lastTick
        #Create the vector of the targets current position
        dest = viz.Vector(target.getPosition())
        #Create a vector pointing from our current looking position to the new looking position
        newLook = dest - currentLook
        #Calculate the distance between the two positions
        distance = newLook.length()
        #If the distance is small or we are locked on the target then look at it immediately
        if distance < 0.1 or lockedTarget:
            currentLook = dest
            lockedTarget = 1
        else:
            #We are not locked on the target, so we increment our looking position towards the current position of the target
            newLook.setLength(elapsed * distance * 2)
            currentLook += newLook
        #Look at the newly calculated position
        viz.lookAt(currentLook.get())
    #Save the current time
    lastTick = viz.tick()

vizact.ontimer(0, mytimer)


def startTracking():
    global target, lockedTarget, currentLook
    #Find which object the mouse is over
    node = viz.pick()
    #If the mouse is over an object other than the ground, begin tracking it
    if node in bodies:

        #If we were previously tracking an object, restore its alpha value
        if target:
            target.alpha(BALL_ALPHA)
        else:
            #Calculate our current looking position based on the viewers
            #head position and look vector
            headpos = viz.MainView.getPosition()
            ballpos = node.getPosition()
            distance = vizmat.Distance(headpos,ballpos)
            currentLook.set(viz.MainView.getMatrix().getForward())
            currentLook.setLength(distance)
            currentLook += headpos
        #Save the new target and set its alpha
        target = node
        lockedTarget = 0
        target.alpha(1)
        #turn off mouse navigation
        viz.mouse(viz.OFF)


def stopTracking():
    global target, lockedTarget, currentLook
    #Stop tracking the current target and turn on mouse navigation
    if target:
        target.alpha(BALL_ALPHA)
    target = 0
    lockedTarget = 0
    viz.mouse(viz.ON)


vizact.onmousedown(viz.MOUSEBUTTON_LEFT, startTracking)
vizact.onmousedown(viz.MOUSEBUTTON_RIGHT, stopTracking)


#'r' key resets simulation
vizact.onkeydown('r',Reset)

#Set the background color
viz.clearcolor(viz.SLATE)