•      Sign In
• Create Account

# Rotating Weapon Gradually To Look at Target Point

6 replies to this topic

### #1Medo3337  Members   -  Reputation: 665

Like
0Likes
Like

Posted 02 July 2014 - 06:35 PM

I have a weapon mesh, how do I make it rotate GRADUALLY to look at the player (target)?

I want to update pitch, yaw, roll gradually and find out when the rotation is done.

Edited by Medo3337, 02 July 2014 - 06:36 PM.

Sponsor:

### #2Buckeye  Crossbones+   -  Reputation: 3990

Like
5Likes
Like

Posted 02 July 2014 - 06:45 PM

It might be easier to use D3DXQUATERNION. Calculate a quaternion reflecting the current mesh orientation [ you could use D3DXQuaternionRotationYawPitchRoll(...) to start with ], named, for instance, startQuat. Calculate a second quaternion for the desired orientation (pointing at the target) named, for instance, finalQuat.

Use a quaternion named, for instance, meshQuat, for orienting the weapon mesh.

Then use D3DXQuaternionSlerp( &meshQuat, &startQuat, &finalQuat, delta ), where delta is incremented at your desired "gradual" rate from 0 to 1, perhaps a function of elapsed time or incremented by a delta-time from your render loop. When delta==1.0f, the rotation is done.

EDIT: For the weapon mesh orientation each frame, you can convert with D3DXMatrixRotationQuaternion(&meshMatrix, &meshQuat);

Edited by Buckeye, 02 July 2014 - 06:50 PM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

### #3Medo3337  Members   -  Reputation: 665

Like
0Likes
Like

Posted 02 July 2014 - 07:38 PM

@Buckeye: If I have the target point that the weapon mesh should look at, how do I calculate finalQuat?

### #4L. Spiro  Crossbones+   -  Reputation: 12675

Like
4Likes
Like

Posted 02 July 2014 - 08:00 PM

how do I make it rotate GRADUALLY to look at the player (target)?

First, your primary inputs are the gun position and the target position.
From there you can derive the vectors needed to make the gun face directly at the target position easily:
vForward = vTargetPos - vGunPos;
vRight = Vector( 0, 1, 0 ) % vForward; // % = cross product.
vUp = vForward % vRight;

vRight.Normalize();    // Matrix row 0.
vUp.Normalize();       // Matrix row 1.
vForward.Normalize();  // Matrix row 2.
vGunPos;               // Matrix row 3.
But your problem is to look that way slowly.
It’s very simple.
Add another input: Current target.

Process:
Your gun is facing a certain direction. The target and curTarget values are the same.
Suddenly you want to lock onto another object.
#1: Set target to the new target location.
#2: Each from, move curTarget closer and closer towards target.
#3: Use the above math, but instead of looking at target, look at curTarget.

This is the most stable way to achieve your goal.
target can move as much as it wants and your gun will always smoothly try to catch up to it.

There is no need for advanced math or quaternions, and you can use the vRight, vUp, vForward, and vGunPos vectors to directly create the gun’s world matrix.

L. Spiro

Edited by L. Spiro, 02 July 2014 - 08:02 PM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

### #5Dirk Gregorius  Members   -  Reputation: 728

Like
0Likes
Like

Posted 02 July 2014 - 10:34 PM

The easiest way is to use linear interpolation:

Vector3 CurrentDirection = /* Get current direction */

Vector3 TargetDirection = /* Get target direction */

float Alpha = 0.5f; // Use smaller values for slower rotations (e.g. based on the weapon weight).

Vector3 NewDirection = ( 1.0f - Alpha ) * CurrentDirection + Alpha * TargetDirection;

This method has exponential decay (e.g. you multiply by 0.5 * 0.5 * 0.5 * ...) and rotates pretty fast against the target direction. A value of Alpha = 0.5 is pretty responsive and snappy which is what you very likely look for. This formula works best with constant time steps. If you have varying time steps you would need to multiply by the ratio of the current and last time step.

I tested some methods lately for something similar and this discrete evolution worked best for me. Though there are other good methods and L. Spiro suggestion will work great as well. I personally liked the exponential decay better than linear error reduction, but this is a matter of personal choice I guess.

HTH,

-Dirk

PS:

In order to update your current rotation you can compute the shortest arc quaternion between the current and new direction:

Quaternion Rotation = ShortestArc( CurrentDirection, NewDirection );

Quaternion NewOrientation = Roation * CurrentOrientation;

Stan Melax wrote a good article about this in Game Programming Gems 1. Google for shortest arc quaternion and you will find some implementations.

Edited by Dirk Gregorius, 02 July 2014 - 10:36 PM.

### #6Medo3337  Members   -  Reputation: 665

Like
0Likes
Like

Posted 02 July 2014 - 11:11 PM

@L. Spiro: How do I get pitch, yaw, roll from vRight, vUp, vForward?

How do I calculate the current target based on the gun position and the final target so I can rotate gradually?

### #7L. Spiro  Crossbones+   -  Reputation: 12675

Like
0Likes
Like

Posted 02 July 2014 - 11:24 PM

Why do you need yaw, roll, and pitch? If you need these it generally means you are doing it wrong.
Anyway, I already gave you the rotation matrix, so:
http://planning.cs.uiuc.edu/node103.html

Updating currentTarget (as an example):
#define MAX_UPDATE_DIST 2.0f
Vector vToTarget = (target - currentTarget);
Vector vAmountToMove = vToTarget;
vAmountToMove.Normalize();
vAmountToMove *= fDeltaTime;       // * is NOT dot-product, it is a regular per-component scalar multiply.
vAmountToMove *= MAX_UPDATE_DIST;  // * is NOT dot-product, it is a regular per-component scalar multiply.
if ( vAmountToMove.LengthSquared() >= vToTarget.LengthSquared() ) {
currentTarget = target;
}
else {
currentTarget += vAmountToMove;
}

L. Spiro

Edited by L. Spiro, 02 July 2014 - 11:33 PM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

PARTNERS