WorldViz User Forum avatar and her reflection
 User Name Remember Me? Password
 Register FAQ Search Today's Posts Mark Forums Read

#1
02-14-2014, 06:09 AM
 AntoniaHamilton Member Join Date: Mar 2013 Posts: 4
avatar and her reflection

Hi,

i'm trying to create a scene with two avatars who mirror each other (e.g. Anna raises her R hand, Betty raises her left hand, with no visible mirror). I've tried a variety of ways to copy Anna's bones or actions onto Betty, and can't get any to work.

The code below is what I *thought* should work - it premultiplies the full Position/Quaterion matrix for each bone by the appropriate transformation matrix. But it isn't giving me the right thing. The commented out version doesn't work either.

So I hope someone can help. Is this the right approach? Is there something silly wrong here? Or is there a different solution all together?

Thanks

Antonia

----------------------------------------

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()

Anna.setPosition([0,0,-1])
Anna.setEuler([0,0,0])
Anna.state(15)

Betty.setPosition([0,0,1])
Betty.setEuler([0,0,0])
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 boneName in BettyBones:

p = AnnaBones[boneName].getPosition(mode)
q = AnnaBones[boneName].getQuat(mode)
t = AnnaBones[boneName].getMatrix(mode)

print '----------------'
print mode
print p
print q
print t

# s = vizmat.Transform()
# s.makeScale(1,-1,1)
# t.preMult(s)
# print t
# BettyBones[boneName].setMatrix(t,mode)

orig = np.array([ [p[0], 0, 0, q[0]], [0, p[1], 0, q[1]], [0, 0, p[2], q[2]], [0, 0, 0, q[3]] ])
rmat = np.array([ [ 1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1] ])

nnn = np.dot(rmat,orig) #pre-multiply the original by the transform

newp = np.array([ nnn[0,0], nnn[1,1], nnn[2,2] ])
newq = np.array([ nnn[0,3], nnn[1,3], nnn[2,3], nnn[3,3] ])

BettyBones[boneName].setPosition(newp.tolist(),mode)
BettyBones[boneName].setQuat(newq.tolist(),mode)

def run_test():
vizact.ontimer(0, reflect)

#2
02-21-2014, 01:58 AM
 Frank Verberne 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.setPosition([0,0,-1])
Anna.setEuler([0,0,0])
Anna.state(15)

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)

#3
02-21-2014, 02:14 AM
 Frank Verberne Member Join Date: Mar 2008 Location: Netherlands Posts: 148
I was partly wrong about the position of the bones. You don't need to mirror the position of every bone, but only the position of the pelvisbone. The code below should work with any avatar with a pelvisbone named 'Bip01 Pelvis' (so at least every Complete Character from Vizard). And, now the position of the avatar is also mirrored!

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 '
PELVIS_BONE_NAME = 'Bip01 Pelvis'

Anna.setPosition([0,0,-1])
Anna.setEuler([0,0,0])
Anna.state(2)

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)
posAnna = AnnaBones[PELVIS_BONE_NAME].getPosition(mode)

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

eulerBetty = eulerAnna
eulerBetty[0] = eulerBetty[0] * -1
eulerBetty[2] = eulerBetty[2] * -1

posBetty = posAnna
posBetty[0] = posBetty[0] * -1

BettyBones[BettyBone].setEuler(eulerBetty, mode)
BettyBones[PELVIS_BONE_NAME].setPosition(posBetty, mode)

def run_test():
vizact.ontimer(0, reflect)

Last edited by Frank Verberne; 02-21-2014 at 02:18 AM.
#4
02-21-2014, 02:52 AM
 AntoniaHamilton Member Join Date: Mar 2013 Posts: 4
Thank you, that is very helpful.

 Thread Tools Display Modes Rate This Thread Hybrid Mode Rate This Thread: 5 : Excellent 4 : Good 3 : Average 2 : Bad 1 : Terrible

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home Getting Vizard Help with AI Announcements Vizard Precision Position Tracker (PPT) Plug-in development

All times are GMT -7. The time now is 04:18 PM.

 Contact Us - WorldViz Home - Archive - Top