FIRE-30873: first pass at swapping axes for the UI control
parent
8c010617e6
commit
327bb00c7e
|
|
@ -908,14 +908,6 @@ void FSFloaterPoser::onAvatarPositionSet()
|
|||
setSelectedJointsPosition(posX, posY, posZ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The trackball controller is not friendly to photographers (or normal people).
|
||||
/// This method could be streamlined but at the high cost of picking apart what it does.
|
||||
/// The simplest thing to do would be to reimplement the code behind the slider!
|
||||
/// TLDR: we just want the trackball to behave like a 2-axis slider.
|
||||
///
|
||||
/// BEWARE! Changes to behaviour here require their inverse to be applied on the slider-callback.
|
||||
/// </summary>
|
||||
void FSFloaterPoser::onLimbTrackballChanged()
|
||||
{
|
||||
FSVirtualTrackpad *trackBall = getChild<FSVirtualTrackpad>(POSER_AVATAR_TRACKBALL_NAME);
|
||||
|
|
|
|||
|
|
@ -99,7 +99,34 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joi
|
|||
return vec3;
|
||||
|
||||
LLQuaternion rot = avJoint->getRotation();
|
||||
rot.getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]);
|
||||
|
||||
return translateRotationFromQuaternion(joint.boneTranslation(), rot);
|
||||
}
|
||||
|
||||
// from the bone to the UI; this is the 'forwards' use of the enum
|
||||
LLVector3 FSPoserAnimator::translateRotationFromQuaternion(E_BoneAxisTranslation translation, LLQuaternion rotation)
|
||||
{
|
||||
LLVector3 vec3;
|
||||
|
||||
switch (translation)
|
||||
{
|
||||
case SWAP_YAW_AND_ROLL:
|
||||
rotation.getEulerAngles(&vec3.mV[VY], &vec3.mV[VZ], &vec3.mV[VX]);
|
||||
break;
|
||||
|
||||
case SWAP_YAW_AND_PITCH:
|
||||
rotation.getEulerAngles(&vec3.mV[VZ], &vec3.mV[VX], &vec3.mV[VY]);
|
||||
break;
|
||||
|
||||
case SWAP_ROLL_AND_PITCH:
|
||||
rotation.getEulerAngles(&vec3.mV[VX], &vec3.mV[VY], &vec3.mV[VZ]);
|
||||
break;
|
||||
|
||||
case SWAP_NOTHING:
|
||||
default:
|
||||
rotation.getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]);
|
||||
break;
|
||||
}
|
||||
|
||||
return vec3;
|
||||
}
|
||||
|
|
@ -115,10 +142,38 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar *avatar, const FSPoserJoint *j
|
|||
if (!avJoint)
|
||||
return;
|
||||
|
||||
LLMatrix3 rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VY], rotation.mV[VZ]);
|
||||
LLQuaternion rot_quat = translateRotationToQuaternion(joint->boneTranslation(), rotation);
|
||||
avJoint->setRotation(rot_quat);
|
||||
}
|
||||
|
||||
// from the UI to the bone, the inverse translation, the un-swap, the backwards
|
||||
LLQuaternion FSPoserAnimator::translateRotationToQuaternion(E_BoneAxisTranslation translation, LLVector3 rotation)
|
||||
{
|
||||
LLMatrix3 rot_mat;
|
||||
switch (translation)
|
||||
{
|
||||
case SWAP_YAW_AND_ROLL:
|
||||
rot_mat = LLMatrix3(rotation.mV[VZ], rotation.mV[VY], -1 * rotation.mV[VX]);
|
||||
break;
|
||||
|
||||
case SWAP_YAW_AND_PITCH:
|
||||
rot_mat = LLMatrix3(rotation.mV[VY], rotation.mV[VX], rotation.mV[VZ]);
|
||||
break;
|
||||
|
||||
case SWAP_ROLL_AND_PITCH:
|
||||
rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VZ], rotation.mV[VY]);
|
||||
break;
|
||||
|
||||
case SWAP_NOTHING:
|
||||
default:
|
||||
rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VY], rotation.mV[VZ]);
|
||||
break;
|
||||
}
|
||||
|
||||
LLQuaternion rot_quat;
|
||||
rot_quat = LLQuaternion(rot_mat) * rot_quat;
|
||||
avJoint->setRotation(rot_quat);
|
||||
|
||||
return rot_quat;
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointScale(LLVOAvatar *avatar, FSPoserJoint joint)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,20 @@ typedef enum E_BoneDeflectionStyles
|
|||
SYMPATHETIC = 2, // change the other joint, but opposite to a mirrored way, eg: both go right or both go left
|
||||
} E_BoneDeflectionStyles;
|
||||
|
||||
/// <summary>
|
||||
/// When we're going from bone-rotation to the UI sliders, some of the axes need swapping so they make sense in UI-terms.
|
||||
/// eg: for one bone, the X-axis may mean up and down, but for another bone, the x-axis might be left-right.
|
||||
/// These are translations of bone-TO-UI; an inverse translation needs to happen the other way.
|
||||
/// It would be nice if these were defined in XML; but then they're not const, and I want const.
|
||||
/// </summary>
|
||||
typedef enum E_BoneAxisTranslation
|
||||
{
|
||||
SWAP_NOTHING = 0,
|
||||
SWAP_YAW_AND_ROLL = 1,
|
||||
SWAP_YAW_AND_PITCH = 2,
|
||||
SWAP_ROLL_AND_PITCH = 3,
|
||||
} E_BoneAxisTranslation;
|
||||
|
||||
class FSPoserAnimator
|
||||
{
|
||||
public:
|
||||
|
|
@ -73,6 +87,7 @@ public:
|
|||
std::string _jointName; // expected to be a match to LLJoint.getName() for a joint implementation.
|
||||
std::string _mirrorJointName;
|
||||
E_BoneTypes _boneList;
|
||||
E_BoneAxisTranslation _boneTranslation;
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the name of the joint.
|
||||
|
|
@ -89,6 +104,11 @@ public:
|
|||
/// </summary>
|
||||
E_BoneTypes boneType() const { return _boneList; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the E_BoneAxisTranslation of the joint.
|
||||
/// </summary>
|
||||
E_BoneAxisTranslation boneTranslation() const { return _boneTranslation; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a PoserJoint.
|
||||
/// </summary>
|
||||
|
|
@ -99,11 +119,12 @@ public:
|
|||
/// </param>
|
||||
/// <param name="b">The opposite joint name, if any. Also expected to be a well-known name.</param>
|
||||
/// <param name="c">The </param>
|
||||
FSPoserJoint(std::string a, std::string b, E_BoneTypes c)
|
||||
FSPoserJoint(std::string a, std::string b, E_BoneTypes c, E_BoneAxisTranslation d = SWAP_NOTHING)
|
||||
{
|
||||
_jointName = a;
|
||||
_mirrorJointName = b;
|
||||
_boneList = c;
|
||||
_boneTranslation = d;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +143,7 @@ public:
|
|||
/// </remarks>
|
||||
const std::vector<FSPoserJoint> PoserJoints {
|
||||
// head, torso, legs
|
||||
{"mPelvis", "", WHOLEAVATAR}, {"mTorso", "", BODY}, {"mChest", "", BODY}, {"mNeck", "", BODY}, {"mHead", "", BODY},
|
||||
{"mPelvis", "", WHOLEAVATAR}, {"mTorso", "", BODY, SWAP_YAW_AND_ROLL}, {"mChest", "", BODY}, {"mNeck", "", BODY}, {"mHead", "", BODY},
|
||||
{"mCollarLeft", "mCollarRight", BODY}, {"mShoulderLeft", "mShoulderRight", BODY}, {"mElbowLeft", "mElbowRight", BODY}, {"mWristLeft", "mWristRight", BODY},
|
||||
{"mCollarRight", "mCollarLeft", BODY}, {"mShoulderRight", "mShoulderLeft", BODY}, {"mElbowRight", "mElbowLeft", BODY}, {"mWristRight", "mWristLeft", BODY},
|
||||
{"mHipLeft", "", BODY}, {"mKneeLeft", "", BODY}, {"mAnkleLeft", "", BODY},
|
||||
|
|
@ -269,6 +290,23 @@ public:
|
|||
private:
|
||||
bool _currentlyPosingSelf = false;
|
||||
|
||||
/// <summary>
|
||||
/// Translates a rotation vector from the UI to a Quaternion for the bone.
|
||||
/// This also performs the axis-swapping the UI needs for up/down/left/right to make sense.
|
||||
/// </summary>
|
||||
/// <param name="translation">The axis translation to perform.</param>
|
||||
/// <param name="rotation">The rotation to transform to quaternion.</param>
|
||||
/// <returns>The rotation quaternion.</returns>
|
||||
LLQuaternion translateRotationToQuaternion(E_BoneAxisTranslation translation, LLVector3 rotation);
|
||||
|
||||
/// <summary>
|
||||
/// Translates a bone-rotation quaternion to a vector usable easily on the UI.
|
||||
/// </summary>
|
||||
/// <param name="translation">The axis translation to perform.</param>
|
||||
/// <param name="rotation">The rotation to transform to matrix.</param>
|
||||
/// <returns>The rotation vector.</returns>
|
||||
LLVector3 translateRotationFromQuaternion(E_BoneAxisTranslation translation, LLQuaternion rotation);
|
||||
|
||||
// public:
|
||||
// static LLMotion *create(const LLUUID &id) { return new FSPoserAnimator(id); }
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ public:
|
|||
Optional<LLViewBorder::Params> border;
|
||||
Optional<LLUIImage *> image_moon_back, image_moon_front, image_sphere, image_sun_back, image_sun_front;
|
||||
Optional<bool> pinch_mode;
|
||||
Optional<bool> allow_drag_outside;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -594,10 +594,10 @@ width="565">
|
|||
left_delta="0"
|
||||
top_pad="2"
|
||||
width="200">Up/Down:</text>
|
||||
<slider decimal_digits="0"
|
||||
<slider decimal_digits="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
increment="1"
|
||||
increment="0.1"
|
||||
initial_value="0"
|
||||
layout="topleft"
|
||||
left_delta="5"
|
||||
|
|
@ -614,10 +614,10 @@ width="565">
|
|||
left_delta="-5"
|
||||
top_pad="0"
|
||||
width="200">Left/Right:</text>
|
||||
<slider decimal_digits="0"
|
||||
<slider decimal_digits="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
increment="1"
|
||||
increment="0.1"
|
||||
initial_value="0"
|
||||
layout="topleft"
|
||||
left_delta="5"
|
||||
|
|
@ -634,10 +634,10 @@ width="565">
|
|||
left_delta="-5"
|
||||
top_pad="-1"
|
||||
width="200">Roll:</text>
|
||||
<slider decimal_digits="0"
|
||||
<slider decimal_digits="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
increment="1"
|
||||
increment="0.1"
|
||||
initial_value="0"
|
||||
layout="topleft"
|
||||
left_delta="5"
|
||||
|
|
|
|||
Loading…
Reference in New Issue