2
votes

I will try to be very descriptive with this. I'm editing a game right now and the scenario is a 3D area.

I have an initial angle, writen as a direction vector, and another vector which haves different coordinates. As we know, the angle between 2 vectors is given by the formula: Theta = ACos( DotProduct( vec1, vec2 ) / ( VectorLength( vec1 ) * VectorLength( vec2 ) ) )

So let's describe the scenario: I'm currently programming some kind of stationary weapon, a sentry gun, this thing moves slowly his "head", shooting bullets to enemies. That angle rotation thing is my problem.

Let's imagine this: I have my sentry gun on a empty 3D area, and a "enemy" spawns over there. I can currently get the direction vector of my sentry's view angle, and the direction vector between my sentry and the player. Let's guess, using the formula described, his separation angle is 45 degrees. My sentry gun thinks (calls a function) at every 0.1 seconds, and I want to move his head 5 degrees at every thinking function until it reach the the player (ie, both vectors are nearly equal), and that means it will reach the player (if player keeps on its position...) in 0.9 seconds (5 degrees from 45)

How I can move sentry's view angle slowly until it reach a target? In 2D is easily but know I'm fighting with a 3D scenario, and I'm currently lost with this.

Any help would be appreciated, and about coding, I will be grateful with a pseudocode. Thanks! (and sorry for my english)

1
If you can solve this in 2D, you can solve it in 3D by ignoring the 3rd coordinate to use in your 2D formulas, unless it rotates in 3 directions. - Ricardo Souza
To make it slowly rotates you can use some easing formula like: position = currentPosition + (finalPosition - currentPosition) / easingFactor, where easingFactor is an integer that defines the deceleration. - Ricardo Souza
You will want to calculate the vector normal to the plane containing vec1 and vec2 — this defines the axis around which you will rotate the sentry-gun's line-of-sight vector. The formula to perform a rotation (of, say, ) around an arbitrary 3D vector is somewhat complicated, and explained all over the web. For example: here. However, if you don't need the angle to vary between vec1 and vec2, linearly, a fudged solution like @rcdmk's would suffice, linearly-varying coordinates instead of angle. - A. Vidor
It will depend on the angle between both vectors, @rcdmk. Your formula divides it's difference in small pieces, but those pieces would be each one different. Take in consideration that the "enemy" can move, so that's why it's different: it relies on moving "sentry's" head constantly until it reach a target. - PM32
Thanks @this-vidor, gonna take a look - PM32

1 Answers

1
votes

What you need is called SLERP - spherical linear interpolation

Your starting direction vector is p0 there, goal direction is p1, Omega is your Theta, and t parameter varies in range 0..1 with needed step

Delphi example for 2D case (it is easy to control)

var
  p0, p1: TPoint;
  i, xx, yy: Integer;
  omega, InvSinOmega, t, a0, a1: Double;
begin
  P0 := Point(0, 200);
  P1 := Point(200, 0);
  omega := -Pi / 2;
  InvSinOmega := 1.0 / Sin(omega);
  Canvas.Brush.Color := clRed;
  Canvas.Ellipse(120 + P0.X, 120 + P0.Y, 120 + P0.X + 7, 120 + P0.Y + 7);
  Canvas.Ellipse(120 + P1.X, 120 + P1.Y, 120 + P1.X + 7, 120 + P1.Y + 7);

  for i := 1 to 9 do begin
    t := i / 10;

    a0 := sin((1 - t) * omega) * InvSinOmega;
    a1 := sin(t * omega) * InvSinOmega;
    xx := Round(P0.X * a0 + P1.X * a1);
    yy := Round(P0.Y * a0 + P1.Y * a1);

    Canvas.Brush.Color := RGB(25 * i, 25 * i, 25 * i);
    Canvas.Ellipse(120 + xx, 120 + yy, 120 + xx + 9, 120 + yy + 9);
  end;

enter image description here