(This is a bit of long post but I would be really greatful if someone could shed some light on this issue, its more about visualising the co-ordinate system in Panda)
A slight problem with getting my head around rotation co-ordinates in relation to bone orientation.
If I set up a T-pose skeleton in Max and import into Panda, it seems the .egg file will store each bone with an orientation that matches that bone orientation in Max. It seems as though a bone with Hpr(0,0,0) will be pointing to the right and facing the sky. So my chest bone that faces forwards (towards the screen) and points upwards (inside Max), is stored with a default orientation as (90,0,-90) in the .egg file so Panda can display the bone correctly.
Ok, this is fine but what happens when I want to feed in rotational values to this bone? I want to move the bone +10degrees around the Z-axis.
hips.setHpr(10,0,0) = FAIL (the bone moves plus 10degrees around the Z-axis but in relation to the default bone position: pointing to the right and facing up + 10degrees in Z)
So I must:
self.hipsChannelOrder.setHpr(self.float[5],self.float[4],self.float[3])
self.hipsCorrection.setHpr(self.hipsChannelOrder, 90,0,-90)
This yields the correct result.
Now what is strange and what I cannot figure out:
The child of this bone, chest, is already aligned correctly (pointing up, facing forward) because it has enherited the ‘hipsCorrection’ from the Hips bone. However, to now rotate around the Z-axis I must apply values to the ‘Pitch’ axis (rotations around X) instead of ‘Heading’ (rotations around Z):
self.chestC.setHpr(Point3(self.float[33],self.float[35],self.float[34]*-1))
self.neckC.setHpr(Point3(self.float[60],self.float[62],self.float[61]*-1))
self.headC.setHpr(Point3(self.float[63],self.float[65],self.float[64]*-1))
I must multiply the value in ‘Roll’ by -1 to yield a correct result. Local co-ordinate space is changing but how comes it doesn’t affect the bone which I applied the transformation to but it does to its children? Does anyone know how this transformation or any transformation for that matter affects co-ordinate space. If I rotate by (90,180,90) how does that affect Hpr? The hpr directions are obviously changing (i did a little experiment).
These values are being inserted into the float array from a BVH file. (BVH Rot order = ZXY:
float[3] = hips Z
float[4] = hips X
float[5] = hips Y
float[33] = chest Z
float[34] = chest X
float[35] = chest Y etc)
The order of ZXY remains constant throughout the file.
I understand that the co-ordinate system from the BVH must be matched to Panda. So maybe the channels arn’t applied Hpr(float[3],float[4],float[5]) but perhaps Hpr[float[4],float[3].float[5]*-1) to match t he co-ordinate space.
WHAT I DONT GET:
BUT i do not understand why the order changes when I rotate a bone to give it that correct first orientation?
Plus, the Hpr order on the bone i rotate (hips) stays the same but it is the child(ren) whose co-ordinate system changes!
Does anyone understand what I’m trying to illustrate? My BVH values map correctly to my character and it looks awesome but there is no logic to the order and I must get my head around these bone orientations. Getting the hips and chest working wasn’t too much effort but once 90degree changes happen for both shoulders then both upperArms (to get into the T-pose) it gets crazily confusing. Plus the foreArms needed crazy default orientations to work even though they face the same direction as their parent.
#Apply the data to model
def applyMotion(self):
#Hips
#Channel order BVH: ZXY
#To convert to Panda: Hpr(Y,Z,X)
self.leftH.setHpr(self.float[5],self.float[3],self.float[4])
#This correction must be made to orientate the bone correctly
self.hipsC.setHpr(self.leftH, 90,0,-90)
#Chest
#Channel order must now change to Hpr(Z,Y,X*-1) to display correctly???
#No correction is needed as the bone is orientated correctly (following the correction applied to its parent - self.hips)
self.chestC.setHpr(Point3(self.float[33],self.float[35]*-1,self.float[34]*-1))
#Neck
#Channel order same as Chest
self.neckC.setHpr(Point3(self.float[60],self.float[62],self.float[61]*-1))
#Head
#Channel order same as Chest
self.headC.setHpr(Point3(self.float[63],self.float[65],self.float[64]*-1))
#LeftShoulder
#Channel order doesn't change although we have orientated the bone differently!:
self.leftH.setHpr(self.float[36],self.float[38],self.float[37]*-1)
#This correction must be applied to orientate the bone correctly
self.leftShoulderC.setHpr(-90,0,0)
#LeftArm
#Channel order changes!
self.leftA.setHpr(self.float[39],self.float[40],self.float[41])
#Channel correction must be applied to orientate the bone correctly
self.leftArmC.setHpr(self.leftA, -90,0,0)
#LeftForeArm
#Although this bone is facing in the same direction as leftArm we must do some crazy things with Hpr to display properly!
#First correction
self.leftForeArmC.setHpr(90,180,0)
#Apply channels
self.leftA.setHpr(self.leftForeArmC,self.float[44],self.float[43],self.float[42])
#Second correction
self.leftForeArmC.setHpr(self.leftA, 90,180,0)
#Left Hand
#Channel order different again!
self.leftHandC.setHpr(Point3(self.float[45],self.float[47]*-1,self.float[46]))
#Right Shoulder
self.rightS.setHpr(self.float[48],self.float[50],self.float[49]*-1)
self.rightShoulderC.setHpr(self.rightS, 90,0,0)
#Right Arm
self.rightS.setHpr(self.float[51],self.float[52]*-1,self.float[53]*-1)
self.rightArmC.setHpr(self.rightS, 90,0,0)
#Right ForeArm
self.rightForeArmC.setHpr(90,180,0)
self.rightS.setHpr(self.rightForeArmC, self.float[56],self.float[55],self.float[54])
self.rightForeArmC.setHpr(self.rightS, 90, 180,0)
#Right Arm
self.rightHandC.setHpr(Point3(self.float[58],self.float[59],self.float[57]))
Could using Quaternions be an answer? The foreArms didn’t require initial orientation and I believe that I got the channel order correct but flipping occured at certain angles, I think this might have been due to gimble lock or the fact that with euler’s: (X=90,Y=180,Z=100) != (Y=180,Z=100,X=90) Anyhow I had to mess around with the orientation so that I could apply the channel’s in a differently order…make sense? though not.
No, seriously, if anyone has had any experience with what I’m talking about please shed some light on this issue!?
Thankyou.
Could someone shed some light on this please?