# Thread: Direction between 2 Vectors

1. That sounds good, but I seem to be having a lot of problems trying to incorporate this into my camera class, could you give some example? I appreciate the help. Thanks

I have made some changes and changed the lerp call to some linear interpolation which is working very smoothly and looks fantastic, i will post the code tomorrow when i'm able.  Reply With Quote

2. well first of all remove the interpolation and make sure everything is working like this:
rotation := rV;  Reply With Quote

3. Hello Dan, Yes it does work fine, expect still the limitation on the Y axis,

However after a bit testing i see the problem is on the xz rotation it takes 2*PI for full rotation, on the Y Axis, it would technically take 4*PI, so instead i will do a basic test for flipping the camera, and changing the right and up vectors so the view will then be upside down.  Reply With Quote

4. OK i have my camera system working exactly how i want it except for 1 problem, I have uploaded test build, press N to spawn a ball, then if you press down and to the left so the ball rolls around the camera will at 1 point spin in the opposite direction back to the ball.

New code:

Code:
```//
// sets the look at target of the camera
//
procedure TCameraController.setTarget(const targ: TD3DXMatrix);
const
tween = 0.01;
var
pos, rV: TD3DXVector3;
diff: TD3DXVector3;
begin
pos := D3DXVector3(targ._41, targ._42+5, targ._43); // + 5 look slightly above the object

D3DXVec3Subtract(diff, pos, position);
D3DXVec3Normalize(diff, diff);

rV := D3DXVector3(
arctan2(diff.z, diff.x),
arcsin(diff.y),
0
);

rotation.x := (rV.x * tween) + rotation.x * (1 - tween);
rotation.y := (rV.y * tween) + rotation.y * (1 - tween);
rotation.z := (rV.z * tween) + rotation.z * (1 - tween);
end;

//
// sets the position of the camera somewhere behind the object, either facing or by velocity
//
const
Dist = 20;
MaxDist = 50;
DefHeight = 15;
var
tweenSpeed: TD3DXVector3;
absdist: TD3DXVector3;

pos: TD3DXVector3;
gPoint: TD3DXVector3;
begin
pos := D3DXVector3(m._41, m._42, m._43);

gPoint.y := m._42 + DefHeight;
end else begin
gPoint.y := m._42 + DefHeight;
end;

absdist := D3DXVector3(abs(pos.x-position.x),
abs(pos.y-position.y),
abs(pos.z-position.z)
);

if absdist.x > MaxDist then
tweenSpeed.x := 0.005 * (absdist.x - (MaxDist-1))
else
tweenSpeed.x := 0.005;

tweenSpeed.y := 0.005;

if absdist.z > MaxDist then
tweenSpeed.z := 0.005 * (absdist.z - (MaxDist-1))
else
tweenSpeed.z := 0.005;

position.x := (gPoint.x * tweenSpeed.x) + position.x * (1 - tweenSpeed.x);
position.y := (gPoint.y * tweenSpeed.y) + position.y * (1 - tweenSpeed.y);
position.z := (gPoint.z * tweenSpeed.z) + position.z * (1 - tweenSpeed.z);
end;```
else everything is nice, camera moves very smoothly for the most part, just this problem that is a pain... Any ideas?

Thanks.  Reply With Quote

5. Code:
```  rotation.x := (rV.x * tween) + rotation.x * (1 - tween);
rotation.y := (rV.y * tween) + rotation.y * (1 - tween);
rotation.z := (rV.z * tween) + rotation.z * (1 - tween);```
you are again interpolating the angles, only doing it manually this time instead of using a d3dx function.
ok I suppose I have to explain why that is bad. as (I assume) you know arctan2 gives you an angle between
-Pi and Pi, and you store these angles in your rotation variable. every time you adjust your camera you get a
new angle and you interpolate between the old rotation variable and the new rV variable. the values that you
interpolate are angles (-Pi..Pi). so here's an example of the major issue with angles: what if the old angle is
-0.9 * Pi and the new angle is 0.9 * Pi? the actual angular difference here is only 0.2 * Pi but if you
numerically interpolate between these angles by a step size of 0.5 (for example) you will end up exactly at 0!
while you expect to be at Pi, so your camera will turn exactly in the opposite direction.

as I have said before, you should instead interpolate the direction vectors of the camera. the easiest way to
do that is to store the current direction vector and the new direction vector, interpolate between them and
extract your angles from the result. but since I see that you are trying to only deal with the angles you should
simply convert the rotation variable angles into a vector, interpolate it with the diff vector then extract the
angles from the result.

ok at this point if you need more help I can give you the code that will simply work. but that would be no fun would it   Reply With Quote

6. I understand the issue yes, this is the problem that i have been mainly trying to solve.

What do you mean by "convert the rotation variable angles into a vector" ? the rotation variable is already a vector ?  Reply With Quote

7. Originally Posted by Colin the rotation variable is already a vector ?
no it's not=) you just store the angles it in a vector format that's it. what you need to do is convert these angles into a 3d direction vector.
ok, here's how you do it:
Code:
```var
Dir: TD3DXVector3;
sh, ch, sv, cv: Single;
...
SinCos(rotation.x, sh, ch);
SinCos(rotation.y, sv, cv);
Dir.x := ch * cv; Dir.y := sv; Dir.z := sh * cv;```
then you find the "diff" vector just as you do now.
interpolate between the Dir and diff vector (Dir is the old camera direction, diff is the new camera direction).
so you might want to do something like this:
Code:
```  Dir.x := Dir.x + (diff.x - Dir.x) * tween;
Dir.y := Dir.y + (diff.y - Dir.y) * tween;
Dir.z := Dir.z + (diff.z - Dir.z) * tween;
D3DXVec3Normalize(Dir, Dir);```
and finally convert the Dir vector to rotation angles. I don't know why you are using a 3d vector for rotation
angles, but here it is:
Code:
```  rotation := D3DXVector3(
arctan2(Dir.z, Dir.x),
arcsin(Dir.y),
0
);```
overall this approach should work fine. however, there is still a more consistent and reliable way of spherically interpolating quaternions instead of vectors,
but that is a tale for another time.  Reply With Quote

8. Hello Dan,

Thanks for the code, and for the explanation, it has helped me to understand the idea behind the method. I have updated the procedure with your code and now it works exactly as it should.

Code:
```//
// sets the look at target of the camera
//
procedure TCameraController.setTarget(const targ: TD3DXMatrix);
const
tween = 0.01;
var
pos, diff, Dir: TD3DXVector3;
sh, ch, sv, cv: Extended;
begin
SinCos(rotation.x, sh, ch);
SinCos(rotation.y, sv, cv);
Dir := D3DXVector3(ch * cv, sv, sh * cv);

pos := D3DXVector3(targ._41, targ._42+1, targ._43); // + 1 look slightly above the object

D3DXVec3Subtract(diff, pos, position);
D3DXVec3Normalize(diff, diff);

Dir := D3DXVector3(
Dir.x + (diff.x - Dir.x) * tween,
Dir.y + (diff.y - Dir.y) * tween,
Dir.z + (diff.z - Dir.z) * tween
);
D3DXVec3Normalize(Dir, Dir);

rotation := D3DXVector3(
arctan2(Dir.z, Dir.x),
arcsin(Dir.y),
0
);
end;```
Once I finish adding an Actor class, then maybe i will come back to working on the camera class to look into the quaternion alternatives.

Thanks again  Reply With Quote

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•
Comodo SSL