View Single Post
  #2  
Old 02-21-2014, 01:58 AM
Frank Verberne Frank Verberne is offline
Member
 
Join Date: Mar 2008
Location: Netherlands
Posts: 148
Hi Antonia,

I have been struggling with this problem for a while as well, and found the solution (at least using Euler rotations). To mirror the movements of another avatar, you need to apply the rotation of the left arm (for example) to the right arm AND you need to inverse the yaw & roll of that rotation. The pitch remains unchanged, because when you raise your arm in front of a mirror, your mirror image will also raise its arm. Furthermore, you don't need the position of the bones, the position of each bone is determined by the rotations of the 'motherbone'. I have updated your code, and this should do exactly what you are looking for, for any avatar with identical names for the left and right side bones (except for a unique left/right identifier).

On a side note, I am trying to understand matrix transformations using quaternions instead of using euler rotations (although I understand euler rotations, and I don't understand quaternions yet). So if you can tweak the code using matrix transformations, I'm all eyes !

Frank
Code:
import viz
import vizact
import vizshape

import viztask	 #Needed to control the experiment structure.
import vizinput	 #Needed to allow the input of participant information.
import time	 #Needed to record the date and time.

import numpy as np

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

UNIQUE_ID_LEFT_BONES = ' L '
UNIQUE_ID_RIGHT_BONES = ' R '

Anna = viz.addAvatar('vcc_female.cfg')
Anna.setPosition([0,0,-1])
Anna.setEuler([0,0,0])
Anna.state(15)

Betty = viz.addAvatar('vcc_female.cfg')
Betty.setEuler([180,0,0])
Betty.setPosition([0,0,1])
#Betty.state(15)

AnnaBones = {bone.getName(): bone for bone in Anna.getBoneList()}#For every bone in Linda's bone list, gets its name and make a dictionary.
BettyBones = {bone.getName(): bone for bone in Betty.getBoneList()}#Does the same for Mike.

mode = viz.AVATAR_LOCAL	 #Vizard defaults to ABS_PARENT. Sets 'mode' so that when we move the avatars' bones, they move locally to each avatar.

def reflect():
	[BettyBones[bone].lock() for bone in BettyBones]	 #Locks Betty's bones.

	# work out position & quaterion of each bone
	for AnnaBone in AnnaBones:	
		if UNIQUE_ID_LEFT_BONES in AnnaBone or UNIQUE_ID_RIGHT_BONES in AnnaBone:
			copyboneName = AnnaBone
			if UNIQUE_ID_LEFT_BONES in AnnaBone:
				BettyBone = copyboneName.replace(UNIQUE_ID_LEFT_BONES, UNIQUE_ID_RIGHT_BONES)
			elif UNIQUE_ID_RIGHT_BONES in AnnaBone:
				BettyBone = copyboneName.replace(UNIQUE_ID_RIGHT_BONES, UNIQUE_ID_LEFT_BONES)
		else:
			BettyBone = AnnaBone
			
		eulerAnna = AnnaBones[AnnaBone].getEuler(mode)

		print '----------------'
		print 'Annabone', AnnaBone
		print 'Bettybone', BettyBone

		eulerBetty = eulerAnna
		eulerBetty[0] = eulerBetty[0] * -1
		eulerBetty[2] = eulerBetty[2] * - 1
		
		BettyBones[BettyBone].setEuler(eulerBetty, mode)
	
def run_test():
	vizact.ontimer(0, reflect)	

viztask.schedule(run_test)
Reply With Quote