|
-
Sep 14th, 2009, 12:30 PM
#1
Thread Starter
Lively Member
XNA: Quaternion from two Vector3s
Working from the XNA aiming sample and trying to convert it to 3d...
I have a rotating gun turret that I'm trying to turn to point at a moving ship, but it's not quite working as I expected it to. I'm taking the angle between two Vector3s (representing the turret and ship positions) along each of the 3 axes, create a rotation matrix and generate a quaternion that I can apply to the turret to point it at the ship. Two questions:
What am I doing wrong?
Is there an easier way to do this?
position = turret position
aimAtThis = ship position
Code:
Quaternion Target3D(Vector3 position, Vector3 aimAtThis)
{
float x = aimAtThis.X - position.X;
float y = aimAtThis.Y - position.Y;
float z = aimAtThis.Z - position.Z;
float xAngle = WrapAngle((float)Math.Atan2(z, y));
float yAngle = WrapAngle((float)Math.Atan2(z, x));
float zAngle = WrapAngle((float)Math.Atan2(y, x));
Matrix m = Matrix.CreateRotationX(xAngle) *
Matrix.CreateRotationY(yAngle) *
Matrix.CreateRotationZ(zAngle);
Quaternion q = Quaternion.CreateFromRotationMatrix(m);
return q;
}
float WrapAngle(float radians)
{
while (radians < -MathHelper.Pi)
{
radians += MathHelper.TwoPi;
}
while (radians > MathHelper.Pi)
{
radians -= MathHelper.TwoPi;
}
return radians;
}
Thanks.
-
Sep 15th, 2009, 01:53 PM
#2
Re: XNA: Quaternion from two Vector3s
You say it's not quite working as you expect it to. What is it doing exactly?
In the meantime, try this code:
Code:
private Quaternion GetRotation(Vector3 src, Vector3 dest)
{
src.Normalize();
dest.Normalize();
float d = Vector3.Dot(src, dest);
if (d >= 1f)
{
return Quaternion.Identity;
}
else if (d < (1e-6f - 1.0f))
{
Vector3 axis = Vector3.Cross(Vector3.UnitX, src);
if (axis.LengthSquared() == 0)
{
axis = Vector3.Cross(Vector3.UnitY, src);
}
axis.Normalize();
return Quaternion.CreateFromAxisAngle(axis, MathHelper.Pi);
}
else
{
float s = (float)Math.Sqrt((1 + d) * 2);
float invS = 1 / s;
Vector3 c = Vector3.Cross(src, dest);
Quaternion q = new Quaternion(invS * c, 0.5f * s);
q.Normalize();
return q;
}
}
Last edited by Jenner; Sep 15th, 2009 at 02:38 PM.
-
Sep 16th, 2009, 11:40 AM
#3
Thread Starter
Lively Member
Re: XNA: Quaternion from two Vector3s
 Originally Posted by Jenner
You say it's not quite working as you expect it to. What is it doing exactly?
It's rotating, but nowhere near the way I expected it to.
I tried your code, but now it does not rotate at all. I guess I need to do more homework...
-
Sep 16th, 2009, 02:52 PM
#4
Re: XNA: Quaternion from two Vector3s
Yea, I've been doing some sample apps as well but I have yet to find a single, clear-cut example of how to do this. The code I found will rotate for me, as long as the source model isn't at position 0,0,0. Then it crashes.
I can rotate it via vectors alone, but this creates gimble-lock.
I'll keep poking at it though and see if I can't get it working because I have a similar problem in a game I'm designing too.
-
Sep 20th, 2009, 01:46 AM
#5
New Member
Re: XNA: Quaternion from two Vector3s
wow progamming game ! i try , i try
-
Sep 21st, 2009, 07:52 AM
#6
Re: XNA: Quaternion from two Vector3s
Ok, best I figure on this problem is this:
#1) You have to translate the positional vectors to the grid origin (0,0,0) first. If your positional vector of your turret is at 1,2,0 and your ship at 15,32,10, you need to subtract them prior to the rotation: (15,32,10) - (1,2,0) = (14, 30, 10) Use this positional coordinate in your calculation.
#2) A quaternion needs two things now, an axis of rotation, and an angle. The axis is easy because you have two vectors to work with: The ROTATIONAL vector of the turret (i.e. the vector describing the direction it's pointing, not the vector describing it's position in 3D space) and the POSITIONAL vector of your ship, that you just offset in #1.
Take the cross product, and you get a new vector that's perpendicular to the two, so you just need: axisVector = Vector3.Cross(turretHeadingVector, shipOffsetPositionVector)
#3) Now you just need the angle between the two vectors, and this is also simple, take the dot product of the same two vectors and then the acos of that to get the angle: angle = Math.Acos(Vector3.Dot(turretHeadingVector, shipOffsetPositionVector))
#4) Now, just build your quaternion using the axis, angle method: Quaternion.CreateFromAxisAngle(axisVector, angle)
The best I can tell, this is the simplest method of doing this. Now, there are some issues you need to know and program around, such as some "0" conditions like if the vectors are 180 degrees apart, but if your turret has a limited field of fire, it won't be tracking objects in that coordinate zone anyways.
-
Sep 22nd, 2009, 12:54 PM
#7
Thread Starter
Lively Member
Re: XNA: Quaternion from two Vector3s
 Originally Posted by Jenner
#1) You have to translate the positional vectors to the grid origin (0,0,0) first. If your positional vector of your turret is at 1,2,0 and your ship at 15,32,10, you need to subtract them prior to the rotation: (15,32,10) - (1,2,0) = (14, 30, 10) Use this positional coordinate in your calculation.
Okay, that's easy enough:
Code:
Vector3 translatedPos = aimAtThis - position;
 Originally Posted by Jenner
#2) A quaternion needs two things now, an axis of rotation, and an angle. The axis is easy because you have two vectors to work with: The ROTATIONAL vector of the turret (i.e. the vector describing the direction it's pointing, not the vector describing it's position in 3D space) and the POSITIONAL vector of your ship, that you just offset in #1.
Take the cross product, and you get a new vector that's perpendicular to the two, so you just need: axisVector = Vector3.Cross(turretHeadingVector, shipOffsetPositionVector)
Here's my problem. How do I get the rotational vector of the turret from the positional vectors of the turret and ship?
-
Sep 22nd, 2009, 03:40 PM
#8
Re: XNA: Quaternion from two Vector3s
Yea, that was my problem too. It's more or less a unit-vector, since all you're interested in is it's components. All game-engine systems, when dealing with models have some manner to control position (typically a Vector3), and some manner to control rotation (possibly a rotation matrix or a quaternion or a Vector3 unit vector). Do you know how to get any rotational information from your models and what form it takes?
See, the POSITIONAL vector of the turret is pointless, since you've translated it to 0, 0, 0 anyways! In fact, ANY object you're trying to figure a rotation about will effectively be at 0, 0, 0. If your turret was pointed straight down the X-axis of your world grid and nowhere else, it would be a ROTATIONAL vector (1, 0, 0); it would never be 0, 0 ,0 though since it can never point nowhere.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|