View Single Post
  #3  
Old 01-10-2008, 03:20 PM
farshizzo farshizzo is offline
WorldViz Team Member
 
Join Date: Mar 2003
Posts: 2,849
I've attached a sample script that creates a custom vizact action that animates a bone. The code at the bottom of the script shows how to use the action. This action will be included in the vizact library in the next release of Vizard. Let me know if anything is unclear.
Code:
import viz
viz.go()

"""
Code for creating action that animates a bone rotating
"""

_paramval_ = vizact._paramval_
_paramlist_ = vizact._paramlist_
VizCubicQuatInterpolator = vizact.VizCubicQuatInterpolator
VizLinearQuatInterpolator = vizact.VizLinearQuatInterpolator

def boneSpinTo(bone,mode=viz.ABS_PARENT,quat=None,euler=None,axisAngle=None,speed=None,time=None,p1=None,p2=None):
	bla = viz.ActionData()
	bla.bone =  bone
	bla.mode = mode
	bla.speed = speed
	bla.time = time
	bla.quat = quat
	bla.euler = euler
	bla.axisAngle = axisAngle
	bla.p1 = p1
	bla.p2 = p2
	bla.actionclass = VizBoneSpintToAction
	return bla

class VizBoneSpintToAction(viz.ActionClass):

	def begin(self,object):
		
		self.elapsed = 0.0
		self.duration = 0.0
		
		#If bone is not a Vizard bone object, assume it is string and get bone from name
		bone = _paramval_(self._actiondata_.bone,object)
		if isinstance(bone,viz.VizBone):
			self.bone = bone
		else:
			self.bone = object.getBone(bone)
		
		#Make sure bone is valid
		if not self.bone:
			self.end(object)
			return
			
		#Lock the bone for animating
		self.bone.lock()
		
		#Get coordinate frame mode for bone rotations
		self.mode = _paramval_(self._actiondata_.mode,object)
		
		#Get begin and end rotation
		beginQuat = self.bone.getQuat(self.mode)
		
		if self._actiondata_.quat is not None:
			self.endQuat = _paramlist_(self._actiondata_.quat,object)
		elif self._actiondata_.euler is not None:
			self.endQuat = vizmat.EulerToQuat(_paramlist_(self._actiondata_.euler,object))
		elif self._actiondata_.axisAngle is not None:
			self.endQuat = vizmat.AxisAngleToQuat(_paramlist_(self._actiondata_.axisAngle,object))
		else:
			self.end(object)
			return

		#Compute whether animation duration is based on time or speed
		speed = _paramval_(self._actiondata_.speed,object)
		time = _paramval_(self._actiondata_.time,object)
		
		if time is not None:
			self.duration = time
		elif speed is not None:
			self.duration = vizmat.QuatDiff(beginQuat,self.endQuat) / speed

		#Make sure duration is valid
		if self.duration <= 0.0:
			self.bone.setQuat(self.endQuat,self.mode)
			self.end(object)
			return
	
		#Check if we are using linear or cubic interpolation
		p1 = _paramlist_(self._actiondata_.p1,object)
		p2 = _paramlist_(self._actiondata_.p2,object)
		if p1[0] is not None and p2[0] is not None:
			interpolator = VizCubicQuatInterpolator(p1[0],p2[0])
		else:
			interpolator = VizLinearQuatInterpolator()

		interpolator.init(beginQuat,self.endQuat)
		self.interpolate = interpolator.interpolate
		
	def update(self,elapsed,object):

		self.elapsed += elapsed
		p = self.elapsed / self.duration
		if p >= 1.0:
			self._overtime_ = self.elapsed - self.duration
			self.bone.setQuat(self.endQuat,self.mode)
			self.end(object)
			return
	
		self.bone.setQuat(self.interpolate(p),self.mode)
	



model = viz.add('vcc_female.cfg',pos=(0,0,5),euler=(180,0,0))

lookRight = boneSpinTo('Bip01 Spine1',mode=viz.AVATAR_LOCAL,euler=(45,0,0),speed=90)
lookLeft = boneSpinTo('Bip01 Spine1',mode=viz.AVATAR_LOCAL,euler=(-45,0,0),speed=90)

vizact.onkeydown(viz.KEY_RIGHT,model.runAction,lookRight,pool=1)
vizact.onkeydown(viz.KEY_LEFT,model.runAction,lookLeft,pool=1)
Reply With Quote