Page 1 of 1

[Semi-Solved] Bone Pitch problem | Quaternion flipping

Posted: Mon Jun 17, 2013 4:13 pm
by Mind Calamity
Hello guys, I've been trying to get my character to look at where the crosshair is pointing, and for that I need to manually control my hips bone, I do so like this:

Code: Select all

		// mDirection is the direction of the character
		Vector3 boneDir = getBoneWorldOrientation(mEntity, mHips) * mDirection;
		// This is the direction of the crosshair
 		Vector3 dir = mCameraTrans->_getDerivedDirection();
		Quaternion rot = boneDir.getRotationTo(dir);

		// The code below has been taken from the sinbad character controller and adapted to pitch, instead of yaw
		Real pitchToGoal = rot.getPitch().valueDegrees();
 		Real pitchAtSpeed = pitchToGoal / Ogre::Math::Abs(pitchToGoal) * timeSinceLastUpdate * 100.0f;
		if (pitchToGoal < 0) pitchToGoal = std::min<Real>(0, std::max<Real>(pitchToGoal, pitchAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
		else if (pitchToGoal > 0) pitchToGoal = std::max<Real>(0, std::min<Real>(pitchToGoal, pitchAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
 		mHips->pitch(Degree(pitchToGoal));
Unfortunately I'm not that good with Vector/Quaternion math, and I get the following bug:
[youtube]IwUpzEE3uwI[/youtube]
It seems to work properly on +Z, it's shaking a bit on -Z, and it just continues to rotate on +X/-X.

I hope someone can help. :)

EDIT: I've sorta fixed this, see my second post.
Also, I've mirrored my topic to GameDev.net, you can find the topic here: http://www.gamedev.net/topic/644417-vec ... on-vector/

Re: Help with Quaternion/Vector math - bone pitch to directi

Posted: Tue Jun 18, 2013 9:53 am
by Daixiwen
To help debug your code, could you try and printout the contents of the boneDir and dir vectors, to check that they have the expected values? Either by printing something on the hud or have your code regularly print them on the console.

Re: Help with Quaternion/Vector math - bone pitch to directi

Posted: Tue Jun 18, 2013 6:24 pm
by Syniurge
Any reason why you are changing the pitch only and not the yaw?

Something like:

Code: Select all

      // mDirection is the direction of the character
      Vector3 boneDir = getBoneWorldOrientation(mEntity, mHips) * mDirection;
      // This is the direction of the crosshair
      Vector3 dir = mCameraTrans->_getDerivedDirection();
      Quaternion rot = boneDir.getRotationTo(dir);

      Vector3 rotAxis;
      Degree rotAngle, minAngle, maxAngle;
      rot.ToAngleAxis(rotAngle, rotAxis);  // rotAngle is set somewhere between 0 and 360 by ToAngleAxis()
      if (rotAngle.valueDegrees() <= 180.0f) {
        minAngle = 0.0f; maxAngle = rotAngle;
        rotAngle = 1.0f;
      } else {
        minAngle = rotAngle - 360.0f; maxAngle = 0.0f;
        rotAngle = -1.0f;
      }

      rotAngle *= timeSinceLastUpdate * 100.0f;
      mHips->rotate(Quaternion(Radian(Math::Clamp(rotAngle, minAngle, maxAngle)), rotAxis));
should orientate your bone towards dir.

Re: [Semi-Solved] Bone Pitch problem | Quaternion flipping

Posted: Wed Jun 19, 2013 12:31 am
by Mind Calamity
Thanks alot for the replies.

Unfortunately, Syniurge your code didn't work, it was just rotating again, except now it was rotating in all directions and not keeping to the proper direction at all.

I've kinda solved this myself by adapting the Camera::setDirection code from OGRE to work for my need:

Now I have the following code:

Code: Select all

	Vector3 boneDir = getBoneWorldOrientation(mEntity, mHips) * Vector3::UNIT_Z; //mDirection;
	Vector3 dir = mCameraTrans->_getDerivedDirection();

	Vector3 zAdjustVec = dir;
	zAdjustVec.normalise();

	Quaternion targetWorldOrientation;

	Vector3 xVec = Vector3::UNIT_Y.crossProduct(zAdjustVec);
	xVec.normalise();

	Vector3 yVec = zAdjustVec.crossProduct(xVec);
	yVec.normalise();

	targetWorldOrientation.FromAxes(xVec, yVec, zAdjustVec);

	// mTransform is basically the SceneNode of the character, I'm multiplying the target orientation with it's inverse orientation to get it to parent/character-space.
	mHips->_setDerivedOrientation(mTransform->_getDerivedOrientation().Inverse() * targetWorldOrientation);
The above code was taken from OgreCamera.cpp, the setDirection function, the part with the fixed yaw axis.
Now, that works... Sorta, I now get this problem at near-90 degree pitch, the orientation kind of flips to the other side, I've made another video to showcase this:

[youtube]6bdFhW_vtUs[/youtube]

Any ideas on how to fix this ?